package com.jwipc.finance.controller.rest;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson2.JSON;
import com.google.common.collect.Lists;
import com.jwipc.exception.DaoException;
import com.jwipc.finance.dto.CompanyAccountStatementDTO;
import com.jwipc.finance.dto.CompanyInvoicedApplyDTO;
import com.jwipc.finance.dto.CompanyInvoicedApplySaveParamDTO;
import com.jwipc.finance.dto.InvoicedApplyDTO;
import com.jwipc.finance.entity.CompanyInvoicedApply;
import com.jwipc.finance.logic.CompanyAccountStatementDetailLogic;
import com.jwipc.finance.logic.CompanyAccountStatementLogic;
import com.jwipc.finance.logic.CompanyInvoicedApplyLogic;
import com.jwipc.finance.logic.PaymentAdvanceApplyDetailLogic;
import com.jwipc.finance.model.query.CompanyInvoicedApplyQuery;
import com.jwipc.finance.model.query.CreateInvoicedApplyPageQuery;
import com.jwipc.order.client.PurchaseOrderClient;
import com.jwipc.page.PageView;
import com.jwipc.security.LoginUtil;
import com.jwipc.sys.client.DigitalSealBusinessDetailClient;
import com.jwipc.util.EasyExcelUtils;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.Objects;

import static com.jwipc.finance.constant.ModuleConst.MODULE_ROOT;

/**
 * @author shenyang.ou
 * @date 2024/3/5 13:56
 * @desc
 */
@RestController
@RequestMapping(MODULE_ROOT + "/company/invoiced/apply/rest")
@RequiredArgsConstructor
public class CompanyInvoicedApplyRestController {

    private final CompanyInvoicedApplyLogic costInvoicedApplyLogic;
    private final PurchaseOrderClient purchaseOrderClient;
    private final PaymentAdvanceApplyDetailLogic paymentAdvanceApplyDetailLogic;
    private final CompanyAccountStatementDetailLogic costAccountStatementDetailLogic;
    private final DigitalSealBusinessDetailClient digitalSealBusinessDetailClient;
    private final CompanyAccountStatementLogic costAccountStatementLogic;

    /**
     * 查询开票申请单列表
     *
     * @param query 查询条件
     * @return 结果
     */
    @PostMapping("/list")
    public PageView list(CompanyInvoicedApplyQuery query) {
        query.setIsSupplier(LoginUtil.isSupplier()?1:0);
        query.setUserId(LoginUtil.getUserId());

        // 1:暂存 2:待采购确认 3:采购拒绝 4:待推送OA审批 5:OA审批中 6:OA审批不通过 7:待财务确认 8:财务拒绝 9:确认通过
        List<Integer> statusList = Lists.newArrayList();
        if(StringUtils.isNotEmpty(query.getIaStatus())) {
            final String[] statusArray = StringUtils.split(query.getIaStatus(), ",");
            for (String status: statusArray) {
                statusList.add(Integer.parseInt(status));
            }
        }else {
            // 角色类型 1:采购角色 2:财务角色
            if (null != query.getRoleType() && 1 == query.getRoleType()) {
                statusList.add(2);
                statusList.add(4);
                statusList.add(5);
                statusList.add(6);
                statusList.add(7);
                statusList.add(8);
                statusList.add(9);
            }
            if (null != query.getRoleType() && 2 == query.getRoleType()) {
                statusList.add(7);
                statusList.add(9);
            }
        }
        query.setStatusList(statusList);

        return costInvoicedApplyLogic.selectDataByQuery(query);
    }

    @PostMapping("/payableSend")
    @Transactional(rollbackFor = Exception.class)
    public ResponseEntity payableSend(String ids) {
        costInvoicedApplyLogic.payableSend(ids);
        return ResponseEntity.ok(true);
    }

    /**
     * 查询开票申请单列表
     *
     * @param query 查询条件
     * @return 结果
     */
    @PostMapping("/sup/list")
    public PageView supList(CompanyInvoicedApplyQuery query) {
        query.setIsSupplier(LoginUtil.isSupplier()?1:0);
        if (LoginUtil.isSupplier()) {
            query.setSupplierCode(LoginUtil.getAccount());
        } else {
            query.setUserId(LoginUtil.getUserId());
        }
        // 1:暂存 2:待采购确认 3:采购拒绝 4:待推送OA审批 5:OA审批中 6:OA审批不通过 7:待财务确认 8:财务拒绝
        List<Integer> statusList = Lists.newArrayList();
        statusList.add(1);
        statusList.add(2);
        statusList.add(3);
        statusList.add(4);
        statusList.add(5);
        statusList.add(6);
        statusList.add(7);
        statusList.add(8);
        statusList.add(9);
        query.setStatusList(statusList);
        query.setDelFlg(1);
        return costInvoicedApplyLogic.selectDataByQuery(query);
    }

    /**
     * 导出
     * @param exportFiled 导出的列信息
     * @param queryStr 查询条件
     */
    @PostMapping("/sup/export")
    public void supExport(HttpServletResponse response, String exportFiled, String queryStr) throws IOException {
        CompanyInvoicedApplyQuery query = JSON.parseObject(queryStr, CompanyInvoicedApplyQuery.class);
        if (LoginUtil.isSupplier()) {
            query.setSupplierCode(LoginUtil.getAccount());
        } else {
            query.setUserId(LoginUtil.getUserId());
        }
        // 1:暂存 2:待采购确认 3:采购拒绝 4:待推送OA审批 5:OA审批中 6:OA审批不通过 7:待财务确认 8:财务拒绝
        List<Integer> statusList = Lists.newArrayList();
        statusList.add(1);
        statusList.add(2);
        statusList.add(3);
        statusList.add(4);
        statusList.add(5);
        statusList.add(6);
        statusList.add(7);
        statusList.add(8);
        statusList.add(9);
        query.setStatusList(statusList);
        query.setDelFlg(1);
        // 查询数据列表，直接调用列表的查询，无需特殊改动
        final List<CompanyInvoicedApplyDTO> exportData = costInvoicedApplyLogic.listAll(query);
        //动态导出工具类，只需要修改导出excel名称
        EasyExcelUtils.trendsModelWrite(response,"对账开票申请-" + DateUtil.format(new Date(), DatePattern.NORM_DATE_PATTERN),"sheet", exportData, exportFiled);
    }

    /**
     * 查询对账单的开票申请单是否已经存在，并且为9（发票已确认状态）
     * @type 1 对账单页面发起电子印章签署操作，2 进行附件删除操作
     * @return
     */
    @GetMapping("/checkApply")
    public ResponseEntity checkApply(String accountStatementNo, String type, String accountStatementId) {
        if (type.equals("2")) {
            CompanyAccountStatementDTO accountStatementDTO = costAccountStatementLogic.getById(Long.parseLong(accountStatementId));
            if (Objects.isNull(accountStatementDTO) || StringUtils.isEmpty(accountStatementDTO.getAccountStatementNo())) {
                throw new DaoException("该账单还未到开票申请环节！");
            }
//            accountStatementNo = accountStatementDTO.getAccountStatementNo();
        }

        if (type.equals("1")) {
            final CompanyInvoicedApply invoicedApply = costInvoicedApplyLogic.findInvoicedApplyByStatementNo(accountStatementNo);
            if (Objects.nonNull(invoicedApply)) {
                throw new DaoException("该对账单为发票已确认状态，不可上传电子印章签署操作！");
            }
        }

//        boolean exist  = digitalSealBusinessDetailClient.checkExist(Long.valueOf(accountStatementId), "purchase_sale_contract,purchase_sale_process_contract");
//
//        if (exist){
//            final CompanyInvoicedApply invoicedApply = costInvoicedApplyLogic.findInvoicedApplyByStatementNo(accountStatementNo);
//            String msg = "该对账单为发票已确认状态，不可发起电子印章签署操作!";
//            if (type.equals("2")) {
//                msg = "该对账单为发票已确认状态，无法进行附件删除操作!";
//            }
//            if (Objects.nonNull(invoicedApply)) {
//                throw new DaoException(msg);
//            }
//        }
        return ResponseEntity.ok(true);
    }

    /**
     * 开票申请单删除
     *
     * @param ids 开票申请ID
     * @return 结果
     */
    @PostMapping("/del")
    public ResponseEntity dataDel(String ids) {
        costInvoicedApplyLogic.dataDel(ids,false);
        return ResponseEntity.ok(true);
    }

    /**
     * 开票申请提交采购确认
     *
     * @param ids 开票申请ID
     * @return 结果
     */
    @PostMapping("/submit/confirm")
    public ResponseEntity submitConfirm(String ids) {
        costInvoicedApplyLogic.submitConfirm(ids);
        return ResponseEntity.ok(true);
    }

    /**
     * 数据导出
     *
     * @param request 请求体
     * @param response 返回体
     * @param id 开票申请单ID
     */
    @GetMapping("/data/export")
    public void dataExport(HttpServletRequest request, HttpServletResponse response, Long id) {
        costInvoicedApplyLogic.dataExport(request,response,id);

    }

    @PostMapping("/writeOff")
    public ResponseEntity writeOff(Long id,String writeOff) {
        costInvoicedApplyLogic.writeOff(id,writeOff);
        return ResponseEntity.ok(true);
    }


    /**
     * 暂时存表头
     * fin/invoiced/apply/rest/saveHead
     *
     * @param params 请求参数
     * @return 结果
     */
    @PostMapping("/saveHead")
    public ResponseEntity updateHead(@RequestBody CompanyInvoicedApplySaveParamDTO params) {
        costInvoicedApplyLogic.updateHead(params);
        return ResponseEntity.ok(true);
    }

    /**
     * 暂时存表头
     *
     * @param params 请求参数
     * @return 结果
     */
    @PostMapping("/save")
    public ResponseEntity dataSave(@RequestBody CompanyInvoicedApplySaveParamDTO params) {
        CompanyInvoicedApplyDTO headDto = params.getHeadData();
        CreateInvoicedApplyPageQuery query = new CreateInvoicedApplyPageQuery();
        query.setFactoryCode(headDto.getFactoryCode());
        query.setAsId(headDto.getAccountStatementId());
        costInvoicedApplyLogic.dataSave(params);
        return ResponseEntity.ok(true);
    }


    @PostMapping("/statementInvoicing/check")
    public ResponseEntity statementInvoicingCheck(String accountStatementNo){
        if(Objects.isNull(accountStatementNo)){
            return ResponseEntity.ok(false);
        }
        return ResponseEntity.ok(costInvoicedApplyLogic.statementInvoicingCheck(accountStatementNo));
    }

    /**
     * 采购或财务确认开票申请
     *
     * @param params 开票申请数据
     * @return 结果
     */
    @PostMapping("/approve/confirm")
    public ResponseEntity purchaseConfirm(@RequestBody CompanyInvoicedApplySaveParamDTO params){
        //开票申请时获取对账单数据（分库分表后，加入别的事务查询不会生效，剥离到这里查询传入值）
//        if(1 == params.getRoleType() && 1 == params.getApproveStatus()){
//            //2025-09-06增加采购审核通过保存时，当实际未付金额大于0，判定对账明细中所有订单行是否有未抵扣的预付款金额逻辑校验
//            paymentAdvanceApplyDetailLogic.hasUnappliedPrepaymentBalance(params.getHeadData(),params.getAddAdvances());
//        }

        costInvoicedApplyLogic.purchaseConfirm(params);
        return ResponseEntity.ok(true);
    }

    /**
     * 采购撤销待财务确认状态的开票申请
     *
     * @param iaId 开票申请ID
     * @param revokeReason 撤销原因
     * @return 结果
     */
    @PostMapping("/revoke/fin/confirm")
    public ResponseEntity revokeFinConfirm(Long iaId, String revokeReason) {
        costInvoicedApplyLogic.revokeFinConfirm(iaId, revokeReason);
        return ResponseEntity.ok(true);
    }

    @PostMapping("/approve/confirmCancel")
    @Transactional(rollbackFor = Exception.class)
    public ResponseEntity financeConfirmCancel(String ids) {
        costInvoicedApplyLogic.financeConfirmCancel(ids);
        return ResponseEntity.ok(true);
    }

    @PostMapping("/statementInvoicing/checkHasNGSignOk")
    public ResponseEntity checkHasNGSignOk(String accountStatementId,String year, String month, String supplierCode) {
        if(Objects.isNull(accountStatementId) || Objects.isNull(supplierCode) || Objects.isNull(year) || Objects.isNull(month)) {
            throw new DaoException("参数不能为空!");
        }
        String reStr = purchaseOrderClient.findMonthNGconfirmOrderList(accountStatementId, year, month, supplierCode);
        if (StringUtils.isNotEmpty(reStr)) {
            throw new DaoException(reStr);
        } else {
            return ResponseEntity.ok(false);
        }
    }

    @PostMapping("/toImg")
    public ResponseEntity toImg(Long iaId) {
        CompanyInvoicedApplyDTO invoicedApplyDTO = costInvoicedApplyLogic.getById(iaId);
        if (StringUtils.isNotEmpty(invoicedApplyDTO.getImgCode())&&invoicedApplyDTO.getImgTime()!=null){
            throw new DaoException("该开票申请单已影像化，不可重复操作");
        }
        costInvoicedApplyLogic.toImg(iaId);
        return ResponseEntity.ok(true);
    }

    @PostMapping("/deleteImg")
    public ResponseEntity deleteImg(Long iaId) {
        CompanyInvoicedApplyDTO invoicedApplyDTO = costInvoicedApplyLogic.getById(iaId);
        if (invoicedApplyDTO.getImgTime()==null){
            throw new DaoException("该开票申请单未影像化，不可删除");
        }
        costInvoicedApplyLogic.deleteImg(iaId);
        return ResponseEntity.ok(true);
    }

}
