package com.zhiqiyun.open.mvc.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zhiqiyun.open.annotation.Permission;
import com.zhiqiyun.open.core.enmus.Gender;
import com.zhiqiyun.open.core.enmus.PassengerType;
import com.zhiqiyun.open.core.models.equipment.EquipmentPassenger;
import com.zhiqiyun.open.core.models.equipment.EquipmentPassengerPeople;
import com.zhiqiyun.open.core.models.user.OauthInfo;
import com.zhiqiyun.open.core.service.EquipmentPassengerPeopleService;
import com.zhiqiyun.open.core.service.EquipmentPassengerService;
import com.zhiqiyun.open.core.service.OauthService;
import com.zhiqiyun.open.core.service.SequenceService;
import com.zhiqiyun.open.mvc.Result;
import com.zhiqiyun.open.mvc.params.equipment.QueryEquipmentPassengerParams;
import com.zhiqiyun.open.mvc.params.equipment.SaveEquipmentPassengerParams;
import com.zhiqiyun.open.utils.DateUtil;
import com.zhiqiyun.open.utils.ServletContext;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@RestController
@RequestMapping("/equipment/passenger")
public class EquipmentPassengerController {

	@Autowired
	private EquipmentPassengerService equipmentPassengerService;

	@Autowired
	private EquipmentPassengerPeopleService equipmentPassengerPeopleService;

	@Autowired
	private SequenceService sequenceService;

	@Autowired
	private OauthService oauthService;

	@Permission(value = "equipment.passenger.find", tags = "查询人流采集设备")
	@PostMapping("/findPage")
	public Result findPage(@RequestBody QueryEquipmentPassengerParams params) {

		QueryWrapper<EquipmentPassenger> queryWrapper = new QueryWrapper<>();

		if (StringUtils.isNotBlank(params.getBrief())) {
			queryWrapper.like("brief", params.getBrief());
		}
		if (params.getPlaceBaseInfoId() != null) {
			queryWrapper.eq("place_base_info_id", params.getPlaceBaseInfoId());
		}

		Page<EquipmentPassenger> page = params.getPage();
		page.addOrder(OrderItem.desc("id"));

		Page<EquipmentPassenger> resultData = this.equipmentPassengerService.page(page, queryWrapper);
		QueryWrapper<EquipmentPassengerPeople> passengerWrapper;
		for (EquipmentPassenger equipment : resultData.getRecords()) {
			passengerWrapper = new QueryWrapper<>();
			passengerWrapper.eq("equipment_id", equipment.getId());
			passengerWrapper.eq("passenger_type", PassengerType.IN);
			if (params.getRangeDate() != null) {
				passengerWrapper.between("created_time", params.getRangeDate().getStatDate(), params.getRangeDate().getEndDate());
			}
			Long inPeopleCount = this.equipmentPassengerPeopleService.count(passengerWrapper);


			passengerWrapper = new QueryWrapper<>();
			passengerWrapper.eq("equipment_id", equipment.getId());
			passengerWrapper.eq("passenger_type", PassengerType.OUT);
			if (params.getRangeDate() != null) {
				passengerWrapper.between("created_time", params.getRangeDate().getStatDate(), params.getRangeDate().getEndDate());
			}
			Long outPeopleCount = this.equipmentPassengerPeopleService.count(passengerWrapper);

			equipment.setInPeopleCount(inPeopleCount);
			equipment.setOutPeopleCount(outPeopleCount);
		}

		return Result.instance(Result.Code.SUCCESS).setData(resultData);
	}

	@Permission(value = "equipment.passenger.find", tags = "查询人流采集设备详情")
	@PostMapping("/findDetail")
	public Result findDetail(Long id) {

		Date startTime = DateUtil.current();

		Map<String, Object> dataMap = new HashMap<>();
		QueryWrapper<EquipmentPassengerPeople> wrapper = new QueryWrapper<>();
		wrapper.eq("equipment_id", id);
		wrapper.eq("passenger_type", PassengerType.IN);
		Long inCount = this.equipmentPassengerPeopleService.count(wrapper);

		wrapper = new QueryWrapper<>();
		wrapper.eq("equipment_id", id);
		wrapper.eq("passenger_type", PassengerType.OUT);
		Long outCount = this.equipmentPassengerPeopleService.count(wrapper);


		wrapper = new QueryWrapper<>();
		wrapper.select("gender", "count(id) value");
		wrapper.eq("equipment_id", id);
		wrapper.groupBy("gender");
		List<Map<String, Object>> listGenders = this.equipmentPassengerPeopleService.listMaps(wrapper);
		for (Map<String, Object> genderMap : listGenders) {
			int genderValue = Integer.parseInt(genderMap.get("gender").toString());
			Gender gender = Gender.valueOf(genderValue);
			if (gender != null) {
				genderMap.put("name", gender.getText());
			}
		}


		wrapper = new QueryWrapper<>();
		wrapper.select("from_source name", "count(id) value");
		wrapper.eq("equipment_id", id);
		wrapper.groupBy("from_source");
		wrapper.orderByDesc("value");
		wrapper.last("limit 8");
		List<Map<String, Object>> listFromSource = this.equipmentPassengerPeopleService.listMaps(wrapper);


		wrapper = new QueryWrapper<>();
		wrapper.select("AVG(unix_timestamp(created_time)) t", "passenger_type");
		wrapper.eq("equipment_id", id);
//		wrapper.inSql("face_id", "select face_id from equipment_passenger_people GROUP BY face_id HAVING count(face_id)> 1");
		wrapper.groupBy("passenger_type");
		List<Map<String, Object>> listPassenger = this.equipmentPassengerPeopleService.listMaps(wrapper);

		int avgInTime = 0;
		int avgOutTime = 0;
		for (Map<String, Object> avgMap : listPassenger) {
			int passengerTypeValue = Integer.parseInt(avgMap.get("passenger_type").toString());
			BigDecimal t = new BigDecimal(avgMap.get("t").toString());
			PassengerType passengerType = PassengerType.valueOf(passengerTypeValue);
			if (PassengerType.IN.equals(passengerType)) {
				avgInTime = t.intValue();
			}
			if (PassengerType.OUT.equals(passengerType)) {
				avgOutTime = t.intValue();
			}
		}

		Date endTime = DateUtil.current();

		dataMap.put("inCount", inCount);
		dataMap.put("outCount", outCount);
		dataMap.put("listGenders", listGenders);
		dataMap.put("listFromSource", listFromSource);
		dataMap.put("avgStayTime", avgOutTime - avgInTime);
		dataMap.put("l", endTime.getTime() - startTime.getTime());
		return Result.instance(Result.Code.SUCCESS).setData(dataMap);
	}

	@Permission(value = "equipment.passenger.add", tags = "保存人流采集设备")
	@PostMapping("/save")
	public Result save(@Valid @RequestBody SaveEquipmentPassengerParams params) {

		this.equipmentPassengerService.save(this.buildEntity(this.sequenceService.nextId(), params));

		return Result.instance(Result.Code.MESSAGE_SUCCESS);
	}

	@Permission(value = "equipment.passenger.edit", tags = "编辑人流采集设备")
	@PostMapping("/updateById")
	public Result updateById(Long id, @Valid @RequestBody SaveEquipmentPassengerParams params) {

		this.equipmentPassengerService.updateById(this.buildEntity(id, params));

		return Result.instance(Result.Code.MESSAGE_SUCCESS);
	}


	private EquipmentPassenger buildEntity(Long id, @Valid SaveEquipmentPassengerParams params) {

		EquipmentPassenger entity = new EquipmentPassenger();

		BeanUtils.copyProperties(params, entity);

		OauthInfo oauthInfo = this.oauthService.getAuth(ServletContext.getAccessToken());

		entity.setCreatedTime(DateUtil.current());
		entity.setUpdatedTime(DateUtil.current());
		entity.setCreatedBy(oauthInfo.getId());
		entity.setUpdatedBy(oauthInfo.getId());

		entity.setId(id);
		return entity;
	}

	@Permission(value = "equipment.passenger.delete", tags = "删除人流采集设备")
	@PostMapping("/deleteByIds")
	public Result deleteByIds(@RequestBody List<Long> ids) {
		this.equipmentPassengerService.removeByIds(ids);
		return Result.instance(Result.Code.MESSAGE_SUCCESS);
	}
}
