package com.kym.admin.controller;

import cn.hutool.core.io.IoUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import cn.dev33.satoken.stp.StpUtil;
import com.kym.common.R;
import com.kym.common.annotation.SysLog;
import com.kym.common.exception.BusinessException;
import com.kym.entity.admin.InvoiceDetail;
import com.kym.entity.admin.queryParams.CommonQueryParam;
import com.kym.entity.admin.queryParams.InvoiceDetailQueryParam;
import com.kym.entity.admin.queryParams.InvoiceQueryParam;
import com.kym.entity.miniapp.Invoice;
import com.kym.service.admin.InvoiceDetailService;
import com.kym.service.miniapp.HuapiaoerInvoiceService;
import com.kym.service.miniapp.InvoiceService;
import com.kym.service.miniapp.RefundLogService;
import com.kym.service.wechat.WxPayService;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.*;

import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;

@RestController
@RequestMapping("/finance")
public class FinanceController {

    private final Logger logger = LoggerFactory.getLogger(FinanceController.class);

    private final WxPayService wxPayService;
    private final RefundLogService refundLogService;
    private final InvoiceService invoiceService;
    private final InvoiceDetailService invoiceDetailService;
    private final HuapiaoerInvoiceService huapiaoerInvoiceService;

    public FinanceController(WxPayService wxPayService, RefundLogService refundLogService,
                             InvoiceService invoiceService, InvoiceDetailService invoiceDetailService,
                             HuapiaoerInvoiceService huapiaoerInvoiceService) {
        this.wxPayService = wxPayService;
        this.refundLogService = refundLogService;
        this.invoiceService = invoiceService;
        this.invoiceDetailService = invoiceDetailService;
        this.huapiaoerInvoiceService = huapiaoerInvoiceService;
    }

    @SysLog("退款申请列表")
    @GetMapping("/listRefundLog")
    R<?> listRefundLog(@ModelAttribute CommonQueryParam params) {
        return R.success(refundLogService.listRefundLog(params));
    }

    @SysLog("处理用户微信退款")
    @GetMapping("/customWxRefund/{refundLogId}")
    R<?> customWxRefund(@PathVariable("refundLogId") long refundLogId) {
        wxPayService.wxRefund(refundLogId);
        return R.success();
    }

    @SysLog("手动确认退款（线下退款）")
    @GetMapping("/manualConfirmRefund/{refundLogId}")
    R<?> manualConfirmRefund(@PathVariable("refundLogId") long refundLogId) {
        wxPayService.manualConfirmRefund(refundLogId);
        return R.success();
    }

    @SysLog("挂起退款申请")
    @GetMapping("/suspendRefund/{refundLogId}")
    R<?> suspendRefund(@PathVariable("refundLogId") long refundLogId) {
        wxPayService.suspendRefund(refundLogId);
        return R.success();
    }

    @SysLog("取消挂起退款申请")
    @GetMapping("/cancelSuspendRefund/{refundLogId}")
    R<?> cancelSuspendRefund(@PathVariable("refundLogId") long refundLogId) {
        wxPayService.cancelSuspendRefund(refundLogId);
        return R.success();
    }

    @SysLog("开具发票")
    @GetMapping("/handleInvoice/{invoiceId}")
    R<?> handleInvoice(@PathVariable("invoiceId") String invoiceId) {
        var invoice = invoiceService.getById(invoiceId);
        if (invoice == null) {
            throw new BusinessException("发票记录不存在");
        }
        if (!invoice.getStatus().equals(Invoice.STATUS_待开票)) {
            throw new BusinessException("发票状态不是待开票");
        }
        // 记录开票人
        invoiceService.lambdaUpdate()
                .set(Invoice::getBiller, StpUtil.getSession().getString("username"))
                .eq(Invoice::getId, invoice.getId())
                .update();

        var resp = huapiaoerInvoiceService.openBlueInvoice(invoice);
        if (resp.isSuccess()) {
            invoiceService.lambdaUpdate()
                    .set(Invoice::getStatus, Invoice.STATUS_开票中)
                    .eq(Invoice::getId, invoice.getId())
                    .update();
        }
        return R.success(resp);
    }

    @SysLog("确认手动开票")
    @PostMapping("/confirmManualInvoice/{invoiceId}")
    R<?> confirmManualInvoice(@PathVariable("invoiceId") Long invoiceId) {
        invoiceService.confirmManualInvoice(invoiceId);
        return R.success();
    }

    @SysLog("下载发票")
    @GetMapping("/downloadInvoice/{invoiceId}")
    R<?> downloadInvoice(@PathVariable("invoiceId") String invoiceId) {
        var invoice = invoiceService.getById(invoiceId);
        if (invoice == null) {
            throw new BusinessException("发票记录不存在");
        }
        var detail = invoiceDetailService.lambdaQuery()
                .eq(InvoiceDetail::getApplyId, invoice.getApplyId())
                .one();
        return R.success(huapiaoerInvoiceService.getInvoiceDownloadUrls(invoice.getId(), detail));
    }

    @PostMapping("/listInvoice")
    R<?> list(@RequestBody InvoiceQueryParam params) {
        return R.success(invoiceService.listInvoice(params));
    }

    @GetMapping("/cancelApplyInvoice/{invoiceId}")
    R<?> cancelApplyInvoice(@PathVariable String invoiceId) {
        invoiceService.cancelApplyInvoice(invoiceId);
        return R.success();
    }

    @GetMapping("/getInvoice/{applyId}")
    R<?> getInvoice(@PathVariable String applyId) {
        var detail = invoiceDetailService.lambdaQuery()
                .eq(InvoiceDetail::getApplyId, applyId)
                .one();
        return R.success(detail);
    }

    @GetMapping("/listInvoiceDetail")
    R<?> listInvoiceDetail(@ModelAttribute InvoiceDetailQueryParam params) {
        return R.success(invoiceDetailService.listInvoiceDetail(params));
    }

    @GetMapping("/export/invoiceList")
    void exportInvoiceList(@ModelAttribute InvoiceDetailQueryParam params, HttpServletRequest request, HttpServletResponse response) {
        ExcelWriter writer = invoiceDetailService.exportInvoiceDetail(params);
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
        response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode("发票详情列表", StandardCharsets.UTF_8) + ".xlsx");
        ServletOutputStream excelOut = null;
        try {
            excelOut = response.getOutputStream();
            writer.flush(excelOut, true);
        } catch (Exception e) {
            logger.error("exportInvoiceList error", e);
        } finally {
            writer.close();
        }
        IoUtil.close(excelOut);
    }

}
