package com.ruoyi.app.mendian;

import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.app.utils.ezPay.EzPay;
import com.ruoyi.app.utils.ezPay.EzPayConfig;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.system.domain.dto.StoreEzpayCredentialDto;
import com.ruoyi.system.domain.vo.PosStoreEzpayVo;
import com.ruoyi.system.service.IPosStoreEzpayService;
import jakarta.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * 平台后台 - 商家 ezPay 发票开通管理。
 *
 * <p>ezPay 商店注册为线下人工；本接口负责申请状态推进、凭证录入与联网验证、
 * 启用开关、免用发票标记。ezPay 联网验证（仅用只读 invoice_search）放在本 Controller 层，
 * Service 仅做持久化，避免 ruoyi-system 反向依赖 ruoyi-admin 的 EzPay 工具类。
 *
 * @author ruoyi
 * @date 2026-06-15
 */
@RestController
@RequestMapping("/system/storeEzpay")
public class PosStoreEzpayController extends BaseController {

    @Autowired
    private IPosStoreEzpayService posStoreEzpayService;

    @Autowired
    private EzPay ezPay;

    /** ezPay 根地址（测试 cinv.ezpay.com.tw / 生产 inv.ezpay.com.tw），来自 application.yml */
    @Value("${ezpay.base-url}")
    private String ezpayBaseUrl;

    /** ezPay 开通管理列表（分页 + 筛选 + 快捷过滤）。 */
    @PreAuthorize("@ss.hasPermi('chanting:storeEzpay:list')")
    @GetMapping("/list")
    public TableDataInfo list(PosStoreEzpayVo query) {
        startPage();
        List<PosStoreEzpayVo> list = posStoreEzpayService.selectEzpayStoreList(query);
        return getDataTable(list);
    }

    /** 门店 ezPay 详情。 */
    @PreAuthorize("@ss.hasPermi('chanting:storeEzpay:query')")
    @GetMapping("/{storeId}")
    public AjaxResult getInfo(@PathVariable Long storeId) {
        return success(posStoreEzpayService.selectEzpayStoreDetail(storeId));
    }

    /** 发起申请（未申请 0 → 申请中 1）。 */
    @PreAuthorize("@ss.hasPermi('chanting:storeEzpay:apply')")
    @Log(title = "ezPay发起申请", businessType = BusinessType.UPDATE)
    @PutMapping("/apply/{storeId}")
    public AjaxResult apply(@PathVariable Long storeId) {
        return toAjax(posStoreEzpayService.apply(storeId));
    }

    /**
     * 录入 ezPay 凭证并验证：调 ezPay 只读 invoice_search 验证金钥，
     * 回应含 KEY1xxxx 视为凭证无效（拒绝、状态不变），否则视为通过并标记已开通。
     */
    @PreAuthorize("@ss.hasPermi('chanting:storeEzpay:saveCredentials')")
    @Log(title = "ezPay录入凭证", businessType = BusinessType.UPDATE)
    @PutMapping("/saveCredentials")
    public AjaxResult saveCredentials(@RequestBody @Valid StoreEzpayCredentialDto dto) {
        EzPayConfig cfg = new EzPayConfig(dto.getMerchantId(), dto.getHashKey(), dto.getHashIv());
        Map<String, Object> postData = new LinkedHashMap<>();
        postData.put("RespondType", "JSON");
        postData.put("Version", "1.3");
        postData.put("SearchType", "0");
        postData.put("InvoiceNumber", "AA12345678"); // 测试用假发票号，只用于验证金钥
        postData.put("RandomNum", "1234");

        String respStr;
        try {
            JSONObject resp = ezPay.doPost(ezpayBaseUrl + EzPay.URL_SEARCH, cfg, postData);
            respStr = resp == null ? "" : resp.toJSONString();
        } catch (Exception e) {
            posStoreEzpayService.recordVerifyResult(dto.getStoreId(), "ERROR: " + msg(e));
            return error("ezPay 验证服务暂不可用，请稍后重试");
        }

        if (respStr.contains("KEY1")) {
            posStoreEzpayService.recordVerifyResult(dto.getStoreId(), "FAIL: " + respStr);
            return error("ezPay 凭证无效，请检查商店代号 / HashKey / HashIV");
        }

        posStoreEzpayService.enableWithCredentials(dto);
        return success("凭证验证通过，已开通");
    }

    /** 停用 / 恢复（仅已开通门店）。 */
    @PreAuthorize("@ss.hasPermi('chanting:storeEzpay:toggleEnable')")
    @Log(title = "ezPay停用恢复", businessType = BusinessType.UPDATE)
    @PutMapping("/toggleEnable/{storeId}")
    public AjaxResult toggleEnable(@PathVariable Long storeId) {
        return toAjax(posStoreEzpayService.toggleEnable(storeId));
    }

    /** 标记免用发票 / 恢复需开票。入参 {invoiceExempt: 0|1}。 */
    @PreAuthorize("@ss.hasPermi('chanting:storeEzpay:markExempt')")
    @Log(title = "ezPay免用发票标记", businessType = BusinessType.UPDATE)
    @PutMapping("/markExempt/{storeId}")
    public AjaxResult markExempt(@PathVariable Long storeId, @RequestBody Map<String, Integer> body) {
        Integer invoiceExempt = body == null ? null : body.get("invoiceExempt");
        return toAjax(posStoreEzpayService.markExempt(storeId, invoiceExempt));
    }

    /** 重置状态（凭证作废/重新申请）。 */
    @PreAuthorize("@ss.hasPermi('chanting:storeEzpay:query')")
    @Log(title = "ezPay重置状态", businessType = BusinessType.UPDATE)
    @PutMapping("/reset/{storeId}")
    public AjaxResult reset(@PathVariable Long storeId) {
        return toAjax(posStoreEzpayService.reset(storeId));
    }

    private static String msg(Throwable e) {
        return e.getMessage() == null ? e.getClass().getSimpleName() : e.getMessage();
    }
}
