package com.yuchen.saas.park.service.controller.basic;

import cn.hutool.core.lang.Validator;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.thinkunion.park.service.common.utils.AES;
import com.thinkunion.park.service.common.utils.ReceiptCodeUtil;
import com.yuchen.saas.manage.system.api.entity.NestCustomerManage;
import com.yuchen.saas.manage.system.api.feign.CustomerManageFeignServer;
import com.yuchen.saas.park.api.dto.park.AddSubSiteNumReqDTO;
import com.yuchen.saas.park.api.dto.park.ParkInfoPageQueryDTO;
import com.yuchen.saas.park.api.dto.park.ParkInfoStatusUpdateDTO;
import com.yuchen.saas.park.api.dto.park.VerifyParkReqDTO;
import com.yuchen.saas.park.api.entity.park.PmgBatParkInfo;
import com.yuchen.saas.park.api.entity.park.accredit.SaasParkAccreditInfo;
import com.yuchen.saas.park.api.response.ParkInfoResponse;
import com.yuchen.saas.park.api.vo.park.ParkSpaceStatisticsVO;
import com.yuchen.saas.park.api.vo.park.PmgBatParkTreeVo;
import com.yuchen.saas.park.api.vo.park.PmgParkBuildingInfoVo;
import com.yuchen.saas.park.service.service.PmgBatParkInfoService;
import com.yuchen.saas.park.service.service.accredit.ISaasParkAccreditInfoService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.nest.springwrap.core.log.exception.ServiceException;
import org.nest.springwrap.core.mp.base.BaseEntity;
import org.nest.springwrap.core.mp.support.Condition;
import org.nest.springwrap.core.mp.support.NestPage;
import org.nest.springwrap.core.mp.support.Query;
import org.nest.springwrap.core.secure.ContextUser;
import org.nest.springwrap.core.secure.utils.AuthUtil;
import org.nest.springwrap.core.tool.api.R;
import org.nest.springwrap.core.tool.utils.Func;
import org.nest.springwrap.core.tool.utils.StringUtil;
import org.nest.springwrap.core.tool.utils.WebUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * 园区基本信息
 *
 * @author 黄辉
 * @email 1.0
 * @date 2021-04-26 14:38:35
 */
@Api(tags = "园区基本信息 管理")
@RestController
@RequestMapping("/parkInfo")
public class PmgBatParkInfoController {
    @Autowired
    private PmgBatParkInfoService pmgBatParkInfoService;
    @Resource
    private CustomerManageFeignServer customerManageFeignServer;

    @Resource
    private ISaasParkAccreditInfoService iSaasParkAccreditInfoService;

    /**
     * 详情
     */
    @GetMapping("/detail")
    @ApiOperationSupport(order = 1)
    @ApiOperation(value = "详情", notes = "传入PmgBatParkInfo")
    public R<PmgBatParkInfo> detail(PmgBatParkInfo pmgBatParkInfo) {
        return R.data(pmgBatParkInfoService.parkDetail(pmgBatParkInfoService.getOne(Condition.getQueryWrapper(pmgBatParkInfo))));
    }

    /**
     * 分页
     */
    @GetMapping("/list")
    @ApiOperationSupport(order = 2)
    @ApiOperation(value = "分页", notes = "传入PmgBatParkInfo")
    public R<IPage<PmgBatParkInfo>> list(PmgBatParkInfo pmgBatParkInfo, Query query) {
        return R.data(pmgBatParkInfoService.page(Condition.getPage(query), Condition.getQueryWrapper(pmgBatParkInfo)));
    }

    /**
     * 分页 - 客户端使用
     * @tag tag2
     */
    @GetMapping("/page")
    @ApiOperationSupport(order = 2)
    @ApiOperation(value = "分页获取", notes = "传入ParkInfoPageQueryDTO")
    public R<NestPage<PmgBatParkInfo>> page(ParkInfoPageQueryDTO queryDTO) {
        return R.data(pmgBatParkInfoService.getPage(queryDTO));
    }

    /**
     * 分页 - 运营端使用
     * @tag tag2
     */
    @GetMapping("/operatePage")
    @ApiOperationSupport(order = 2)
    @ApiOperation(value = "分页获取", notes = "传入ParkInfoPageQueryDTO")
    public R<NestPage<PmgBatParkInfo>> operatePage(ParkInfoPageQueryDTO queryDTO) {
        return R.data(pmgBatParkInfoService.operatePage(queryDTO));
    }

    /**
     * 修改状态（启动、停止）
     * @tag tag2
     */
    @PostMapping("/updateStatus")
    @ApiOperationSupport(order = 2)
    @ApiOperation(value = "修改状态（启动、停止）", notes = "ParkInfoStatusUpdateDTO")
    public R<Boolean> updateStatus(@RequestBody @Validated ParkInfoStatusUpdateDTO dto) {
        return R.data(pmgBatParkInfoService.updateStatus(dto));
    }

    /**
     * 确认项目
     * @tag tag2
     */
    @PostMapping("/verifyProject")
    @ApiOperationSupport(order = 2)
    @ApiOperation(value = "确认项目", notes = "确认项目")
    public R verifyProject(@Valid @RequestBody VerifyParkReqDTO reqDTO) {
        return R.status(pmgBatParkInfoService.verifyProject(reqDTO));
    }

    /**
     * 增减场站数量
     */
    @PostMapping("/parkInfo/addSubSiteNum")
    public R addSubSiteNum(@RequestBody AddSubSiteNumReqDTO reqDTO) {
        return R.status(pmgBatParkInfoService.addSubSiteNum(reqDTO));
    }

    /**
     * 分页
     */
    @PostMapping("/getJtlist")
    @ApiOperationSupport(order = 2)
    @ApiOperation(value = "", notes = "传入PmgBatParkInfo")
    public R<List<ParkInfoResponse>> getJtlist(@RequestBody Map<String, String> body) {
        String sign = body.get("sign");
        String signatureContent = AES.getSignatureContent(body);
        String aesSign = AES.encrypt(signatureContent,AES.DEFAULT_DEVICE_SECRET);
        if(aesSign.equals(sign)){
            return R.data(pmgBatParkInfoService.pageJt());
        }
        return R.error("身份验证未通过");
    }

    /**
     * 新增
     * @tag tag2
     */
    @PostMapping("/save")
    @ApiOperationSupport(order = 3)
    @ApiOperation(value = "新增", notes = "传入PmgBatParkInfo")
    public R save(@Valid @RequestBody PmgBatParkInfo pmgBatParkInfo) {
        ContextUser contextUser = AuthUtil.getUser();
        if (Objects.isNull(contextUser)) {
            throw new ServiceException("用户不存在");
        }
        // 判断园区名字和唯一标识是否重复
        LambdaQueryWrapper<PmgBatParkInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.nested(qw -> qw.eq(PmgBatParkInfo::getSMark, pmgBatParkInfo.getSMark())
                .or().eq(PmgBatParkInfo::getParkName, pmgBatParkInfo.getParkName()));
        if (pmgBatParkInfoService.count(wrapper) > 0){
            return R.error("社区名称或社区标识重复！");
        }
        pmgBatParkInfo.setOperator(contextUser.getCustomerManageId());
        if (Func.isNotEmpty(pmgBatParkInfo.getOperator()))
        {
            R<NestCustomerManage> customerManageR = customerManageFeignServer.getDetailById(pmgBatParkInfo.getOperator());
            if (Func.isNotEmpty(customerManageR)&&customerManageR.isSuccess()&&Func.isNotEmpty(customerManageR.getData())){
                pmgBatParkInfo.setOperatorName(customerManageR.getData().getName());
            }
        }
        pmgBatParkInfo.setProjectCode(ReceiptCodeUtil.generateRandomString(16));
        pmgBatParkInfo.setVerifyState("0");
        pmgBatParkInfoService.save(pmgBatParkInfo);
        // 绑定项目授权
        SaasParkAccreditInfo saasParkAccreditInfo = new SaasParkAccreditInfo();
        saasParkAccreditInfo.setProjectId(pmgBatParkInfo.getId());
        saasParkAccreditInfo.setCustomerId(pmgBatParkInfo.getOperator());
        saasParkAccreditInfo.setProjectAddFlag("1");
        saasParkAccreditInfo.setCreateOrgUser(contextUser.getOrgUserId());
        return R.status(iSaasParkAccreditInfoService.save(saasParkAccreditInfo));
    }



    /**
     * 修改
     */
    @PutMapping("/update")
    @ApiOperationSupport(order = 4)
    @ApiOperation(value = "修改", notes = "传入PmgBatParkInfo")
    public R update(@Valid @RequestBody PmgBatParkInfo pmgBatParkInfo) {
        if (!Validator.isMobile(pmgBatParkInfo.getPhone())) {
            return R.error("手机号码格式错误!");
        }
        // 判断园区名字和唯一标识是否重复
        LambdaQueryWrapper<PmgBatParkInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.ne(PmgBatParkInfo::getId, pmgBatParkInfo.getId());
        wrapper.nested(qw -> qw.eq(PmgBatParkInfo::getSMark, pmgBatParkInfo.getSMark())
                .or().eq(PmgBatParkInfo::getParkName, pmgBatParkInfo.getParkName()));
        if (pmgBatParkInfoService.count(wrapper) > 0){
            return R.error("社区名称或社区标识重复！");
        }
        if (Func.isNotEmpty(pmgBatParkInfo.getOperator()))
        {
            R<NestCustomerManage> customerManageR = customerManageFeignServer.getDetailById(pmgBatParkInfo.getOperator());
            if (Func.isNotEmpty(customerManageR)&&customerManageR.isSuccess()&&Func.isNotEmpty(customerManageR.getData())){
                pmgBatParkInfo.setOperatorName(customerManageR.getData().getName());
            }
        }
        return R.status(pmgBatParkInfoService.updateById(pmgBatParkInfo));
    }

    /**
     * 删除
     * @tag tag2
     */
    @DeleteMapping("/remove")
    @ApiOperationSupport(order = 5)
    @ApiOperation(value = "逻辑删除", notes = "传入ids,多个id 逗号隔开")
    public R remove(@ApiParam(value = "主键集合", required = true) @RequestParam String ids) {
        return R.status(pmgBatParkInfoService.deleteIds(ids));
    }

    /**
     * 楼宇销控报表
     */
    @GetMapping("/statement")
    @ApiOperationSupport(order = 6)
    @ApiOperation(value = "楼宇销控报表", notes = "园区id")
    public R statement(@RequestParam Long id) {
        return R.data(pmgBatParkInfoService.statement(id));
    }

    /**
     * 楼宇统计报表
     */
    @GetMapping("/buildingCount")
    @ApiOperationSupport(order = 7)
    @ApiOperation(value = "楼宇统计报表", notes = "楼宇id id为空查询所有楼栋报表")
    public R<List<PmgParkBuildingInfoVo>> buildingCount(@RequestParam(value = "id", required = false) Long id) {
        return R.data(pmgBatParkInfoService.buildingCount(id));
    }

    /**
     * 获取所有园区
     */
//    @GetMapping("/getAll")
    @ApiOperationSupport(order = 2)
    @ApiOperation(value = "获取所有园区（带数据权限）", notes = "传入PmgBatParkInfo")
    public R<List<PmgBatParkInfo>> getAll(ContextUser user,String tenantId,String deptId,String roleId,Integer isAdmin) {
        if(StringUtil.isNotBlank(deptId)){
            return R.data(pmgBatParkInfoService.getAllPark(roleId,isAdmin,deptId,tenantId));
        }else{
            return R.data(pmgBatParkInfoService.getAllPark(user.getRoleId(),user.getIsAdmin(),user.getDeptId(),tenantId));
        }
    }

    /**
     * 获取所有园区
     */
    @GetMapping("/getAll")
    @ApiOperationSupport(order = 3)
    @ApiOperation(value = "获取所有园区（带数据权限v1）", notes = "获取所有园区（带数据权限v1）")
    public R<List<PmgBatParkInfo>> getAllV1(ContextUser user,String tenantId,String deptId,String roleId,Integer isAdmin,Long orgUserId) {
        //todo 兼容  后期更改回来
        if (Func.isNotEmpty(deptId)){
            user.setDeptId(deptId);
        }
        if (Func.isNotEmpty(roleId)){
            user.setRoleId(roleId);
        }
        if (Func.isNotEmpty(isAdmin)){
            user.setIsAdmin(isAdmin);
        }
        if (Func.isNotEmpty(orgUserId)){
            user.setOrgUserId(orgUserId);
        }
        if (Func.isNotEmpty(user.getOrgUserId())){
            List<PmgBatParkInfo> allParkV1 = pmgBatParkInfoService.getAllParkV1(user.getRoleId(),user.getIsAdmin(),user.getDeptId(),tenantId,user.getOrgUserId());
            return R.data(allParkV1);
        }else {
            List<PmgBatParkInfo> allPark = pmgBatParkInfoService.getAllPark(user.getRoleId(),user.getIsAdmin(),user.getDeptId(),tenantId);
            return R.data(Func.isEmpty(allPark)?new ArrayList<>():allPark);
        }
    }

    /**
     * 获取所有园区（根据运营商id（客户id）
     * @tag  V1.0
     * @param operator
     * @return
     */
    @GetMapping("/getAllByOperator")
    @ApiOperationSupport(order = 3)
    @ApiOperation(value = "获取所有园区（根据运营商id（客户id）", notes = "获取所有园区（根据运营商id（客户id）")
    public R<List<PmgBatParkInfo>> getAllByOperator(Long operator) {
        List<PmgBatParkInfo> allParkV1 = pmgBatParkInfoService.getAllByOperator(operator);
        return R.data(allParkV1);
    }

    /**
     * 获取能够开票的园区
     */
    @GetMapping("/getCanInvoiceList")
    @ApiOperationSupport(order = 2)
    @ApiOperation(value = "获取所有园区（带数据权限）", notes = "传入PmgBatParkInfo")
    public R<List<PmgBatParkInfo>> getCanInvoiceList(@ApiParam(name = "customerId", value = "客户ID", required = true) @RequestParam Long customerId, @ApiParam(name = "parkIds", value = "主键集合", required = false) @RequestParam(required = false) String parkIds) {
        return R.data(pmgBatParkInfoService.getCanInvoiceList(customerId, parkIds));
    }

    /**
     * 获取所有园区
     */
    @GetMapping("/getAllVisitor")
    @ApiOperationSupport(order = 2)
    @ApiOperation(value = "获取所有园区(访客调用)", notes = "传入PmgBatParkInfo")
    public R<List<PmgBatParkInfo>> getAllVisitor(String tenantId) {
        LambdaQueryWrapper<PmgBatParkInfo> wrapper = Wrappers.lambdaQuery();
        if(!"000000".equals(tenantId)){
            wrapper.eq(PmgBatParkInfo::getTenantId,tenantId);
        }
        return R.data(pmgBatParkInfoService.list(wrapper.orderByDesc(PmgBatParkInfo::getCreateTime)));
    }

    @GetMapping("/listAll")
    @ApiOperationSupport(order = 2)
    @ApiOperation(value = "获取所有园区不分租户", notes = "获取所有园区不分租户")
    public R<List<PmgBatParkInfo>> listAll(@ApiParam(name = "cityName", value = "城市名称", required = false) @RequestParam(value = "cityName", required = false) String cityName) {
        return R.data(pmgBatParkInfoService.listAll(cityName));
    }

    @GetMapping("/listByApplyId")
    @ApiOperationSupport(order = 2)
    @ApiOperation(value = "按应用获取园区", notes = "按应用获取园区")
    public R<List<PmgBatParkInfo>> listByApplyId() {
        return R.data(pmgBatParkInfoService.listByApplyId(WebUtil.getApplyIdToLong()));
    }


    /**
     * 根据园区id获取楼栋、楼层、房间树形结构
     */
    @GetMapping("/getParkTree")
    @ApiOperationSupport(order = 10)
    @ApiOperation(value = "树形结构", notes = "根据园区id获取楼栋、楼层、房间树形结构")
    public R<PmgBatParkTreeVo> getParkTree(@RequestParam(value = "id", required = false) String id) {
        return R.data(pmgBatParkInfoService.getParkTree(id));
    }

    /**
     * 根据parkId查询园区名称
     */
    @GetMapping("/getParkInfo")
    @ApiOperationSupport(order = 11)
    @ApiOperation(value = "园区信息", notes = "传入parkId")
    public R<PmgBatParkInfo> getParkInfo(@RequestParam Long parkId) {
        return R.data(pmgBatParkInfoService.getById(parkId));
    }

    /**
     * 根据
     * @param tenantId
     * @param scopeValue
     * @return
     */
    @GetMapping("/list/park/scopeValue")
    @ApiOperationSupport(order = 7)
    @ApiOperation(value = "根据租户id和域值查询园区列表", notes = "根据租户id和域值查询园区列表")
    public R<List<ParkInfoResponse>> getParkListByScopeValue(String tenantId, String scopeValue) {
        return R.data(pmgBatParkInfoService.getParkListByScopeValue(tenantId,scopeValue));
    }

    @GetMapping("/list/park/tenant")
    @ApiOperation(value = "获取租户园区", notes = "获取租户园区")
    public R<List<ParkInfoResponse>> getParkList(@RequestParam(required = false) Long tenantId,
                                                 @RequestParam(required = false) Long parkId,
                                                 @RequestParam(required = false)String parkName){
        return R.data(pmgBatParkInfoService.getParkList(tenantId,parkId,parkName));
    }


    //feign调用,
    @GetMapping("/getParkAll2")
    @ApiOperationSupport(order = 2)
    @ApiOperation(value = "获取所有园区")
    public R<List<PmgBatParkInfo>> getParkAll2() {
        LambdaQueryWrapper<PmgBatParkInfo> wrapper = Wrappers.lambdaQuery();
        return R.data(pmgBatParkInfoService.list(wrapper.orderByDesc(PmgBatParkInfo::getCreateTime)));
    }

    /**
     * 根据园区id获取园区信息-园区id不必传
     * @return list
     */
    @GetMapping("/getParkInfoListById")
    @ApiOperationSupport(order = 3)
    @ApiOperation(value = "根据园区id获取园区信息")
    public R<List<PmgBatParkInfo>> getParkInfoListById(@RequestParam(required = false) Long parkId) {
        return R.data(pmgBatParkInfoService.list(new LambdaQueryWrapper<PmgBatParkInfo>()
                .eq(Objects.nonNull(parkId), BaseEntity::getId, parkId)
                .orderByDesc(BaseEntity::getCreateTime)));
    }


    //======================新版接口======================================
    /**
     * 根据组织id查询园区
     */
    @GetMapping("findListByDeptId")
    @ApiOperationSupport(order = 13)
    @ApiOperation(value = "根据组织id查询园区", notes = "根据组织id查询园区")
    public R<List<PmgBatParkInfo>> findListByDeptId(@ApiParam(name = "deptId", value = "组织id", required = true) @RequestParam Long deptId) {
        return R.data(pmgBatParkInfoService.findListByDeptId(deptId));
    }


    /**
     * 根据园区ID列表查询园区名称列表
     * @return 园区名称列表
     */
    @GetMapping("/getParkNamesByIds")
    @ApiOperationSupport(order = 3)
    @ApiOperation(value = "根据园区ID列表查询园区名称列表")
    public R<String> getParkNamesByIds(@RequestParam String parkIds) {
        return R.data(pmgBatParkInfoService.getParkNamesByIds(parkIds));
    }


    @GetMapping("/getParkMap")
    @ApiOperationSupport(order = 3)
    @ApiOperation(value = "根据园区ID列表查询园区名称列表")
    public R<Map<Long, String>> getParkMap(@RequestParam List<Long> parkIds) {
        return R.data(pmgBatParkInfoService.getParkMap(parkIds));
    }

    @PostMapping("/getParkNameMap")
    @ApiOperation(value = "根据园区ID列表查询园区名称")
    public R<Map<Long, String>> getParkNameMap(@RequestBody List<Long> projectIdList) {
        return R.data(pmgBatParkInfoService.getParkNameMap(projectIdList));
    }

    @PostMapping("/getParkInfoMap")
    @ApiOperation(value = "根据园区ID列表查询园区信息")
    public R<Map<Long, PmgBatParkInfo>> getParkInfoMap(@RequestBody List<Long> projectIdList) {
        return R.data(pmgBatParkInfoService.getParkInfoMap(projectIdList));
    }

    @GetMapping("/getSpaceTree")
    @ApiOperationSupport(order = 15)
    @ApiOperation(value = "获取园区（社区/项目）空间树", notes = "获取园区（社区/项目）空间树")
    public R<PmgBatParkInfo> getSpaceTree(@RequestParam Long parkId) {
        PmgBatParkInfo allParkV1 = pmgBatParkInfoService.getSpaceTree(parkId);
        return R.data(allParkV1);
    }
    @GetMapping("/getSpaceStatistics")
    @ApiOperationSupport(order = 16)
    @ApiOperation(value = "获取园区（社区/项目）空间信息", notes = "获取园区（社区/项目）空间信息")
    public R<ParkSpaceStatisticsVO> getSpaceStatistics(@RequestParam Long parkId) {
        return R.data(pmgBatParkInfoService.getSpaceStatistics(parkId));
    }
}
