package org.dromara.payment.bill.controller;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSONObject;
import lombok.RequiredArgsConstructor;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.*;
import cn.dev33.satoken.annotation.SaCheckPermission;
import org.dromara.common.core.enums.BusRole;
import org.dromara.common.core.utils.DateUtils;
import org.dromara.common.core.utils.StreamUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.core.utils.file.FileUtils;
import org.dromara.common.excel.core.ExcelResult;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.payment.bill.domain.bo.AddBillBo;
import org.dromara.payment.bill.domain.bo.MerBillDetailBo;
import org.dromara.payment.bill.domain.vo.MerBillDetailVo;
import org.dromara.payment.bill.listener.BillImportListener;
import org.dromara.payment.bill.service.IMerBillDetailService;
import org.dromara.payment.task.domain.bo.MerTaskBo;
import org.dromara.payment.task.domain.bo.MerTaskEnrollBo;
import org.dromara.payment.task.domain.vo.MerTaskEnrollVo;
import org.dromara.payment.task.domain.vo.MerTaskVo;
import org.dromara.payment.task.service.IMerTaskEnrollService;
import org.dromara.payment.task.service.IMerTaskService;
import org.dromara.payment.worker.domain.UserWorkerAccount;
import org.dromara.payment.worker.domain.bo.UserWorkerAccountBo;
import org.dromara.payment.worker.domain.vo.UserWorkerVo;
import org.dromara.payment.worker.service.impl.UserWorkerAccountServiceImpl;
import org.dromara.payment.worker.service.impl.UserWorkerServiceImpl;
import org.dromara.system.api.model.LoginUser;
import org.springframework.cloud.stream.function.StreamBridge;
import org.springframework.http.MediaType;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.web.core.BaseController;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.payment.bill.domain.vo.MerBillVo;
import org.dromara.payment.bill.domain.bo.MerBillBo;
import org.dromara.payment.bill.service.IMerBillService;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.springframework.web.multipart.MultipartFile;

/**
 * 账单
 * 前端访问路由地址为:/payment/bill
 *
 * @author LionLi
 * @date 2024-04-08
 */
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/bill")
public class MerBillController extends BaseController {

    private final IMerBillService merBillService;

    private final IMerBillDetailService billDetailService;

    private final IMerTaskService merTaskService;

    private final IMerTaskEnrollService merTaskEnrollService;

    private final StreamBridge streamBridge;

    private final UserWorkerAccountServiceImpl userWorkerAccountServiceImpl;

    private final UserWorkerServiceImpl userWorkerServiceImpl;

    private void bindDataPermission(MerBillBo bo) {
        LoginUser loginUser = LoginHelper.getLoginUser();
        if(loginUser.getCurRoleId() == BusRole.SERVICE.getId()){
            bo.setSydId(loginUser.getBusId().longValue());
        }else if(loginUser.getCurRoleId() == BusRole.OPERATOR.getId()){
            bo.setOpId(loginUser.getBusId().longValue());
        }else if(loginUser.getCurRoleId() == BusRole.MERCHANT.getId()){
            bo.setMerId(loginUser.getBusId().longValue());
            bo.setSydId(loginUser.getSydId().longValue());
        }else if(loginUser.getCurRoleId() == BusRole.AGENT.getId()){
            bo.getParams().putAll(Map.of("channel_no",loginUser.getBusNo()));
        }
    }

    /**
     * 查询代发批次列表
     */
    @SaCheckPermission("payment:bill:list")
    @GetMapping("/list")
    public TableDataInfo<MerBillVo> list(MerBillBo bo, PageQuery pageQuery) {
        bindDataPermission(bo);
        return merBillService.queryPageList(bo, pageQuery);
    }

    /**
     * 服务商接单审批代发列表
     */
    @GetMapping("/orderApprovalList")
    public TableDataInfo<MerBillVo> orderApprovalList(MerBillBo bo, PageQuery pageQuery) {
        LoginUser loginUser = LoginHelper.getLoginUser();
        bo.setSydId(loginUser.getBusId().longValue());
        return merBillService.queryPageList(bo, pageQuery);
    }

    /**
     * 服务商接单审批代发待审批数量
     */
    @GetMapping("/orderApprovalCount")
    public R<Integer> orderApprovalCount(MerBillBo bo) {
        LoginUser loginUser = LoginHelper.getLoginUser();
        bo.setSydId(loginUser.getBusId().longValue());
        bo.setStatus(0l);//已提交
        bo.setSydVerifyStatus(1);//待审批
        return R.ok(merBillService.queryListCount(bo));
    }

    /**
     * 导出接单审批代发列表
     */
    @Log(title = "导出接单审批代发列表", businessType = BusinessType.EXPORT)
    @PostMapping("/exportOrderApproval")
    public void exportOrderApproval(MerBillBo bo, HttpServletResponse response) {
        LoginUser loginUser = LoginHelper.getLoginUser();
        bo.setSydId(loginUser.getBusId().longValue());
        List<MerBillVo> list = merBillService.queryList(bo);
        ExcelUtil.exportExcel(list, "批次打款_"+ DateUtils.dateTimeNow(), MerBillVo.class, response);
    }

    /**
     * 商户出款审批代发列表
     */
    @GetMapping("/paymentApprovalList")
    public TableDataInfo<MerBillVo> paymentApprovalList(MerBillBo bo, PageQuery pageQuery) {
        LoginUser loginUser = LoginHelper.getLoginUser();
        if(loginUser.getBusRole() == BusRole.AGENT.getId() || loginUser.getBusRole() == BusRole.OPERATOR.getId()){
            return new TableDataInfo<MerBillVo>();
        }else if(loginUser.getBusRole() == BusRole.MERCHANT.getId()){
            bo.setMerId(loginUser.getBusId().longValue());
            bo.setSydId(loginUser.getSydId().longValue());
        }

        return merBillService.queryPageList(bo, pageQuery);
    }

    /**
     * 商户出款审批代发待审批数量
     */
    @GetMapping("/paymentApprovalCount")
    public R<Integer> paymentApprovalCount(MerBillBo bo) {
        LoginUser loginUser = LoginHelper.getLoginUser();
        if(loginUser.getBusRole() == BusRole.AGENT.getId() || loginUser.getBusRole() == BusRole.OPERATOR.getId()){
            return R.ok(0);
        }else if(loginUser.getBusRole() == BusRole.MERCHANT.getId()){
            bo.setMerId(loginUser.getBusId().longValue());
            bo.setSydId(loginUser.getSydId().longValue());
        }

        bo.setStatus(1l);//已接单
        bo.setVerifyStatus(1l);//待审批
        return R.ok(merBillService.queryListCount(bo));
    }

    /**
     * 导出出款审批代发列表
     */
    @Log(title = "导出出款审批代发列表", businessType = BusinessType.EXPORT)
    @PostMapping("/exportPaymentApproval")
    public void exportPaymentApproval(MerBillBo bo, HttpServletResponse response,String fields) {
        LoginUser loginUser = LoginHelper.getLoginUser();
        List<MerBillVo> list = new ArrayList<>();
        if(loginUser.getBusRole() == BusRole.AGENT.getId() || loginUser.getBusRole() == BusRole.OPERATOR.getId()){
            list = new ArrayList<>();
        }else if(loginUser.getBusRole() == BusRole.MERCHANT.getId()){
            bo.setMerId(loginUser.getBusId().longValue());
            bo.setSydId(loginUser.getSydId().longValue());
            list = merBillService.queryList(bo);
        }


//        ExcelUtil.exportExcel(list, "批次打款_"+ DateUtils.dateTimeNow(), MerBillVo.class, response);
        List fieldList = new ArrayList();
        if(StringUtils.isNotBlank(fields)){
            fieldList = Arrays.asList(fields.split(","));
        }
        ExcelUtil.exportExcelInclude(list, "批次打款_"+ DateUtils.dateTimeNow(), MerBillVo.class, response,fieldList);
    }

    /**
     * 出款审批
     */
    @Log(title = "出款审批", businessType = BusinessType.UPDATE)
    @RepeatSubmit()
    @PostMapping()
    public R<Void> paymentApproval(@Validated(EditGroup.class) @RequestBody MerBillBo bo) {
        LoginUser loginUser = LoginHelper.getLoginUser();
        bo.setVerifyBy(loginUser.getNickname());
        Boolean rtn = merBillService.paymentApproval(bo);
        if (rtn && bo.getVerifyStatus() == 3){//审核通过
            JSONObject queueParam = new JSONObject();
            queueParam.put("billId", bo.getId());
            streamBridge.send("bill-out-0", MessageBuilder.withPayload(queueParam).build());
        }
        return toAjax(rtn);
    }

    /**
     * 导出代发B2B回单
     * @param billIds 代发批次id(多个逗号分隔)
     */
    @Log(title = "导出代发B2B回单", businessType = BusinessType.EXPORT)
    @PostMapping("/exportB2B")
    public void exportB2B(@NotBlank(message = "代发批次id不能为空") String billIds, HttpServletResponse response) throws IOException {
        MerBillDetailBo where = new MerBillDetailBo();
        where.setBillIds(billIds);
        where.setPayStatus(1);//支付成功
        List<MerBillDetailVo> details = billDetailService.queryList(where);
        List<String> b2bs = StreamUtils.toList(details,MerBillDetailVo::getPayReceiptB2b, b2b -> StringUtils.isNotBlank(b2b));
        FileUtils.downloadZip(DateUtils.dateTimeNow()+ RandomUtil.randomNumbers(8),response,b2bs);
    }

    /**
     * 导出代发批次列表
     */
//    @SaCheckPermission("payment:bill:export")
    @Log(title = "代发批次导出", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(MerBillBo bo, HttpServletResponse response,String fields) {
        bindDataPermission(bo);
        List<MerBillVo> list = merBillService.queryList(bo);

        List fieldList = new ArrayList();
        if(StringUtils.isNotBlank(fields)){
            fieldList = Arrays.asList(fields.split(","));
        }
        ExcelUtil.exportExcelInclude(list, "代发批次", MerBillVo.class, response,fieldList);
    }

    /**
     * 获取账单详细信息
     *
     * @param id 主键
     */
//    @SaCheckPermission("payment:bill:query")
    @GetMapping("/{id}")
    public R<MerBillVo> getInfo(@NotNull(message = "主键不能为空")
                                     @PathVariable Long id) {
        return R.ok(merBillService.queryById(id));
    }



    /**
     * 获取账单详细信息
     * @param no 编码
     *
     */
    @SaCheckPermission("payment:bill:query")
    @GetMapping("/getInfo/{no}")
    public R<MerBillVo> getInfo(@NotNull(message = "账单编码不能为空")
                                @PathVariable String no) {
        return R.ok(merBillService.queryByNo(no));
    }


    /**
     * 派单在线打款导入
     * @param bo
     * @return
     */
    @Log(title = "派单在线打款导入", businessType = BusinessType.IMPORT)
    @RepeatSubmit()
    @PostMapping("/onlinePaymentImport")
    public R<ExcelResult<MerBillDetailBo>> onlinePaymentImport(@Validated(AddGroup.class) @RequestBody AddBillBo bo) {
        this.merBillService.validateSysSyd(bo);
        return R.ok(merBillService.onlinePaymentImport(bo));
    }

    /**
     * 抢单项目打款导入
     * @param bo
     * @return
     */
    @Log(title = "抢单项目打款导入", businessType = BusinessType.IMPORT)
    @RepeatSubmit()
    @PostMapping("/qdPaymentImport")
    public R<ExcelResult<MerBillDetailBo>> qdPaymentImport(@Validated(AddGroup.class) @RequestBody AddBillBo bo) {
        this.merBillService.validateSysSyd(bo);
        return R.ok(merBillService.qdPaymentImport(bo));
    }

    /**
     * 派单上传批量打款文件
     * @param file
     * @param bo
     * @return
     * @throws Exception
     */
    @Log(title = "派单上传批量打款文件", businessType = BusinessType.IMPORT)
    @PostMapping(value = "/importBillData", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public R<ExcelResult<MerBillDetailBo>> importBillData(@RequestPart("file") MultipartFile file,AddBillBo bo) throws Exception {
        this.merBillService.validateSysSyd(bo);
        ExcelResult<MerBillDetailBo> result = ExcelUtil.importExcel(file.getInputStream(),new BillImportListener(bo));

        List<MerBillDetailBo> list = result.getList();
        for (MerBillDetailBo merBillDetailBo : list) {

            UserWorkerVo userWorkerVo = userWorkerServiceImpl.queryByName(merBillDetailBo.getWorkerName());

            UserWorkerAccountBo account = new UserWorkerAccountBo();
            account.setWorkId(userWorkerVo.getId());
            account.setBankCard(merBillDetailBo.getBankCard());

            




            userWorkerAccountServiceImpl.updateByBo(account);
        }


        return R.ok(result);
    }

    /**
     * 接单审核
     */
    @Log(title = "接单审核", businessType = BusinessType.UPDATE)
    @RepeatSubmit()
    @PostMapping("/orderApproval")
    public R<Void> orderApproval(@Validated(EditGroup.class) @RequestBody MerBillBo bo) {
        LoginUser loginUser = LoginHelper.getLoginUser();
        bo.setSydVerifyBy(loginUser.getNickname());
        return toAjax(merBillService.orderApproval(bo));
    }

    /**
     * 新增账单
     */
//    @SaCheckPermission("payment:bill:add")
    @Log(title = "账单", businessType = BusinessType.INSERT)
    @RepeatSubmit()
    @PostMapping("/add")
    public R<Void> add(@Validated(AddGroup.class) @RequestBody AddBillBo bo) {
        LoginUser loginUser = LoginHelper.getLoginUser();
        bo.setAddBy(loginUser.getNickname());
        return toAjax(merBillService.insertByBo(bo));
    }

    /**
     * 修改账单
     */
    @SaCheckPermission("payment:bill:edit")
    @Log(title = "账单", businessType = BusinessType.UPDATE)
    @RepeatSubmit()
    @PutMapping("/edit")
    public R<Void> edit(@Validated(EditGroup.class) @RequestBody MerBillBo bo) {
        return toAjax(merBillService.updateByBo(bo));
    }

    /**
     * 删除账单
     *
     * @param ids 主键串
     */
    @SaCheckPermission("payment:bill:remove")
    @Log(title = "账单", businessType = BusinessType.DELETE)
    @DeleteMapping("/{ids}")
    public R<Void> remove(@NotEmpty(message = "主键不能为空")
                          @PathVariable Long[] ids) {
        return toAjax(merBillService.deleteWithValidByIds(List.of(ids), true));
    }

    /**
     * 查询待结算的抢单任务列表
     */
    @GetMapping("/balanceTaskList")
    @Log(title = "查询待结算的抢单任务列表", businessType = BusinessType.OTHER)
    public TableDataInfo<MerTaskVo> list(MerTaskBo bo, PageQuery pageQuery) {
        Integer busRole = LoginHelper.getBusRole();
        if(busRole ==  BusRole.PLATFORM.getId()){
            return new TableDataInfo<>();
        }
        bo.setStatus(1);
        bo.setClassify(2l);
        bo.setTaskStatusList(Arrays.asList(7,8));
        return merTaskService.queryPageList(bo, pageQuery);
    }

    /**
     * 查询待结算的抢单任务竞标人列表
     */
    @GetMapping("/balanceEnrollList")
    @Log(title = "查询待结算的抢单任务竞标人列表", businessType = BusinessType.OTHER)
    public TableDataInfo<MerTaskEnrollVo> list(MerTaskEnrollBo bo, PageQuery pageQuery) {
        bo.setTaskStatus(3);
        bo.setSettlementStatus(0);
        return merTaskEnrollService.queryPageList(bo, pageQuery);
    }
}
