package com.gree.mall.manager.controller.workerorder;

import cn.hutool.core.lang.TypeReference;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.gree.mall.manager.annotation.ZfireList;
import com.gree.mall.manager.bean.admin.AdminUserCom;
import com.gree.mall.manager.bean.listvo.param.WorkOrderZfireParam;
import com.gree.mall.manager.bean.listvo.workorder.OrderBase2VO;
import com.gree.mall.manager.bean.listvo.workorder.OrderBaseVO;
import com.gree.mall.manager.bean.workorder.OrderAddBean2DTO;
import com.gree.mall.manager.bean.workorder.OrderAddBeanDTO;
import com.gree.mall.manager.bean.workorder.OrderSettleDetailBean;
import com.gree.mall.manager.constant.Constant;
import com.gree.mall.manager.enums.workorder.OrderFlagEnum;
import com.gree.mall.manager.exception.RemoteServiceException;
import com.gree.mall.manager.helper.ResponseHelper;
import com.gree.mall.manager.logic.common.CommonLogic;
import com.gree.mall.manager.logic.workorder.OrderBaseExcelLogic;
import com.gree.mall.manager.logic.workorder.OrderBaseLogic;
import com.gree.mall.manager.logic.workorder.OrderLogLogic;
import com.gree.mall.manager.plus.entity.PgOrderBase;
import com.gree.mall.manager.plus.entity.PgOrderOperatorLog;
import com.gree.mall.manager.plus.entity.PgOrderProduct;
import com.gree.mall.manager.plus.entity.PgOrderWorker;
import com.gree.mall.manager.utils.excel.ExcelUtils;
import com.gree.mall.manager.zfire.bean.ZfireParamBean;
import com.gree.mall.manager.zfire.util.FieldUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.integration.redis.util.RedisLockRegistry;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;

@RequiredArgsConstructor
@Slf4j
@RestController
@Api(value = "工单API", tags = {"工单API"})
@RequestMapping(value = "/order/base", produces = "application/json; charset=utf-8")
public class OrderBaseController {

    private final OrderBaseLogic orderBaseLogic;
    private final OrderBaseExcelLogic orderBaseExcelLogic;
    private final OrderLogLogic orderLogLogic;
    private final RedisLockRegistry redisLockRegistry;
    private final CommonLogic commonLogic;

    @ZfireList
    @PostMapping("/list")
    @ApiOperation(value = "列表")
    public ResponseHelper<Page<OrderBaseVO>> list(
            @RequestBody WorkOrderZfireParam workOrderZfireParam
    ) {
        IPage<OrderBaseVO> orderBaseVOIPage = orderBaseLogic.orderBaseList(workOrderZfireParam);
        return ResponseHelper.success(orderBaseVOIPage, new TypeReference<OrderBaseVO>() {});
    }

    @PostMapping("/list/export")
    @ApiOperation(value = "导出")
    public void listExport(@RequestBody WorkOrderZfireParam zfireParamBean, HttpServletRequest request, HttpServletResponse response) throws Exception {
        //1.组装查询条件
        ZfireParamBean zfireParam = FieldUtils.supplyParam(zfireParamBean);
        //2.查询要导出的内容
        IPage<OrderBaseVO> page = orderBaseLogic.orderBaseList(zfireParamBean);
        //3.导出
        FieldUtils.exportData(page.getRecords(), zfireParam.getExportFields(), request, response);
    }

    @PostMapping("/list/gene")
    @ApiOperation("普通的工单列表")
    public ResponseHelper<Page<PgOrderBase>> listGene(
            @ApiParam(value = "用户id") @RequestParam String userId,
            @RequestParam Integer pageNum,
            @RequestParam Integer pageSize
    ){
        IPage<PgOrderBase> pgOrderBaseIPage = orderBaseLogic.list2(userId, pageNum, pageSize);
        return ResponseHelper.success(pgOrderBaseIPage);
    }



    @PostMapping("/status/count")
    @ApiOperation(value = "按工单状态统计")
    public ResponseHelper<List<Map<String,Object>>> countStatus(
            @RequestParam(required = false) String startTime,
            @RequestParam(required = false) String endTime,
            @RequestParam(required = false) String orderSmallType,
            @RequestParam(required = false) String orderSmallTypeText
    ) {
        List<Map<String, Object>> maps = orderBaseLogic.countStatus(startTime,endTime,orderSmallType,orderSmallTypeText);
        return ResponseHelper.success(maps);
    }

    @PostMapping("/save")
    @ApiOperation(value = "保存工单(传id则编辑)")
    public ResponseHelper<String> save(@Valid @RequestBody OrderAddBeanDTO orderAddBeanDTO){
        String orderBaseId = orderBaseLogic.saveOrder(orderAddBeanDTO);
        return ResponseHelper.success(orderBaseId);
    }


    @PostMapping("/update")
    @ApiOperation(value = "修改工单")
    public ResponseHelper update(@Valid @RequestBody PgOrderBase pgOrderBase){
         orderBaseLogic.update(pgOrderBase);
        return ResponseHelper.success();
    }


    @PostMapping("/save2")
    @ApiOperation(value = "保存工单(小程序端用)")
    public ResponseHelper save2(@Valid @RequestBody OrderAddBean2DTO orderAddBean2DTO){
        orderBaseLogic.add(orderAddBean2DTO);
        return ResponseHelper.success();
    }

    @PostMapping("/cancel")
    @ApiOperation(value = "取消工单")
    public ResponseHelper cancel(@RequestParam String orderBaseId) throws InterruptedException {
        Lock obtain = redisLockRegistry.obtain(Constant.RedisPrefix.LOCK_ORDER + orderBaseId);
        if(!obtain.tryLock(10,TimeUnit.SECONDS)){
            throw new RemoteServiceException("系统繁忙,请稍后再试");
        }
        try {
            orderBaseLogic.cancel(orderBaseId);
        }finally {
            obtain.unlock();
        }

        return ResponseHelper.success();
    }

    @PostMapping("/active")
    @ApiOperation(value = "激活工单")
    public ResponseHelper active(@RequestParam String orderBaseId) throws InterruptedException {
        Lock obtain = redisLockRegistry.obtain(Constant.RedisPrefix.LOCK_ORDER + orderBaseId);
        if(!obtain.tryLock(10,TimeUnit.SECONDS)){
            throw new RemoteServiceException("系统繁忙,请稍后再试");
        }
        try {
            orderBaseLogic.active(orderBaseId);
        }finally {
            obtain.unlock();
        }

        return ResponseHelper.success();
    }



    @PostMapping("/reject")
    @ApiOperation(value = "驳回工单")
    public ResponseHelper reject(@RequestParam String orderBaseId) throws InterruptedException {
        Lock obtain = redisLockRegistry.obtain(Constant.RedisPrefix.LOCK_ORDER + orderBaseId);
        if(!obtain.tryLock(10,TimeUnit.SECONDS)){
            throw new RemoteServiceException("系统繁忙,请稍后再试");
        }
        try{
            orderBaseLogic.reject(orderBaseId);
        }finally {
            obtain.unlock();
        }
        return ResponseHelper.success();
    }


    @PostMapping("/detail")
    @ApiOperation(value = "工单-详情")
    public ResponseHelper<OrderAddBeanDTO> detail(@RequestParam String orderBaseId){
        OrderAddBeanDTO detail = orderBaseLogic.detail(orderBaseId);
        return ResponseHelper.success(detail);
    }

    @PostMapping("/worker/list")
    @ApiOperation(value = "工单师傅-列表")
    public ResponseHelper<List<PgOrderWorker>> workerList(@RequestParam String orderBaseId){
        List<PgOrderWorker> orderWorkers = orderBaseLogic.orderWorkerList(orderBaseId);
        return ResponseHelper.success(orderWorkers);
    }


    @PostMapping("/product/list")
    @ApiOperation(value = "服务单-工单机型列表")
    public ResponseHelper<List<PgOrderProduct>> productList(@RequestParam String orderBaseId) {
        List<PgOrderProduct> orderProducts = orderBaseLogic.listOrderProduct(orderBaseId);
        return ResponseHelper.success(orderProducts);
    }

    @PostMapping("/product/add")
    @ApiOperation(value = "服务单-新增工单机型")
    public ResponseHelper<List<PgOrderProduct>> addProduct(@RequestBody PgOrderProduct orderProduct) {
        List<PgOrderProduct> orderProducts = orderBaseLogic.addOrderProduct(orderProduct);
        return ResponseHelper.success(orderProducts);
    }

    @PostMapping("/product/update")
    @ApiOperation(value = "服务单-修改工单机型")
    public ResponseHelper<List<PgOrderProduct>> updateProduct(@RequestBody PgOrderProduct orderProduct) {
        List<PgOrderProduct> orderProducts = orderBaseLogic.updateOrderProduct(orderProduct);
        return ResponseHelper.success(orderProducts);
    }

    @PostMapping("/product/delete")
    @ApiOperation(value = "服务单-删除工单机型")
    public ResponseHelper<List<PgOrderProduct>> deleteProduct(@RequestParam String orderProductId) {
        List<PgOrderProduct> orderProducts = orderBaseLogic.deleteOrderProduct(orderProductId);
        return ResponseHelper.success(orderProducts);
    }


    @PostMapping("/flag")
    @ApiOperation(value = "工单-打标记(加急/取消加急,异常/取消异常 等等..)")
    public ResponseHelper flag(
            @ApiParam(value = "工单号",required = true) @RequestParam String orderBaseId,
            @ApiParam(value = "标记类型 JIA_JI=加急 YI_CHANGE=异常") @RequestParam OrderFlagEnum orderFlagEnum,
            @ApiParam(value = "打标记 true=打 false=取消",required = true) @RequestParam Boolean flag
    ){
        orderBaseLogic.jiaji(orderBaseId,orderFlagEnum,flag);
        return ResponseHelper.success();
    }


    @PostMapping("/log/add")
    @ApiOperation(value = "过程反馈-添加")
    public ResponseHelper addOrderOperator(
            @RequestBody PgOrderOperatorLog pgOrderOperatorLog
    ) {
        orderLogLogic.addLog(pgOrderOperatorLog);
        return ResponseHelper.success();
    }


    @PostMapping("/log/list")
    @ApiOperation(value = "工单操作明细-列表")
    public ResponseHelper<List<PgOrderOperatorLog>> orderOperatorLog(
            @RequestParam String orderBaseId
    ) {
        List<PgOrderOperatorLog> pgOrderOperatorLogs = orderLogLogic.operatorLogList(orderBaseId);
        return ResponseHelper.success(pgOrderOperatorLogs);
    }

    @ZfireList
    @PostMapping("/list2")
    @ApiOperation(value = "已完工待结算-列表")
    public ResponseHelper<Page<OrderBase2VO>> list2(
            @RequestBody WorkOrderZfireParam workOrderZfireParam
    ) {
        IPage<OrderBase2VO> orderBaseVOIPage = orderBaseLogic.orderBaseList2(workOrderZfireParam);
        return ResponseHelper.success(orderBaseVOIPage, new TypeReference<OrderBase2VO>() {});
    }

    @PostMapping("/settle/norm/detail2")
    @ApiOperation(value = "已完工待结算-详情")
    public ResponseHelper<List<OrderSettleDetailBean>> settleNormDetail2(
            @ApiParam(value = "产品id", required = true) @RequestParam String orderProductId,
            @ApiParam(value = "工单id", required = true) @RequestParam String id
    ) {
        OrderSettleDetailBean bean = orderLogLogic.settleNormDetail2(orderProductId, id);
        return ResponseHelper.success(bean);
    }

    @PostMapping("/status/count2")
    @ApiOperation(value = "已完工待结算-按工单状态统计")
    public ResponseHelper<List<Map<String,Object>>> countStatus2(
            @RequestParam(required = false) String orderSmallTypeText
    ) {
        List<Map<String, Object>> maps = orderBaseLogic.countStatus2(orderSmallTypeText);
        return ResponseHelper.success(maps);
    }

    @PostMapping("/settle/norm/detail")
    @ApiOperation(value = "费用结算-详情")
    public ResponseHelper<List<OrderSettleDetailBean>> settleNormDetail(
            @ApiParam(value = "id", required = true) @RequestParam String id
    ) {
        OrderSettleDetailBean bean = orderLogLogic.settleNormDetail(id);
        return ResponseHelper.success(bean);
    }

    @PostMapping("/settle/norm/confirm")
    @ApiOperation(value = "费用结算-确认结算")
    public ResponseHelper settleNormConfirm(
            @ApiParam(value = "详情bean", required = true) @RequestBody OrderSettleDetailBean bean
    ) throws Exception {
        AdminUserCom adminUser = commonLogic.getAdminUser();
        String lockKey = "";
        if (Objects.nonNull(adminUser.getAdminCompanyWechat())) {
            lockKey = adminUser.getAdminCompanyWechat().getCompanyWechatId();
        }
        Lock obtain = redisLockRegistry.obtain(Constant.RedisPrefix.LOCK_ORDER + ":" + lockKey);
//        Lock obtain = redisLockRegistry.obtain(Constant.RedisPrefix.LOCK_ORDER + ":" + bean.getId());
        try {
            if (obtain.tryLock(5, TimeUnit.SECONDS)) {
                orderLogLogic.settleNormConfirm(bean);
            }
        } catch(Exception e) {
            log.error("【确认结算处理】失败", e);
            throw e;
        } finally {
            obtain.unlock();
        }

        return ResponseHelper.success();
    }

    @PostMapping("/settle/norm/reset")
    @ApiOperation(value = "费用结算-重新结算")
    public ResponseHelper settleNormReset(
            @ApiParam(value = "详情bean", required = true) @RequestBody OrderSettleDetailBean bean
    ) throws Exception {
        AdminUserCom adminUser = commonLogic.getAdminUser();
        String lockKey = "";
        if (Objects.nonNull(adminUser.getAdminCompanyWechat())) {
            lockKey = adminUser.getAdminCompanyWechat().getCompanyWechatId();
        }
        Lock obtain = redisLockRegistry.obtain(Constant.RedisPrefix.LOCK_ORDER + ":" + lockKey);
        try {
            if (obtain.tryLock(5, TimeUnit.SECONDS)) {
//                orderLogLogic.settleNormReset(bean);
                orderLogLogic.settleNormReset(bean);
            }
        } catch(Exception e) {
            log.error("【重新结算处理】失败", e);
            throw e;
        } finally {
            obtain.unlock();
        }

        return ResponseHelper.success();
    }


    @PostMapping("/import")
    @ApiOperation(value = "导入工单，模板名：工单导入模板.xlsx")
    public ResponseHelper importData(
            @RequestParam MultipartFile file
    ) throws IOException {
        List<Object> objects = ExcelUtils.importExcel(file);
        orderBaseExcelLogic.importOrder(objects);
        return ResponseHelper.success();
    }


    @PostMapping("/import2")
    @ApiOperation(value = "导入工单，模板名：工单导入模板2.xlsx")
    public ResponseHelper importData2(
            @RequestParam MultipartFile file

    ) throws IOException {
        List<Object> objects = ExcelUtils.importExcel(file);
        orderBaseExcelLogic.importOrder2(objects);
        return ResponseHelper.success();
    }


    @PostMapping("/import3")
    @ApiOperation(value = "工单4.0导入")
    public ResponseHelper importData3(
            @RequestParam MultipartFile file
    ) throws IOException {
        List<Object> objects = ExcelUtils.importExcel(file);
        orderBaseExcelLogic.import3(objects);
        return ResponseHelper.success();
    }

}
