package com.ruoyi.app.mendian;

import com.ruoyi.app.omgpay.OmgStoreCredentialVerifier;
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.StoreOmgCredentialDto;
import com.ruoyi.system.domain.vo.PosStoreOmgVo;
import com.ruoyi.system.service.IPosStoreOmgService;
import jakarta.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

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

/**
 * 平台后台 - 门店 OMG(歐買尬) 支付凭证管理。
 *
 * <p>OMG 商店注册为线下人工；本接口负责申请状态推进、凭证录入与联网验证(QueryTradeInfo 探测)、
 * 启用开关。联网验证放应用层（避免 ruoyi-system 反向依赖 ruoyi-admin），
 * Service 仅持久化。
 *
 * @author ruoyi
 * @date 2026-07-29
 */
@RestController
@RequestMapping("/system/storeOmg")
public class PosStoreOmgController extends BaseController {

    @Autowired
    private IPosStoreOmgService posStoreOmgService;

    @Autowired
    private OmgStoreCredentialVerifier credentialVerifier;

    /** 门店 OMG 凭证管理列表（分页 + 筛选）。 */
    @PreAuthorize("@ss.hasPermi('chanting:storeOmg:list')")
    @GetMapping("/list")
    public TableDataInfo list(PosStoreOmgVo query) {
        startPage();
        List<PosStoreOmgVo> list = posStoreOmgService.selectOmgStoreList(query);
        return getDataTable(list);
    }

    /** 门店 OMG 详情。 */
    @PreAuthorize("@ss.hasPermi('chanting:storeOmg:query')")
    @GetMapping("/{storeId}")
    public AjaxResult getInfo(@PathVariable Long storeId) {
        return success(posStoreOmgService.selectOmgStoreDetail(storeId));
    }

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

    /**
     * 录入 OMG 凭证并验证：调 OMG QueryTradeInfo/V5 查一个虚构 MerchantTradeNo 探测金钥。
     * 金钥错误 → OMG 回 CheckMacValue 验证错误（拒绝、状态不变）；金钥正确 → 返回「无此交易」类结果，视为通过。
     */
    @PreAuthorize("@ss.hasPermi('chanting:storeOmg:saveCredentials')")
    @Log(title = "OMG录入凭证", businessType = BusinessType.UPDATE)
    @PutMapping("/saveCredentials")
    public AjaxResult saveCredentials(@RequestBody @Valid StoreOmgCredentialDto dto) {
        Map<String, String> resp;
        try {
            resp = credentialVerifier.verify(dto.getMerchantId(), dto.getHashKey(), dto.getHashIv());
        } catch (Exception e) {
            posStoreOmgService.recordVerifyResult(dto.getStoreId(), "ERROR: " + msg(e));
            return error("OMG 验证服务暂不可用，请稍后重试");
        }
        if (resp == null || !resp.containsKey("TradeStatus")) {
            posStoreOmgService.recordVerifyResult(dto.getStoreId(), "FAIL: invalid signed response");
            return error("OMG 凭证验证失败，请稍后重试");
        }
        String rtnMsg = resp == null ? "" : (resp.getOrDefault("RtnMsg", "") + " " + resp.getOrDefault("Message", ""));
        // 金钥/商店代号错误时 OMG 回 CheckMacValue 验证失败或提示 HashKey/商店代号
        if (rtnMsg.contains("CheckMacValue") || rtnMsg.contains("HashKey") || rtnMsg.contains("商店代號") || rtnMsg.contains("商店代号")) {
            posStoreOmgService.recordVerifyResult(dto.getStoreId(), "FAIL: " + auditResponse(resp));
            return error("OMG 凭证无效，请检查商店代号 / HashKey / HashIV");
        }
        posStoreOmgService.enableWithCredentials(dto);
        return success("凭证验证通过，已开通");
    }

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

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

    /** 设置启用支付方式（本期固定 ALL）。入参 {enabledPayments: "ALL"}。 */
    @PreAuthorize("@ss.hasPermi('chanting:storeOmg:saveCredentials')")
    @Log(title = "OMG支付方式", businessType = BusinessType.UPDATE)
    @PutMapping("/enabledPayments/{storeId}")
    public AjaxResult enabledPayments(@PathVariable Long storeId, @RequestBody Map<String, String> body) {
        String payments = body == null ? null : body.get("enabledPayments");
        return toAjax(posStoreOmgService.setEnabledPayments(storeId, payments));
    }

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

    private static Map<String, String> auditResponse(Map<String, String> response) {
        Map<String, String> audit = new LinkedHashMap<>(response);
        audit.remove("CheckMacValue");
        return audit;
    }
}
