/*
 *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the dreamlu.net developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: Chill 庄骞 (smallchill@163.com)
 */
package org.springblade.attence.rule.controller;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.BetweenFormater;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.AllArgsConstructor;

import javax.validation.Valid;

import org.springblade.attence.location.entity.Location;
import org.springblade.attence.location.service.ILocationService;
import org.springblade.attence.rule.dto.QueryDataDTO;
import org.springblade.attence.rule.vo.AttenceRuleVo;
import org.springblade.attence.rule.vo.WxAppDataVo;
import org.springblade.attence.ruleperson.entity.RulePerson;
import org.springblade.attence.ruleperson.service.IRulePersonService;
import org.springblade.attence.rulespectime.entity.RuleSpecTime;
import org.springblade.attence.rulespectime.service.IRuleSpecTimeService;
import org.springblade.attence.ruletime.entity.RuleTime;
import org.springblade.attence.ruletime.service.IRuleTimeService;
import org.springblade.attence.wifi.entity.Wifi;
import org.springblade.attence.wifi.service.IWifiService;
import org.springblade.common.Constants;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.BeanUtil;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.RequestParam;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springblade.attence.rule.entity.Rule;
import org.springblade.attence.rule.vo.RuleVO;
import org.springblade.attence.rule.wrapper.RuleWrapper;
import org.springblade.attence.rule.service.IRuleService;
import org.springblade.core.boot.ctrl.BladeController;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.util.*;

/**
 * 控制器
 *
 * @author BladeX
 * @since 2021-04-12
 */
@RestController
@AllArgsConstructor
@RequestMapping("attence/rule")
@Api(value = "打卡规则接口", tags = "打卡规则接口")
public class RuleController extends BladeController {

	private final IRuleService ruleService;
	private final IRulePersonService rulePersonService;
	private final ILocationService locationService;
	private final IWifiService wifiService;
	private final IRuleTimeService ruleTimeService;
	private final IRuleSpecTimeService ruleSpecTimeService;

	/**
	 * 详情
	 */
	@GetMapping("/detail")
	@ApiOperationSupport(order = 1)
	@ApiOperation(value = "详情", notes = "传入rule")
	public R<AttenceRuleVo> detail(Rule rule) {
		Rule byId = this.ruleService.getById(rule.getId());
		AttenceRuleVo attenceRuleVo = new AttenceRuleVo();
		BeanUtil.copyProperties(byId, attenceRuleVo);
		//打卡人员
		List<RulePerson> rulePersons = this.rulePersonService.list(Condition.getQueryWrapper(new RulePerson()).lambda().eq(RulePerson::getRuleId, rule.getId()));
		attenceRuleVo.setRulePersons(rulePersons);
		//打卡位置
		List<Location> locations = this.locationService.list(Condition.getQueryWrapper(new Location()).lambda().eq(Location::getRuleId, rule.getId()));
		attenceRuleVo.setLocations(locations);
		//打卡wifi
		List<Wifi> wifiList = this.wifiService.list(Condition.getQueryWrapper(new Wifi()).lambda().eq(Wifi::getRuleId, rule.getId()));
		attenceRuleVo.setWifiList(wifiList);
		//打卡时间
		List<RuleTime> ruleTimes = this.ruleTimeService.list(Condition.getQueryWrapper(new RuleTime()).lambda().eq(RuleTime::getRuleId, rule.getId()));
		attenceRuleVo.setRuleTimes(ruleTimes);
		//特殊打卡日期
		List<RuleSpecTime> ruleSpecTimes = this.ruleSpecTimeService.list(Condition.getQueryWrapper(new RuleSpecTime()).lambda().eq(RuleSpecTime::getRuleId, rule.getId()));
		attenceRuleVo.setRuleSpecTimes(ruleSpecTimes);
		return R.data(attenceRuleVo);
	}

	/**
	 * 分页
	 */
	@GetMapping("/list")
	@ApiOperationSupport(order = 2)
	@ApiOperation(value = "分页", notes = "传入rule")
	public R<List<RuleVO>> list(Rule rule) {
		List<Rule> list = ruleService.list(Condition.getQueryWrapper(rule));
		return R.data(RuleWrapper.build().listVO(list));
	}


	/**
	 * 自定义分页
	 */
	@GetMapping("/page")
	@ApiOperationSupport(order = 3)
	@ApiOperation(value = "分页", notes = "传入rule")
	public R<IPage<RuleVO>> page(RuleVO rule, Query query) {
		IPage<RuleVO> pages = ruleService.selectRulePage(Condition.getPage(query), rule);
		return R.data(pages);
	}

	/**
	 * 新增
	 */
	@PostMapping("/save")
	@ApiOperationSupport(order = 4)
	@ApiOperation(value = "新增", notes = "传入AttenceRuleVo")
	public R save(@Valid @RequestBody AttenceRuleVo attenceRuleVo) {
		//保存规则
		Rule before = new Rule();
		BeanUtil.copyProperties(attenceRuleVo, before);
		if (this.ruleService.save(before)) {
			//保存打卡人员
			List<RulePerson> rulePersons = attenceRuleVo.getRulePersons();
			rulePersons.forEach(rulePerson -> {
				rulePerson.setRuleId(before.getId());
				rulePerson.setPersonType(attenceRuleVo.getOwnerType());
			});
			this.rulePersonService.saveBatch(rulePersons);
			//保存打卡地点
			List<Location> locations = attenceRuleVo.getLocations();
			locations.forEach(location -> {
				location.setRuleId(before.getId());
			});
			this.locationService.saveBatch(locations);
			//保存wifi
			List<Wifi> wifiList = attenceRuleVo.getWifiList();
			wifiList.forEach(wifi -> {
				wifi.setRuleId(before.getId());
			});
			this.wifiService.saveBatch(wifiList);
			//保存打卡时间
			List<RuleTime> ruleTimes = attenceRuleVo.getRuleTimes();
			ruleTimes.forEach(ruleTime -> {
				ruleTime.setRuleId(before.getId());
			});
			this.ruleTimeService.saveBatch(ruleTimes);
			//保存特殊打卡日期
			List<RuleSpecTime> ruleSpecTimes = attenceRuleVo.getRuleSpecTimes();
			ruleSpecTimes.forEach(ruleSpecTime -> {
				ruleSpecTime.setRuleId(before.getId());
			});
			this.ruleSpecTimeService.saveBatch(ruleSpecTimes);
			return R.data(true);
		} else {
			return R.data(false);
		}
	}

	/**
	 * 修改
	 */
	@PostMapping("/update")
	@ApiOperationSupport(order = 5)
	@ApiOperation(value = "修改", notes = "传入rule")
	@Transactional
	public R update(@Valid @RequestBody AttenceRuleVo attenceRuleVo) {
		Rule rule = new Rule();
		BeanUtil.copyProperties(attenceRuleVo,rule);
		if (this.ruleService.updateById(rule)) {
			//打卡人员，先删除原有数据，再插入新数据
			this.rulePersonService.getBaseMapper().delete(Condition.getQueryWrapper(new RulePerson()).lambda().eq(RulePerson::getRuleId, rule.getId()));
			List<RulePerson> rulePersons = attenceRuleVo.getRulePersons();
			rulePersons.forEach(rulePerson -> {
				rulePerson.setId(null);
				rulePerson.setRuleId(rule.getId());
				rulePerson.setPersonType(attenceRuleVo.getOwnerType());
			});
			this.rulePersonService.saveBatch(rulePersons);
			//打卡位置
			List<Location> locations = attenceRuleVo.getLocations();
			locations.removeIf(location -> location.getId() != null);
			locations.forEach(location -> location.setRuleId(rule.getId()));
			this.locationService.saveBatch(locations);
			//打卡wifi
			List<Wifi> wifiList = attenceRuleVo.getWifiList();
			wifiList.removeIf(wifi -> wifi.getId() != null);
			wifiList.forEach(wifi -> wifi.setRuleId(rule.getId()));
			this.wifiService.saveBatch(wifiList);
			//打卡时间
			List<RuleTime> ruleTimes = attenceRuleVo.getRuleTimes();
			ruleTimes.forEach(ruleTime -> ruleTime.setRuleId(rule.getId()));
			this.ruleTimeService.saveOrUpdateBatch(ruleTimes);
			//特殊打卡日期
			List<RuleSpecTime> ruleSpecTimes = attenceRuleVo.getRuleSpecTimes();
			ruleSpecTimes.removeIf(ruleSpecTime -> ruleSpecTime.getId() != null);
			ruleSpecTimes.forEach(ruleSpecTime -> ruleSpecTime.setRuleId(rule.getId()));
			this.ruleSpecTimeService.saveBatch(ruleSpecTimes);
			return R.data(true);
		} else {
			return R.data(false);
		}
	}

	/**
	 * 新增或修改
	 */
	@PostMapping("/submit")
	@ApiOperationSupport(order = 6)
	@ApiOperation(value = "新增或修改", notes = "传入rule")
	public R submit(@Valid @RequestBody Rule rule) {
		return R.status(ruleService.saveOrUpdate(rule));
	}


	/**
	 * 删除
	 */
	@PostMapping("/remove")
	@ApiOperationSupport(order = 7)
	@ApiOperation(value = "逻辑删除", notes = "传入id")
	@Transactional
	public R remove(@ApiParam(value = "id", required = true) @RequestParam Long id) {
		this.rulePersonService.getBaseMapper().delete(Condition.getQueryWrapper(new RulePerson()).lambda().eq(RulePerson::getRuleId,id));
		this.locationService.remove(Condition.getQueryWrapper(new Location()).lambda().eq(Location::getRuleId,id));
		this.wifiService.remove(Condition.getQueryWrapper(new Wifi()).lambda().eq(Wifi::getRuleId,id));
		this.ruleTimeService.remove(Condition.getQueryWrapper(new RuleTime()).lambda().eq(RuleTime::getRuleId,id));
		this.ruleSpecTimeService.remove(Condition.getQueryWrapper(new RuleSpecTime()).lambda().eq(RuleSpecTime::getRuleId,id));
		return R.status(this.ruleService.removeById(id));
	}

	/**
	 * 获取必要的数据
	 */
	@PostMapping("/getNecessaryData")
	@ApiOperationSupport(order = 8)
	@ApiOperation(value = "getNecessaryData", notes = "传入rule")
	public R getNecessaryData(@RequestBody QueryDataDTO queryDataDTO) {
		Assert.notNull(queryDataDTO.getLongitude(), "经度不能为空");
		Assert.notNull(queryDataDTO.getLatitude(), "纬度不能为空");
		Assert.notNull(queryDataDTO.getPersonId(), "员工id不能为空");
		Assert.notNull(queryDataDTO.getPersonType(), "员工类型不能为空");
		Assert.notNull(queryDataDTO.getType(), "打卡人员类型不能为空");
		Assert.notNull(queryDataDTO.getWifiMac(), "wifiMac码不能为空");

		WxAppDataVo necessaryData = ruleService.getNecessaryData(queryDataDTO);

		return R.data(necessaryData);
	}
}
