package com.chinaweal.aiccs.aiccs.market.controller;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.chinaweal.aiccs.aiccs.business.service.SliceAutoClaimService;
import com.chinaweal.aiccs.aiccs.dict.entity.CascadeTreeNode;
import com.chinaweal.aiccs.aiccs.market.ai.util.GeometryUtil;
import com.chinaweal.aiccs.aiccs.market.entity.AreaSlice;
import com.chinaweal.aiccs.aiccs.market.entity.AreaSlicePolygon;
import com.chinaweal.aiccs.aiccs.market.entity.dto.AreaPoint;
import com.chinaweal.aiccs.aiccs.market.entity.dto.SlicePolygonInfoDto;
import com.chinaweal.aiccs.aiccs.market.service.AreaSlicePolygonService;
import com.chinaweal.aiccs.aiccs.market.service.AreaSliceService;
import com.chinaweal.aiccs.aiccs.market.service.BizOwnerAssignService;
import com.chinaweal.aiccs.common.base.controller.BaseController;
import com.chinaweal.aiccs.common.constant.Constant;
import com.chinaweal.aiccs.common.enums.SliceTypeEnums;
import com.chinaweal.aiccs.common.util.AnalysisUtils;
import com.chinaweal.aiccs.common.util.StringUtils;
import com.chinaweal.aicorg.model.AICUser;
import com.chinaweal.youfool.framework.springboot.exception.custom.BusinessException;
import com.chinaweal.youfool.framework.springboot.mybatis.plus.page.PageRequestDto;
import com.chinaweal.youfool.framework.springboot.rest.RestResult;
import com.chinaweal.youfool.framework.springboot.rest.ResultCode;
import com.chinaweal.youfool.framework.springboot.util.AssertUtils;
import com.chinaweal.youfool.framework.sso.util.SSOUtil;
import com.github.xiaoymin.knife4j.annotations.ApiSort;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Polygon;
import com.vividsolutions.jts.io.ParseException;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 片区设置记录 前端控制器
 * </p>
 *
 * @author <a href="https://blog.lroyia.top">lroyia</a>
 * @since 2021-04-20
 */
@Slf4j
@Api(tags = "片区设置")
@ApiSort(4)
@RestController
@RequestMapping("/areaSlice")
public class AreaSliceController extends BaseController {

    @Autowired
    private AreaSliceService areaSliceService;
    @Autowired
    private SliceAutoClaimService sliceAutoClaimService;
    @Autowired
    private AreaSlicePolygonService areaSlicePolygonService;
    @Autowired
    private BizOwnerAssignService bizOwnerAssignService;

    @ApiOperation("获取片区树")
    @PostMapping("getSliceTreeByUser")
    public RestResult<?> getSliceTreeByUser(HttpServletRequest request){
        AICUser aicUser = SSOUtil.getUser(request);
        String userOrg = aicUser.getRegionID();
        if("440101".equals(userOrg)){
            userOrg = "";
        }
        List<CascadeTreeNode> list = areaSliceService.getListByOrg(userOrg);
        List<CascadeTreeNode> resultList = new ArrayList<>();
        if(CollectionUtils.isNotEmpty(list)){
            resultList = addChild(list);
        }
        return RestResult.ok(resultList);
    }

    private List<CascadeTreeNode> addChild(List<CascadeTreeNode> parentList){

        for (CascadeTreeNode cascadeTreeNode : parentList) {
            List<CascadeTreeNode> childList = areaSliceService.selectByParentId(cascadeTreeNode.getId());
            if(CollectionUtils.isNotEmpty(childList)) {
                cascadeTreeNode.setChildren(childList);
            }
            addChild(childList);
        }
        return parentList;
    }


    /**
     * 获取片区分页
     * @param request   请求
     * @param pageRequestDto    分页参数
     * @return  获取分页结果
     * @author lroyia
     * @since 2021年4月20日 15:53:16
     */
    @PostMapping("page")
    @ApiOperation("获取片区信息分页")
    public RestResult<?> getAreaSlicePage(HttpServletRequest request, @ApiParam("分页参数") @RequestBody PageRequestDto pageRequestDto){
        AssertUtils.isNotNull(pageRequestDto);
        pageRequestDto.checkDefault(1, 10, null);
        Map<String, Object> paramMap = pageRequestDto.getParamMap();
        if(paramMap == null){
            paramMap = new HashMap<>();
        }
        AICUser curUser = getLoginUser(request);
        paramMap.put("orgNumber", curUser.getRegionID());
        IPage<AreaSlice> pageWithOrg = areaSliceService.getPageWithOrg(new Page<>(pageRequestDto.getCurPage(), pageRequestDto.getPageSize()), paramMap);
        List<AreaSlice> records = pageWithOrg.getRecords();
        Map<String, AreaSlice> pageMap = new HashMap<>();
        for (AreaSlice each : records) {
            pageMap.put(each.getSliceId(), each);
        }
        return RestResult.ok(pageWithOrg);
    }

    /**
     * 加入自动认领队列
     * @param sliceId   片区id
     * @return  加入结果
     * @author lroyia
     * @since  2021年5月25日 10:27:58
     */
    @ApiOperation("片区加入自动认领队列")
    @PostMapping("addAutoClaimQueue")
    public RestResult<?> addAutoClaimQueue(@ApiParam("片区id") String sliceId){
        AssertUtils.isNotBlank(sliceId);
        AreaSlice byId = areaSliceService.getById(sliceId);
        if(byId == null){
            return RestResult.error(ResultCode.DATA_NONE);
        }
        if(byId.getState().equals(Constant.FALSE_0_STR)){
            throw new BusinessException("片区已被禁用");
        }
        sliceAutoClaimService.runSlice(sliceId);
        return OK;
    }

    /**
     * 添加片区设置
     * @param request   请求信息
     * @param areaSlice 片区设置信息
     * @return  添加结果
     * @author lroyia
     * @since  2021年4月20日 17:17:39
     */
    @ApiOperation("添加片区设置")
    @PostMapping("add")
    public RestResult<?> addAreaSlice(HttpServletRequest request, @ApiParam("片区设置信息") AreaSlice areaSlice){
        // 参数校验
        AssertUtils.isNotNull(areaSlice);
        AssertUtils.isNotBlank(areaSlice.getSliceAddr(), areaSlice.getSliceName(),
                areaSlice.getSupervisorId(), areaSlice.getState());

        // 解析出街道，作为解析关键字 TODO:这种解析不准确，需要一个更准确的方式做判断设置
        areaSlice.setSliceAddrKey(AnalysisUtils.getStreetNameByAddress(areaSlice.getSliceAddr()));
        // 设置创建人信息
        AICUser curUser = getLoginUser(request);
        String regionID = curUser.getRegionID();
        areaSlice.setCreatorId(curUser.getPrimaryKey())
            .setOrgNumber(regionID);

        // 查询所公共片区
        AreaSlice stationSlice = areaSliceService.getOne(new LambdaQueryWrapper<AreaSlice>().eq(AreaSlice::getSliceType,
                SliceTypeEnums.STATION_PUBLIC.getCode()).eq(AreaSlice::getOrgNumber, regionID));

        // 新增所公共片区
        if (SliceTypeEnums.STATION_PUBLIC.getCode().equals(areaSlice.getSliceType())) {
            if (stationSlice != null) {
                return RestResult.error(ResultCode.BUSINESS_LOGIC_ERROR, "不能同时存在1个以上公共片区");
            }
            // 查询0-父片区
            AreaSlice parentStationSlice = areaSliceService.getOne(new LambdaQueryWrapper<AreaSlice>().eq(AreaSlice::getSliceType,
                    SliceTypeEnums.REGION_PUBLIC.getCode()).eq(AreaSlice::getOrgNumber, regionID.substring(0,6)));

            if (parentStationSlice == null) {
                return RestResult.error(ResultCode.BUSINESS_LOGIC_ERROR, "请先联系管理员添加区公共片区");
            }
            areaSlice.setPSliceId(parentStationSlice.getSliceId());
        } else if (SliceTypeEnums.SPEC_SLICE.getCode().equals(areaSlice.getSliceType())) { // 新增子片区
            if (stationSlice == null) {
                return RestResult.error(ResultCode.BUSINESS_LOGIC_ERROR, "请先添加公共片区");
            }
            areaSlice.setPSliceId(stationSlice.getSliceId());
        } else {
            return RestResult.error(ResultCode.BUSINESS_LOGIC_ERROR, "添加失败，片区类型无效");
        }

        // 保存
        areaSliceService.save(areaSlice);

        // 添加到队列中
//        sliceAutoClaimService.runSlice(areaSlice.getSliceId());
        return OK;
    }

    /**
     * 修改片区设置
     * @param request 请求信息
     * @param areaSlice 片区设置信息
     * @return 修改结果
     * @author lroyia
     * @since 2021年4月20日 17:48:47
     */
    @ApiOperation("修改片区设置")
    @PostMapping("modify")
    public RestResult<?> modifyAreaSlice(HttpServletRequest request, @ApiParam("片区设置信息") AreaSlice areaSlice){
        // 参数校验
        AssertUtils.isNotNull(areaSlice);
        areaSlice.setUpdateTime(LocalDateTime.now());
        areaSlice.setCreatorId(null);
        areaSlice.setCreateTime(null);

        AICUser curUser = getLoginUser(request);
        String regionID = curUser.getRegionID();


        // 查询所公共片区
        AreaSlice stationSlice = areaSliceService.getOne(new LambdaQueryWrapper<AreaSlice>().eq(AreaSlice::getSliceType, SliceTypeEnums.STATION_PUBLIC.getCode()).eq(AreaSlice::getOrgNumber, regionID));

        if (stationSlice == null) {
            return RestResult.error(ResultCode.BUSINESS_LOGIC_ERROR, "请先添加公共片区");
        }

        if ((stationSlice.getSliceId().equals(areaSlice.getSliceId()) && !SliceTypeEnums.STATION_PUBLIC.getCode().equals(areaSlice.getSliceType()))
            || (!stationSlice.getSliceId().equals(areaSlice.getSliceId()) && SliceTypeEnums.STATION_PUBLIC.getCode().equals(areaSlice.getSliceType()))) {
            return RestResult.error(ResultCode.BUSINESS_LOGIC_ERROR, "不能修改片区类型");
        }

        // 解析街道信息
        if(StringUtils.isNotBlank(areaSlice.getSliceAddr())){
            areaSlice.setSliceAddrKey(AnalysisUtils.getStreetNameByAddress(areaSlice.getSliceAddr()));
        }

        // 更新
        areaSliceService.updateById(areaSlice);
        return OK;
    }

    /**
     * 移除片区设置
     * @param request 请求信息
     * @param ids   移除信息id
     * @return  移除结果
     * @author lroyia
     * @since  2021年4月20日 17:59:47
     */
    @ApiOperation("移除片区设置")
    @PostMapping("remove")
    public RestResult<?> removeAreaSlice(HttpServletRequest request, @ApiParam("移除信息id，多个用','隔开") String ids){
        AssertUtils.isNotBlank(ids);

        // 软删除
        areaSliceService.update(new AreaSlice().setIsDeleted(Constant.TRUE_1_STR),
                new LambdaUpdateWrapper<AreaSlice>().in(AreaSlice::getSliceId, ids.split(Constant.COMMA)));

        return OK;
    }

    /**
     * 列出片区清单
     * @param request   请求信息
     * @return  获取结果
     * @author lroyia
     * @since  2021年5月6日 13:47:22
     */
    @GetMapping("list")
    public RestResult<?> areaSliceList(HttpServletRequest request){
        AICUser curUser = getLoginUser(request);
        return RestResult.ok(areaSliceService.list(new LambdaQueryWrapper<AreaSlice>()
                .eq(AreaSlice::getIsDeleted, Constant.FALSE_0_STR)
                .likeRight(AreaSlice::getOrgNumber, curUser.getRegionID())
                .eq(AreaSlice::getState, Constant.TRUE_1_STR).orderByAsc(AreaSlice::getSliceType, AreaSlice::getSliceId)
                ));
    }

    /**
     * 围点信息保存
     * @param polygonInfo   围点信息
     * @return  围点结果
     * @author lroyia
     * @since 2021年11月28日 19:19:40
     */
    @PostMapping("savePolygon")
    public RestResult<?> savePolygon(@RequestBody SlicePolygonInfoDto polygonInfo){
        List<String> pointList = polygonInfo.getPointList();
        // 形成闭合点集
        pointList.add(pointList.get(0));
        String wkt = "POLYGON((" + pointList.stream().map(each -> each.replace(Constant.COMMA, " "))
                .collect(Collectors.joining(Constant.COMMA))+"))";
        String polygonId = areaSlicePolygonService.savePolygonByWKT(wkt, polygonInfo.getSliceId());
        return RestResult.ok(polygonId);
    }

    /**
     * 查询片区多边形围点信息
     * @param sliceId   片区id
     * @return  查询结果
     * @author lroyia
     * @since  2021年11月29日 14:36:24
     */
    @ApiOperation("获取片区多边形围点信息")
    @GetMapping("getSlicePolygon")
    public RestResult<?> getSlicePolygon(@ApiParam("片区id") @RequestParam String sliceId){
        List<AreaSlicePolygon> list = areaSlicePolygonService.list(new LambdaQueryWrapper<AreaSlicePolygon>().eq(AreaSlicePolygon::getSliceId, sliceId));
        if(CollectionUtils.isEmpty(list)){
            return RestResult.ok(list);
        }
        // 转换结果
        List<List<AreaPoint>> result = new ArrayList<>();
        for (AreaSlicePolygon each : list) {
            try {
                Polygon polygon = (Polygon) GeometryUtil.readWKB(each.getPolygonData());
                Coordinate[] coordinates = polygon.getCoordinates();
                List<AreaPoint> pointList = new ArrayList<>();
                result.add(pointList);
                for (int i = 0; i < coordinates.length - 1; i++) { // -1去掉顺换的尾点
                    pointList.add(new AreaPoint(coordinates[i].x, coordinates[i].y));
                }
            } catch (ParseException e) {
                log.error("读取多边形空间信息失败", e);
            }
        }
        return RestResult.ok(result);
    }

    /**
     * 获取当前用户对该主体的可认领片区
     * @param pripid    主体pripid
     * @param request   请求
     * @return  获取结果
     * @author lroyia
     * @since  2021年12月29日 14:28:06
     */
    @ApiOperation("获取当前用户对该主体的可认领片区")
    @GetMapping("getAssignableSliceList/{pripid}")
    public RestResult<?> getAssignableSlice(@PathVariable @ApiParam("主体pripid") String pripid,
                                            HttpServletRequest request){
        AICUser loginUser = getLoginUser(request);
        return RestResult.ok(bizOwnerAssignService.getAssignableSlice(pripid, loginUser));
    }

    /**
     * 获取当前用户对该主体的可认领片区
     * @author ymc
     * @date 2022年4月2日 16:59
     * @return
     */
    @ApiOperation("获取当前用户对该主体的可认领片区")
    @GetMapping("/getAssignableSliceListNew")
    public RestResult<?> getAssignableSliceNew(String sliceType){
        AICUser aicUser = SSOUtil.getUser();
        return RestResult.ok(areaSliceService.lambdaQuery().likeRight(SliceTypeEnums.STATION_PUBLIC.getCode().equals(sliceType), AreaSlice::getOrgNumber, aicUser.getRegionID())
                .eq(AreaSlice::getState, "1")
                .eq(AreaSlice::getIsDeleted, "0")
                .eq(AreaSlice::getSliceType, sliceType)
                .list());
    }


    @GetMapping("test")
    public RestResult<?> test(){
        return RestResult.ok(areaSlicePolygonService.getById("xcc"));
    }

}

