package com.zfire.mall.manager.controller.engin.info;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.zfire.mall.manager.bean.ExcelData;
import com.zfire.mall.manager.bean.engin.info.EnginInfoOrderBean;
import com.zfire.mall.manager.bean.engin.info.EnginInfoOrderListBean;
import com.zfire.mall.manager.bean.engin.info.EnginInfoSaleExecBean;
import com.zfire.mall.manager.bean.valid.EditGroup;
import com.zfire.mall.manager.bean.valid.SubmitGroup;
import com.zfire.mall.manager.constant.Constant;
import com.zfire.mall.manager.exception.RemoteServiceException;
import com.zfire.mall.manager.helper.ResponseHelper;
import com.zfire.mall.manager.logic.common.CommonLogic;
import com.zfire.mall.manager.logic.engin.info.EnginInfoOrderLogic;
import com.zfire.mall.manager.plus.entity.EnginInfoOrderItem;
import com.zfire.mall.manager.utils.CommonUtils;
import com.zfire.mall.manager.utils.excel.ExcelUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.integration.redis.util.RedisLockRegistry;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.groups.Default;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;

@Slf4j
@RestController
@Api(value = "工程信息单", tags = {"工程信息单"})
@RequestMapping(value = "/engin-info-order", produces = "application/json; charset=utf-8")
public class EnginInfoOrderController {

    @Resource
    EnginInfoOrderLogic enginInfoOrderLogic;
    @Resource
    RedisLockRegistry redisLockRegistry;
    @Resource
    CommonLogic commonLogic;

    @ApiOperation(value = "工程信息单列表")
    @GetMapping("/list")
    public ResponseHelper<IPage<EnginInfoOrderListBean>> list(
            @ApiParam(value = "工程信息单号") @RequestParam(required = false) String enginInfoNo,
            @ApiParam(value = "产品大类") @RequestParam(required = false) String productCategoryId,
            @ApiParam(value = "客户编码/客户名称") @RequestParam(required = false) String customerKeyword,
            @ApiParam(value = "项目名称") @RequestParam(required = false) String projectName,
            @ApiParam(value = "机型类型") @RequestParam(required = false) String machineType,
            @ApiParam(value = "使用单位") @RequestParam(required = false) String useUnit,
            @ApiParam(value = "安装地址") @RequestParam(required = false) String installAddress,
            @ApiParam(value = "工程编号") @RequestParam(required = false) String projectNo,
            @ApiParam(value = "厂工程编号") @RequestParam(required = false) String enginFactoryNo,
            @ApiParam(value = "工程登录类型") @RequestParam(required = false) String enginSignType,
            @ApiParam(value = "业务员") @RequestParam(required = false) String serviceId,
            @ApiParam(value = "单据日期-开始") @RequestParam(required = false) String startOrderDate,
            @ApiParam(value = "单据日期-结束") @RequestParam(required = false) String endOrderDate,
            @ApiParam(value = "合同有效期-开始") @RequestParam(required = false) String startContractExpireDate,
            @ApiParam(value = "合同有效期-结束") @RequestParam(required = false) String endContractExpireDate,
            @ApiParam(value = "创建人名称") @RequestParam(required = false) String createName,
            @ApiParam(value = "审核人名称") @RequestParam(required = false) String confirmName,
            @ApiParam(value = "单据状态 SAVE=保存 WAIT=待审核 OK=通过 FAIL=不通过 CLOSE=关闭") @RequestParam(required = false) List<String> examineStatus,
            @ApiParam(value = "规格型号") @RequestParam(required = false) String specification,
            @ApiParam(value = "true=关闭,false=未关闭") @RequestParam(required = false) Boolean isClose,
            @ApiParam(value = "工程类型 TRADE=商用 HOME=家用") @RequestParam(required = false) String enginOrderType,
            @ApiParam(value = "页号", required = true) @RequestParam Integer pageNum,
            @ApiParam(value = "页大小", required = true) @RequestParam Integer pageSize
    ) throws Exception {
        IPage<EnginInfoOrderListBean> listPage = enginInfoOrderLogic.listPage(enginInfoNo, productCategoryId, customerKeyword, projectName, machineType,
                useUnit, installAddress, projectNo, enginFactoryNo, enginSignType, serviceId, startContractExpireDate, endContractExpireDate, createName,
                confirmName, examineStatus, specification, startOrderDate, endOrderDate, isClose, enginOrderType, pageNum, pageSize);
        return ResponseHelper.success(listPage);
    }

    @ApiOperation(value = "工程信息单详情")
    @GetMapping("/detail")
    public ResponseHelper<EnginInfoOrderBean> detail(
            @ApiParam(value = "工程信息单id", required = true) @RequestParam String id
    ) throws Exception {
        EnginInfoOrderBean enginInfoOrderBean = enginInfoOrderLogic.detail(id);
        return ResponseHelper.success(enginInfoOrderBean);
    }

    @ApiOperation(value = "新增工程信息单")
    @PostMapping("/add")
    public ResponseHelper add(
            @ApiParam(required = true, value = "工程信息单") @RequestBody @Validated EnginInfoOrderBean enginInfoOrderBean
    ) throws Exception {
        return ResponseHelper.success(enginInfoOrderLogic.add(enginInfoOrderBean));
    }

    @ApiOperation(value = "编辑工程信息单")
    @PostMapping("/edit")
    public ResponseHelper edit(
            @ApiParam(required = true, value = "工程信息单")
            @RequestBody
            @Validated(value = {EditGroup.class, Default.class}) EnginInfoOrderBean enginInfoOrderBean
    ) throws Exception {
        return getResponseHelper(enginInfoOrderBean, "edit");
    }

    @ApiOperation(value = "提交工程信息单")
    @PostMapping("/submit")
    public ResponseHelper submit(
            @ApiParam(required = true, value = "工程信息单")
            @RequestBody
            @Validated(value = {SubmitGroup.class, Default.class}) EnginInfoOrderBean enginInfoOrderBean
    ) throws Exception {
        return getResponseHelper(enginInfoOrderBean, "submit");
    }

    @ApiOperation(value = "提交工程信息单")
    @PostMapping("/submit-on-list")
    public ResponseHelper submitOnList(
            @ApiParam(required = true, value = "工程信息单")
            @RequestParam String id
    ) throws Exception {
        EnginInfoOrderBean enginInfoOrderBean = enginInfoOrderLogic.detail(id);
        return getResponseHelper(enginInfoOrderBean, "submit");
    }

    @ApiOperation(value = "审批工程信息单-业务")
    @PostMapping("/examine")
    public ResponseHelper examine(
            @ApiParam(required = true, value = "工程信息单")
            @RequestBody
            @Validated(value = {EditGroup.class, Default.class}) EnginInfoOrderBean enginInfoOrderBean
    ) throws Exception {
        if (commonLogic.getAdminUser(true).getIsCustomer()) {
            throw new RemoteServiceException("暂无权限操作");
        }
        return getResponseHelper(enginInfoOrderBean, "examine");
    }

    @ApiOperation(value = "撤消工程信息单")
    @PostMapping("/revoke")
    public ResponseHelper revoke(
            @ApiParam(required = true, value = "工程信息单") @RequestParam String id
    ) throws Exception {
        Lock obtain = redisLockRegistry.obtain(Constant.RedisPrefix.ENGIN_INFO_ORDER + id);
        try {

            if (obtain.tryLock(5, TimeUnit.SECONDS)) {
                enginInfoOrderLogic.revoke(id);
            }
        } catch (Exception e) {
            log.error("【工程信息单处理】失败", e);
            throw e;
        } finally {
            obtain.unlock();
        }
        return ResponseHelper.success();
    }

    @ApiOperation(value = "工程信息单提前完结")
    @PostMapping("/end-status-upd")
    public ResponseHelper endStatusUpd(
            @ApiParam(required = true, value = "工程信息单") @RequestParam String id
    ) throws Exception {
        if (commonLogic.getAdminUser(true).getIsCustomer()) {
            throw new RemoteServiceException("暂无权限操作");
        }
        Lock obtain = redisLockRegistry.obtain(Constant.RedisPrefix.ENGIN_INFO_ORDER + id);
        try {
            EnginInfoOrderBean detail = enginInfoOrderLogic.detail(id);
            detail.setEndStatus(true);
            detail.setOrderDate(null);
            if (obtain.tryLock(5, TimeUnit.SECONDS)) {
                enginInfoOrderLogic.updInfoOrder(detail);
            }
        } catch (Exception e) {
            log.error("【工程信息单处理】失败", e);
            throw e;
        } finally {
            obtain.unlock();
        }
        return ResponseHelper.success();
    }

    @ApiOperation(value = "删除工程信息单")
    @PostMapping("/del")
    public ResponseHelper del(
            @ApiParam(required = true, value = "工程信息单") @RequestParam List<String> ids
    ) throws Exception {
        enginInfoOrderLogic.del(ids);
        return ResponseHelper.success();
    }

    @ApiOperation(value = "删除工程信息单明细")
    @PostMapping("/del-item")
    public ResponseHelper delItem(
            @ApiParam(required = true, value = "工程信息单号") @RequestParam String enginInfoNo,
            @ApiParam(required = true, value = "工程信息单明细id") @RequestParam String itemId
    ) throws Exception {
        Lock obtain = redisLockRegistry.obtain(Constant.RedisPrefix.ENGIN_ORDER + enginInfoNo);
        try {
            if (obtain.tryLock(5, TimeUnit.SECONDS)) {
                enginInfoOrderLogic.delItem(enginInfoNo, itemId);
                return ResponseHelper.success();
            }
        } catch (Exception e) {
            log.error("【工程信息单明细处理】失败", e);
            throw e;
        } finally {
            obtain.unlock();
        }

        return ResponseHelper.error("删除失败");
    }

    @PostMapping("/abandon")
    @ApiOperation("弃审")
    public ResponseHelper homeAbandon(
            @ApiParam(value = "id", required = true) @RequestParam String id
    ) throws Exception {
        if (commonLogic.getAdminUser(true).getIsCustomer()) {
            throw new RemoteServiceException("暂无权限操作");
        }
        Lock obtain = redisLockRegistry.obtain(Constant.RedisPrefix.ENGIN_INFO_ORDER + id);
        try {
            if (obtain.tryLock(5, TimeUnit.SECONDS)) {
                enginInfoOrderLogic.abandon(id);
            }
        } catch (Exception e) {
            log.error("【工程订单处理】失败", e);
            throw e;
        } finally {
            obtain.unlock();
        }

        return ResponseHelper.success();
    }

    private ResponseHelper getResponseHelper(EnginInfoOrderBean enginInfoOrderBean, String operType) throws Exception {
        Lock obtain = redisLockRegistry.obtain(Constant.RedisPrefix.ENGIN_INFO_ORDER + enginInfoOrderBean.getEnginInfoId());
        try {
            if (obtain.tryLock(5, TimeUnit.SECONDS)) {
                enginInfoOrderLogic.execHandler(enginInfoOrderBean, operType);
            }
        } catch (Exception e) {
            log.error("【工程信息单处理】失败", e);
            throw e;
        } finally {
            obtain.unlock();
        }
        return ResponseHelper.success();
    }

    @ApiOperation(value = "工程信息单列表导出")
    @GetMapping("/export")
    public void export(
            @ApiParam(value = "工程信息单号") @RequestParam(required = false) String enginInfoNo,
            @ApiParam(value = "产品大类") @RequestParam(required = false) String productCategoryId,
            @ApiParam(value = "客户编码/客户名称") @RequestParam(required = false) String customerKeyword,
            @ApiParam(value = "项目名称") @RequestParam(required = false) String projectName,
            @ApiParam(value = "单据类型") @RequestParam(required = false) String orderType,
            @ApiParam(value = "使用单位") @RequestParam(required = false) String useUnit,
            @ApiParam(value = "安装地址") @RequestParam(required = false) String installAddress,
            @ApiParam(value = "工程编号") @RequestParam(required = false) String projectNo,
            @ApiParam(value = "厂工程编号") @RequestParam(required = false) String enginFactoryNo,
            @ApiParam(value = "工程登录类型") @RequestParam(required = false) String enginSignType,
            @ApiParam(value = "业务员") @RequestParam(required = false) String serviceId,
            @ApiParam(value = "合同有效期-开始") @RequestParam(required = false) String startContractExpireDate,
            @ApiParam(value = "合同有效期-结束") @RequestParam(required = false) String endContractExpireDate,
            @ApiParam(value = "单据日期-开始") @RequestParam(required = false) String startOrderDate,
            @ApiParam(value = "单据日期-结束") @RequestParam(required = false) String endOrderDate,
            @ApiParam(value = "创建人名称") @RequestParam(required = false) String createName,
            @ApiParam(value = "审核人名称") @RequestParam(required = false) String confirmName,
            @ApiParam(value = "单据状态 SAVE=保存 WAIT=待审核 OK=通过 FAIL=不通过 CLOSE=关闭") @RequestParam(required = false) List<String> examineStatus,
            @ApiParam(value = "规格型号") @RequestParam(required = false) String specification,
            @ApiParam(value = "true=关闭,false=未关闭") @RequestParam(required = false) Boolean isClose,
            @ApiParam(value = "工程类型 TRADE=商用 HOME=家用") @RequestParam(required = false) String enginOrderType,
            HttpServletRequest request, HttpServletResponse response
    ) throws Exception {
        IPage<EnginInfoOrderListBean> listPage = enginInfoOrderLogic.listPage(enginInfoNo, productCategoryId, customerKeyword, projectName, orderType,
                useUnit, installAddress, projectNo, enginFactoryNo, enginSignType, serviceId, startContractExpireDate, endContractExpireDate, createName,
                confirmName, examineStatus, specification, startOrderDate, endOrderDate, isClose, enginOrderType, 1, -1);
        ExcelData excelData = enginInfoOrderLogic.export(listPage.getRecords());
        ExcelUtils.exportExcel(request, response, "工程信息单.xlsx", excelData);
    }

    @ApiOperation(value = "单据日期修改")
    @PostMapping("/upd-date")
    public ResponseHelper updDate(
            @ApiParam(required = true, value = "工程订单")
            @RequestBody EnginInfoOrderBean enginInfoOrderBean
    ) throws Exception {
        Lock obtain = redisLockRegistry.obtain(Constant.RedisPrefix.ENGIN_INFO_ORDER + enginInfoOrderBean.getEnginInfoId());
        try {
            if (obtain.tryLock(5, TimeUnit.SECONDS)) {
                enginInfoOrderLogic.updInfoOrder(enginInfoOrderBean);
                return ResponseHelper.success();
            }
        } catch (Exception e) {
            log.error("【工程订单处理】失败", e);
            throw e;
        } finally {
            obtain.unlock();
        }
        return ResponseHelper.error("更改日期失败");
    }

    @GetMapping("/download")
    @ApiOperation("下载模板")
    public void download(
            HttpServletResponse response
    ) throws IOException {
        CommonUtils.downloadFile("商用信息单明细模板.xlsx", response);
    }


    @GetMapping("/exec/list")
    @ApiOperation("商用信息单-执行明细")
    public ResponseHelper<IPage<EnginInfoSaleExecBean>> execList(
            @ApiParam(value = "信息单日期开始时间", required = false) @RequestParam(required = false) String startOrderDate,
            @ApiParam(value = "信息单日期结束时间", required = false) @RequestParam(required = false) String endOrderDate,
            @ApiParam(value = "客户id", required = false) @RequestParam(required = false) String customerId,
            @ApiParam(value = "项目名称", required = false) @RequestParam(required = false) String refProjectName,
            @ApiParam(value = "机型型号", required = false) @RequestParam(required = false) String specification,
            @ApiParam(value = "工程编号", required = false) @RequestParam(required = false) String refEnginRecordNo,
            @ApiParam(value = "业务员", required = false) @RequestParam(required = false) String serviceId,
            @ApiParam(value = "是否关闭 true=是 false=否", required = false) @RequestParam(required = false) Boolean isClose,
            @ApiParam(value = "审核人", required = false) @RequestParam(required = false) String confirmName,
            @ApiParam(value = "pageNum", required = true) @RequestParam(required = true) Integer pageNum,
            @ApiParam(value = "pageSize", required = true) @RequestParam(required = true) Integer pageSize
    ) {
        IPage<EnginInfoSaleExecBean> page = enginInfoOrderLogic
                .queryEnginInfoSaleExec(startOrderDate, endOrderDate, customerId, refProjectName, specification,
                        refEnginRecordNo, serviceId, isClose, confirmName, pageNum, pageSize);
        return ResponseHelper.success(page);
    }


    @GetMapping("/exec/export")
    @ApiOperation("商用信息单-执行明细-导出")
    public void exportExecList(
            @ApiParam(value = "信息单日期开始时间", required = false) @RequestParam(required = false) String startOrderDate,
            @ApiParam(value = "信息单日期结束时间", required = false) @RequestParam(required = false) String endOrderDate,
            @ApiParam(value = "客户id", required = false) @RequestParam(required = false) String customerId,
            @ApiParam(value = "项目名称", required = false) @RequestParam(required = false) String refProjectName,
            @ApiParam(value = "机型型号", required = false) @RequestParam(required = false) String specification,
            @ApiParam(value = "工程编号", required = false) @RequestParam(required = false) String refEnginRecordNo,
            @ApiParam(value = "业务员", required = false) @RequestParam(required = false) String serviceId,
            @ApiParam(value = "是否关闭 true=是 false=否", required = false) @RequestParam(required = false) Boolean isClose,
            @ApiParam(value = "审核人", required = false) @RequestParam(required = false) String confirmName,
            HttpServletRequest request,
            HttpServletResponse response
    ) throws Exception {
        IPage<EnginInfoSaleExecBean> page = enginInfoOrderLogic
                .queryEnginInfoSaleExec(startOrderDate, endOrderDate, customerId, refProjectName, specification,
                        refEnginRecordNo, serviceId, isClose, confirmName, 1, -1);
        ExcelData excelData = enginInfoOrderLogic.exportExec(page.getRecords());
        ExcelUtils.exportExcel(request, response, "信息单执行明细.xlsx", excelData);
    }


    @PostMapping("/import-item")
    @ApiOperation("导入产品明细")
    public ResponseHelper<List<EnginInfoOrderItem>> importItem(
            MultipartFile file
    ) throws Exception {
        List<Object> objects = ExcelUtils.importExcel(file);
        return ResponseHelper.success(enginInfoOrderLogic.importData(objects));
    }

    @PostMapping("/close/update")
    @ApiOperation("打开/关闭信息单")
    public ResponseHelper updateClose(
            @ApiParam(value = "信息单id", required = true) @RequestParam(required = true) String enginInfoId,
            @ApiParam(value = "true=关闭 false=不关闭", required = true) @RequestParam(required = true) Boolean isClose
    ) throws Exception {
        enginInfoOrderLogic.updateClose(enginInfoId, isClose);
        return ResponseHelper.success();
    }
}
