package com.sptg.estate.biz.controller;

import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.toolkit.IdWorker;
import com.sptg.common.core.beans.ResultBean;
import com.sptg.common.core.beans.ResultEnum;
import com.sptg.common.core.constant.OperationConstant;
import com.sptg.common.core.entity.DispatchTask;
import com.sptg.common.core.util.JsonUtils;
import com.sptg.device.api.feigns.DeviceFeign;
import com.sptg.estate.api.dto.AccessRecordsDto;
import com.sptg.estate.api.dto.BaseUser;
import com.sptg.estate.api.dto.GuestAuthorizeDto;
import com.sptg.estate.api.entity.AccessCard;
import com.sptg.estate.api.entity.AccessRecords;
import com.sptg.estate.api.entity.GuestAuthorize;
import com.sptg.estate.api.feigns.AccessRecordsFeign;
import com.sptg.estate.biz.service.*;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang.StringUtils;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import java.net.URI;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * title: AccessRecordsController
 * package: com.sptg.estate.biz.controller
 * description:出入记录 控制器
 */
@RestController
@RequiredArgsConstructor
public class AccessRecordsController implements AccessRecordsFeign {

    private final BaseUserServiceInterface baseUserServiceInterface;
    private final AccessRecordsServiceInterface accessRecordsServiceInterface;
    private final GuestAuthorizeServiceInterface guestAuthorizeServiceInterface;
    private final DeviceFeign deviceFeign;
    private final static String GUEST_AUTHORIZE_FOR_PASSWORD = "sptg:guest:authorize:password";
    private final RedisTemplate<String, String> redisTemplate;


    /* -------------------------------------------------------------------------------------------------------------- */

    @Override
    @PostMapping(value = "/accessRecords/showAccessRecordsList")
    public ResultBean<Page<AccessRecords>> showAccessRecordsList(@RequestBody AccessRecordsDto accessRecordsDto) {
        return this.accessRecordsServiceInterface.showAccessRecordsList(accessRecordsDto);
    }

    @Override
    @PostMapping(value = "/accessRecords/accessRecordsListByMemberId")
    public ResultBean<Page<AccessRecords>> accessRecordsListByMemberId(@RequestBody AccessRecordsDto accessRecordsDto) {
        return accessRecordsServiceInterface.getListByMemberId(accessRecordsDto);
    }

    private void getUserInfoById(AccessRecords records) {
        Assert.hasText(records.getUserId(), "用户Id不能为空");
        //  通过Id获取用户
        BaseUser baseUser = this.baseUserServiceInterface.selectUserById(records.getUserId());
        //  设置用户信息
        records.setOpenUserId(baseUser.getId());
        records.setOpenUserName(baseUser.getName());
        records.setOpenUserTel(baseUser.getTel());
        records.setIsAdmin(baseUser.getIsAdmin());
        records.setAccessUserType(baseUser.getType());
        records.setUnitName(baseUser.getUnitName());
        records.setRoomName(baseUser.getRoomName());
        if (null != baseUser.getSex()) {
            records.setAccessSex(baseUser.getSex());
        }
    }

    private void getUserInfoByPwd(AccessRecords records) {
        Assert.hasText(records.getAccessCardNo(), "开门密码不能为空");
        //  通过开门密码获取用户信息
        GuestAuthorize authorize = this.guestAuthorizeServiceInterface.getByPasswordAndXqId(records.getAccessCardNo(), records.getResidentialId());
        Assert.notNull(authorize, "开门密码已过期或密码错误");
        records.setOpenUserId(Long.parseLong(authorize.getUserId()));
        records.setOpenUserName(authorize.getUserName());
        records.setOpenUserTel(authorize.getGuestTel());
        records.setIsAdmin(3);
        records.setAccessUserType(authorize.getGuestType());
        records.setUnitId(authorize.getUnitId());
        records.setUnitName(authorize.getUnitName());
        records.setRoomId(authorize.getRoomId());
        records.setRoomName(authorize.getRoomName());
        if (null != records.getAccessSex()) {
            records.setAccessSex(0);
        }
        //如果是密码开门，从缓存中查出该条记录
        GuestAuthorize guestAuthorize = new GuestAuthorizeDto();
        guestAuthorize.setResidentialId(records.getResidentialId());
        guestAuthorize.setPassword(Integer.valueOf(records.getAccessCardNo()));
        GuestAuthorize guest = guestAuthorizeServiceInterface.getGuestAuthorizeByCondition(guestAuthorize);
        if (guest != null) {
            String hashKey = guest.getId().toString();
            //  查询缓存
            HashOperations<String, String, String> hashRedis = this.redisTemplate.opsForHash();
            String s = hashRedis.get(GUEST_AUTHORIZE_FOR_PASSWORD, hashKey);
            if (s != null) {
                GuestAuthorize redisGuest = JsonUtils.jsonToPojo(s, GuestAuthorize.class);
                //拿到缓存的开门次数减1，如果等于0就删除缓存并且数据库的密码状态改成无效
                Integer times = redisGuest.getValidCount() - 1;
                if (times > 0) {
                    redisGuest.setValidCount(times);
                    //  更新缓存
                    hashRedis.put(GUEST_AUTHORIZE_FOR_PASSWORD, hashKey, JsonUtils.objectToJson(redisGuest));
                }
                if (times <= 0) {
                    hashRedis.delete(GUEST_AUTHORIZE_FOR_PASSWORD, hashKey);
                    guest.setEnableType(OperationConstant.ONE);
                    ResultBean<Boolean> bean = guestAuthorizeServiceInterface.updateGuestAuthorizeEnableType(guest);
                    //下发指令
                    DispatchTask dispatchTask = new DispatchTask();
                    dispatchTask.setXqId(authorize.getResidentialId());
                    dispatchTask.setUnitId(authorize.getUnitId());
                    dispatchTask.setData(authorize);
                    Map<String, String> logMap = new HashMap<>();
                    //小区
                    if (!StringUtils.isEmpty(authorize.getResidentialName())) {
                        logMap.put("xqName", authorize.getResidentialName());
                    } else {
                        logMap.put("xqName", null);
                    }
                    //单元
                    if (!StringUtils.isEmpty(authorize.getUnitName())) {
                        logMap.put("unitName", authorize.getUnitName());
                    } else {
                        logMap.put("unitName", null);
                    }
                    //房间
                    if (!StringUtils.isEmpty(authorize.getRoomName())) {
                        logMap.put("roomName", authorize.getRoomName());
                    } else {
                        logMap.put("roomName", null);
                    }
                    //用户名
                    if (!StringUtils.isEmpty(authorize.getUserName())) {
                        logMap.put("userName", authorize.getUserName());
                    } else {
                        logMap.put("userName", null);
                    }
                    //密码
                    if (null != authorize.getPassword()) {
                        logMap.put("password", authorize.getPassword().toString());
                    } else {
                        logMap.put("password", null);
                    }
                    //有效期开始时间
                    SimpleDateFormat format = new SimpleDateFormat();
                    if (null != authorize.getBeginDate()) {
                        logMap.put("beginTime", format.format(authorize.getBeginDate()));
                    } else {
                        logMap.put("beginTime", null);
                    }
                    //有效期结束时间
                    if (null != authorize.getEndDate()) {
                        logMap.put("endTime", format.format(authorize.getEndDate()));
                    } else {
                        logMap.put("endTime", null);
                    }
                    this.deviceFeign.removeOpenDoorPwd(dispatchTask, logMap);
                }
            }
        }
    }

    private void getDHUserInfoByPwd(AccessRecords records) {
        Assert.hasText(records.getAccessCardNo(), "开门密码不能为空");
        //大豪设备不需要访客授权也能开门
        records.setOpenUserId(null);
        records.setOpenUserName("大豪设备用户");
        records.setOpenUserTel(null);
        records.setIsAdmin(3);
        records.setAccessUserType(null);
        if (null != records.getAccessSex()) {
            records.setAccessSex(0);
        }
    }

    private final ServerUserServiceInterface serverUserServiceInterface;
    private final UserServiceInterface userServiceInterface;
    private final AccessCardServiceInterface accessCardServiceInterface;

    private void getUserInfoByCardNo(AccessRecords records) {
        Assert.hasText(records.getAccessCardNo(), "门禁卡号不能为空");
        //  获取卡信息
        AccessCard card = this.accessCardServiceInterface.getByCardNoAndXqId(records.getAccessCardNo(), records.getResidentialId());
        Assert.notNull(card, "卡号不存在");
        BaseUser baseUser = null;
        switch (card.getType()) {
            //  住户开门
            case 0:
                baseUser = this.userServiceInterface.selectById(card.getUserId());
                break;
            //  服务人员开门
            case 4:
                baseUser = this.serverUserServiceInterface.selectById(card.getUserId());
                break;
            //  房间卡号
            case 1:
                records.setIsAdmin(2);
                records.setAccessUserType(1);
                break;
            //  小区或单元卡
            default:
                records.setIsAdmin(1);
                records.setAccessUserType(4);
                break;
        }
        if (null != baseUser) {
            //  设置用户信息
            records.setOpenUserId(baseUser.getId());
            records.setOpenUserTel(baseUser.getTel());
            records.setOpenUserName(baseUser.getName());
            records.setIsAdmin(baseUser.getIsAdmin());
            records.setAccessUserType(baseUser.getType());
            records.setUnitName(baseUser.getUnitName());
            records.setRoomName(baseUser.getRoomName());
            if (null != baseUser.getSex()) {
                records.setAccessSex(baseUser.getSex());
            }
        }
    }

    @Override
    @PostMapping(value = "/accessRecords/addRecords")
    public ResultBean<?> addRecords(@RequestBody AccessRecords records) {
        records.setId(IdWorker.getId());
        records.setCreateDate(new Date());
        this.accessRecordsServiceInterface.insert(records);
        return ResultBean.ok();
    }

    @Override
    @PostMapping(value = "/accessRecords/addAccessRecords")
    public ResultBean<Boolean> addAccessRecords(@RequestBody AccessRecords records) {
        switch (records.getOpenDoorType()) {
            //  人脸开门 || 远程开门
            case 0:
            case 3:
                this.getUserInfoById(records);
                break;
            //  密码开门
            case 1:
                this.getUserInfoByPwd(records);
                break;
            //  刷卡开门
            case 2:
                this.getUserInfoByCardNo(records);
                break;
            default:
                break;
        }
        if(records.getOpenUserId() == null){
            return new ResultBean<>(ResultEnum.SUCCESS, true);
        }
        records.setId(IdWorker.getId());
        records.setCreateDate(new Date());
        boolean result = this.accessRecordsServiceInterface.insert(records);
        return new ResultBean<>(ResultEnum.SUCCESS, result);
    }

    @Override
    @PostMapping(value = "/accessRecords/addDHAccessRecords")
    public ResultBean<Boolean> addDHAccessRecords(@RequestBody AccessRecords records) {
        switch (records.getOpenDoorType()) {
            //  人脸开门 || 远程开门
            case 0:
            case 3:
                this.getUserInfoById(records);
                break;
            //  密码开门
            case 1:
                this.getDHUserInfoByPwd(records);
                break;
            //  刷卡开门
            case 2:
                this.getUserInfoByCardNo(records);
                break;
            default:
                break;
        }
        records.setId(IdWorker.getId());
        records.setCreateDate(new Date());
        boolean result = this.accessRecordsServiceInterface.insert(records);
        return new ResultBean<>(ResultEnum.SUCCESS, result);
    }

    @Override
    @GetMapping(value = "/accessRecords/findAccessRecordsById/{id}")
    public AccessRecords findAccessRecordsById(@PathVariable(value = "id") Long id) {
        return this.accessRecordsServiceInterface.findAccessRecordsById(id);
    }

    @Override
    @PostMapping(value = "/accessRecords/updateAccessRecords")
    public ResultBean<Boolean> updateAccessRecords(@RequestBody AccessRecordsDto accessRecordsDto) {
        return this.accessRecordsServiceInterface.updateAccessRecords(accessRecordsDto);
    }

    @Override
    @PostMapping(value = "/accessRecords/deleteAccessRecords")
    public ResultBean<Boolean> deleteAccessRecords(@RequestBody AccessRecordsDto accessRecordsDto) {
        return this.accessRecordsServiceInterface.deleteAccessRecords(accessRecordsDto);
    }

    @Override
    @PostMapping(value = "/accessRecords/accessCountListForGroupType")
    public List<Map<String, Object>> accessCountListForGroupType(@RequestBody AccessRecordsDto accessRecordsDto) {
        return this.accessRecordsServiceInterface.accessCountListForGroupType(accessRecordsDto);
    }

    @Override
    @PostMapping(value = "/accessRecords/accessCountForOpenWay")
    public Map<String, Object> accessCountForOpenWay(@RequestBody AccessRecordsDto accessRecordsDto) {
        return this.accessRecordsServiceInterface.accessCountForOpenWay(accessRecordsDto);
    }

    @Override
    @PostMapping(value = "/accessRecords/getAccessRecordsCount")
    public Long getAccessRecordsCount(@RequestBody AccessRecordsDto accessRecordsDto) {
        return this.accessRecordsServiceInterface.getAccessRecordsCount(accessRecordsDto);
    }

    @Override
    @PostMapping(value = "/accessRecords/getListByUserId")
    public ResultBean<AccessRecords> getListByUserId(@RequestBody List<Long> userIds) {
        return this.accessRecordsServiceInterface.getListByUserId(userIds);
    }

    @Override
    @PostMapping(value = "/accessRecords/getAccessRecordsCountByDay")
    public Integer getAccessRecordsCountByDay(@RequestBody AccessRecordsDto accessRecordsDto) {
        return this.accessRecordsServiceInterface.getAccessRecordsCountByDay(accessRecordsDto);
    }

    @Override
    @PostMapping(value = "/accessRecords/getDeviceOpenCountList")
    public ResultBean<Page<Map<String, Object>>> getDeviceOpenCountList(@RequestBody AccessRecordsDto accessRecordsDto) {
        Page<Map<String, Object>> deviceOpenCountPage = this.accessRecordsServiceInterface.getDeviceOpenCountList(accessRecordsDto);
        return new ResultBean<>(ResultEnum.SUCCESS, deviceOpenCountPage);
    }

    @Override
    @PostMapping(value = "/accessRecords/getAccessRecordsList")
    public ResultBean<Page<AccessRecords>> getAccessRecordsList(@RequestBody AccessRecordsDto accessRecordsDto) {
        ResultBean<Page<AccessRecords>> accessRecordsList = this.accessRecordsServiceInterface.getAccessRecordsList(accessRecordsDto);
        return accessRecordsList;
    }

    @Override
    @PostMapping(value = "/accessRecords/getListByCondition")
    public List<AccessRecords> getListByCondition(@RequestBody AccessRecordsDto accessRecordsDto) {
        return this.accessRecordsServiceInterface.getListByCondition(accessRecordsDto);
    }

    @Override
    @PostMapping(value = "/accessRecords/updateBatchList")
    public boolean updateBatchList(@RequestBody List<AccessRecords> accessRecordList) {
        return this.accessRecordsServiceInterface.updateBatchById(accessRecordList);
    }


    /**
     * 同步抓拍记录
     *
     * @return
     */
    @GetMapping("accessRecord/sync")
    public int accessRecordSync() throws ParseException {
        String firstDate = "2020-10-22";
        while (firstDate.compareTo("2020-11-04") < 0) {

            System.out.println("同步" + firstDate + "业主抓拍记录开始");
            syncDetail(firstDate, 1);
            System.out.println("同步" + firstDate + "业主抓拍记录结束");
            System.out.println("同步" + firstDate + "家属抓拍记录开始");
            syncDetail(firstDate, 2);
            System.out.println("同步" + firstDate + "家属抓拍记录结束");
            System.out.println("同步" + firstDate + "租客抓拍记录开始");
            syncDetail(firstDate, 3);
            System.out.println("同步" + firstDate + "租客抓拍记录结束");


            DateFormat df = new SimpleDateFormat("yyyy-MM-dd");


            Date dd = df.parse(firstDate);
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(dd);
            calendar.add(Calendar.DAY_OF_MONTH, 1);//加一天
            firstDate = df.format(calendar.getTime());
        }


        return 1;
    }

    public int syncDetail(String date, int type) throws ParseException {

        RestTemplate restTemplate = new RestTemplate();
//		HttpHeaders httpHeaders =
        ResponseEntity responseEntity = null;
        HttpHeaders headers = new HttpHeaders();
        headers.add(HttpHeaders.CONTENT_TYPE, "text/plain");
        headers.add(HttpHeaders.HOST, "qiotapi.qinlinkeji.com");
        headers.add("Cookie", "acw_tc=2760821216040233709218017edfed503c3f299563c0716431831777dc716e");
        Map<String, Object> map = new HashMap<>();
//        {
//            pageNum: 1,
//            pageSize: 10,
//            date: "2020-05-06",
//            type: 1
//        }
        map.put("pageNum", 1);
        map.put("pageSize", 999999999);
        map.put("date", date);
        map.put("type", type);


        HttpEntity<String> requestEntity = new HttpEntity<String>(JsonUtils.objectToJson(map), headers);
        ParameterizedTypeReference<Object> reference = new ParameterizedTypeReference<Object>() {
        };
        String url = "https://qiotapi.qinlinkeji.com/admin/captureRecord/findListPage?sessionId=admin:2c94811075895709017591950cfc00aa";
        URI uri = URI.create(url);
        responseEntity = restTemplate.exchange(uri, HttpMethod.POST, requestEntity, reference);


        Map map1 = (Map) responseEntity.getBody();

        Map map2 = (Map) map1.get("data");
        List<Map> list = (List<Map>) map2.get("list");

        for (int i = 0; i < list.size(); i++) {
            AccessRecords accessRecords = new AccessRecords();
            accessRecords.setAccessAge(Integer.valueOf(list.get(i).get("age").toString()));
            accessRecords.setInstallPath(list.get(i).get("cameraName").toString());
            accessRecords.setResidentialName(list.get(i).get("communityName").toString());
            accessRecords.setOldId(Long.valueOf(list.get(i).get("id").toString()));
            DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            accessRecords.setAccessDate(df.parse(list.get(i).get("recordTime").toString()));
            accessRecords.setAccessSex((Integer) list.get(i).get("sex"));
            accessRecords.setContrast(list.get(i).get("similarity").toString());
            accessRecords.setIsAdmin(2);
            accessRecords.setAccessUserType(type);
            syncPic(accessRecords);

        }


        return 1;
    }

    private void syncPic(AccessRecords accessRecords) {
        RestTemplate restTemplate = new RestTemplate();
//		HttpHeaders httpHeaders =
        ResponseEntity responseEntity = null;
        HttpHeaders headers = new HttpHeaders();
        headers.add(HttpHeaders.CONTENT_TYPE, "text/plain");
        headers.add(HttpHeaders.HOST, "qiotapi.qinlinkeji.com");
        headers.add("Cookie", "acw_tc=2760821216040233709218017edfed503c3f299563c0716431831777dc716e");
        Map<String, Object> map = new HashMap<>();
//        {
//    date: "2020-11-02 23:19:40",
//    id: "520781202119041024",
//type: 1
//}
        map.put("id", accessRecords.getOldId().toString());
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        map.put("date", df.format(accessRecords.getAccessDate()));
        map.put("type", accessRecords.getAccessUserType());


        HttpEntity<String> requestEntity = new HttpEntity<String>(JsonUtils.objectToJson(map), headers);
        ParameterizedTypeReference<Object> reference = new ParameterizedTypeReference<Object>() {
        };
        String url = "https://qiotapi.qinlinkeji.com/admin/captureRecord/getPic?sessionId=admin:2c94811075895709017591950cfc00aa";
        URI uri = URI.create(url);
        responseEntity = restTemplate.exchange(uri, HttpMethod.POST, requestEntity, reference);


        Map map1 = (Map) responseEntity.getBody();

        accessRecords.setSnapshoUri(map1.get("data").toString());


        AccessRecords accessRecords1 = this.accessRecordsServiceInterface.findByOldId(accessRecords.getOldId().toString());
        if(accessRecords1 != null){
            accessRecords.setId(accessRecords1.getId());
            this.accessRecordsServiceInterface.updateAccessRecordsSync(accessRecords);
        }else{
            this.accessRecordsServiceInterface.addAccessRecordsSync(accessRecords);
        }

        System.out.println(accessRecords.getAccessDate()+"抓拍记录："+accessRecords);
    }
}
