package shop.alien.store.controller;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import shop.alien.entity.result.R;
import shop.alien.entity.store.StorePaymentConfig;
import shop.alien.entity.store.StoreUser;
import shop.alien.store.service.StorePaymentConfigService;
import shop.alien.store.service.StoreUserService;
import shop.alien.util.common.JwtUtil;

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

/**
 * 支付配置 前端控制器
 *
 * @author system
 */
@Slf4j
@Api(tags = {"支付配置"})
@ApiSort(18)
@CrossOrigin
@RestController
@RequestMapping("/store/payment/config")
@RequiredArgsConstructor
public class StorePaymentConfigController {

    private final StorePaymentConfigService storePaymentConfigService;
    private final StoreUserService storeUserService;

    @ApiOperationSupport(order = 1)
    @ApiOperation("新增支付配置（JSON  body）")
    @PostMapping("/add")
    public R<Boolean> add(@RequestBody StorePaymentConfig config) {
        log.info("StorePaymentConfigController.add?config.storeId={}, appId={}", config.getStoreId(), config.getAppId());
        if (config.getStoreId() == null) {
            return R.fail("店铺ID不能为空");
        }
        if (config.getAppId() == null || config.getAppId().trim().isEmpty()) {
            return R.fail("应用ID不能为空");
        }
        try {
            fillCreatedUser(config);
            boolean ok = storePaymentConfigService.save(config);
            return ok ? R.success("新增成功") : R.fail("新增失败");
        } catch (Exception e) {
            log.error("新增支付配置失败", e);
            return R.fail("新增失败：" + e.getMessage());
        }
    }

    @ApiOperationSupport(order = 2)
    @ApiOperation("修改支付配置（JSON body）")
    @PostMapping("/update")
    public R<Boolean> update(@RequestBody StorePaymentConfig config) {
        log.info("StorePaymentConfigController.update?id={}", config.getId());
        if (config.getId() == null) {
            return R.fail("配置ID不能为空");
        }
        try {
            fillUpdatedUser(config);
            boolean ok = storePaymentConfigService.updateById(config);
            return ok ? R.success("修改成功") : R.fail("修改失败");
        } catch (Exception e) {
            log.error("修改支付配置失败", e);
            return R.fail("修改失败：" + e.getMessage());
        }
    }

    @ApiOperationSupport(order = 2)
    @ApiOperation(value = "新增支付配置（带三个证书文件，证书内容直接存入表 store_payment_config）", notes = "multipart：storeId、appId 必填；appSecretCert、*CertPath 选填；三个文件：appPublicCert、alipayPublicCert、alipayRootCert（.crt/.pem/.cer）")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "storeId", value = "店铺ID", dataType = "int", paramType = "form", required = true),
            @ApiImplicitParam(name = "appId", value = "应用ID", dataType = "string", paramType = "form", required = true),
            @ApiImplicitParam(name = "appSecretCert", value = "应用私钥", dataType = "string", paramType = "form"),
            @ApiImplicitParam(name = "appPublicCert", value = "应用公钥证书文件", dataType = "file", paramType = "form"),
            @ApiImplicitParam(name = "alipayPublicCert", value = "支付宝公钥证书文件", dataType = "file", paramType = "form"),
            @ApiImplicitParam(name = "alipayRootCert", value = "支付宝根证书文件", dataType = "file", paramType = "form")
    })
    @PostMapping("/addWithCerts")
    public R<Boolean> addWithCerts(
            @RequestParam Integer storeId,
            @RequestParam String appId,
            @RequestParam(required = false) String appSecretCert,
            @RequestParam(required = false) String appPublicCertPath,
            @RequestParam(required = false) String alipayPublicCertPath,
            @RequestParam(required = false) String alipayRootCertPath,
            @RequestParam(value = "appPublicCert", required = false) MultipartFile appPublicCertFile,
            @RequestParam(value = "alipayPublicCert", required = false) MultipartFile alipayPublicCertFile,
            @RequestParam(value = "alipayRootCert", required = false) MultipartFile alipayRootCertFile) {
        log.info("StorePaymentConfigController.addWithCerts storeId={}, appId={}", storeId, appId);
        if (storeId == null) {
            return R.fail("店铺ID不能为空");
        }
        if (appId == null || appId.trim().isEmpty()) {
            return R.fail("应用ID不能为空");
        }
        try {
            StorePaymentConfig config = new StorePaymentConfig();
            config.setStoreId(storeId);
            config.setAppId(appId.trim());
            config.setAppSecretCert(appSecretCert);
            config.setAppPublicCertPath(appPublicCertPath);
            config.setAlipayPublicCertPath(alipayPublicCertPath);
            config.setAlipayRootCertPath(alipayRootCertPath);
            fillCertContent(config, appPublicCertFile, alipayPublicCertFile, alipayRootCertFile);
            fillCreatedUser(config);
            boolean ok = storePaymentConfigService.save(config);
            return ok ? R.success("新增成功") : R.fail("新增失败");
        } catch (Exception e) {
            log.error("新增支付配置（带证书）失败", e);
            return R.fail("新增失败：" + e.getMessage());
        }
    }

    @ApiOperationSupport(order = 3)
    @ApiOperation(value = "为已有配置上传/覆盖三个证书文件（内容存入表）", notes = "multipart：id 必填；三个文件：appPublicCert、alipayPublicCert、alipayRootCert，传哪个更新哪个")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "配置ID", dataType = "int", paramType = "form", required = true),
            @ApiImplicitParam(name = "appPublicCert", value = "应用公钥证书文件", dataType = "file", paramType = "form"),
            @ApiImplicitParam(name = "alipayPublicCert", value = "支付宝公钥证书文件", dataType = "file", paramType = "form"),
            @ApiImplicitParam(name = "alipayRootCert", value = "支付宝根证书文件", dataType = "file", paramType = "form")
    })
    @PostMapping("/uploadCerts")
    public R<Boolean> uploadCerts(
            @RequestParam Integer id,
            @RequestParam(value = "appPublicCert", required = false) MultipartFile appPublicCertFile,
            @RequestParam(value = "alipayPublicCert", required = false) MultipartFile alipayPublicCertFile,
            @RequestParam(value = "alipayRootCert", required = false) MultipartFile alipayRootCertFile) {
        log.info("StorePaymentConfigController.uploadCerts id={}", id);
        if (id == null) {
            return R.fail("配置ID不能为空");
        }
        StorePaymentConfig existing = storePaymentConfigService.getById(id);
        if (existing == null) {
            return R.fail("配置不存在");
        }
        try {
            fillCertContent(existing, appPublicCertFile, alipayPublicCertFile, alipayRootCertFile);
            fillUpdatedUser(existing);
            boolean ok = storePaymentConfigService.updateById(existing);
            return ok ? R.success("证书已更新") : R.fail("更新失败");
        } catch (Exception e) {
            log.error("上传证书失败", e);
            return R.fail("上传失败：" + e.getMessage());
        }
    }

    @ApiOperationSupport(order = 3)
    @ApiOperation(value = "将三个证书文件写入指定路径", notes = "从表读出证书内容，写入 targetPath 目录；文件名优先使用表中的 *_cert_name，未设置则用默认 app_public.crt、alipay_public.crt、alipay_root.crt。")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "配置ID", dataType = "int", paramType = "query", required = true),
            @ApiImplicitParam(name = "targetPath", value = "目标目录（绝对路径或相对路径），如 D:/certs/export 或 /opt/certs", dataType = "string", paramType = "query", required = true)
    })
    @GetMapping("/downloadCerts")
    public R<List<String>> downloadCerts(@RequestParam Integer id, @RequestParam String targetPath) {
        log.info("StorePaymentConfigController.downloadCerts id={}, targetPath={}", id, targetPath);
        if (id == null) {
            return R.fail("配置ID不能为空");
        }
        if (targetPath == null || targetPath.trim().isEmpty()) {
            return R.fail("目标路径不能为空");
        }
        if (targetPath.contains("..")) {
            return R.fail("目标路径不允许包含 ..");
        }
        StorePaymentConfig config = storePaymentConfigService.getById(id);
        if (config == null) {
            return R.fail("配置不存在");
        }
        try {
            List<String> writtenPaths = writeCertsToPath(config, targetPath.trim());
            if (writtenPaths.isEmpty()) {
                return R.fail("该配置下暂无证书内容可写入");
            }
            return R.data(writtenPaths);
        } catch (Exception e) {
            log.error("写入证书文件失败", e);
            return R.fail("写入失败：" + e.getMessage());
        }
    }

    /** 将表中三个证书内容（byte[] 原样）写入指定目录，不经过字符编码，返回已写入文件的绝对路径列表 */
    private List<String> writeCertsToPath(StorePaymentConfig config, String targetPath) throws Exception {
        Path dir = Paths.get(targetPath);
        Files.createDirectories(dir);
        List<String> written = new ArrayList<>();
        if (config.getAppPublicCert() != null && config.getAppPublicCert().length > 0) {
            String name = safeCertFileName(config.getAppPublicCertName(), "app_public.crt");
            Path file = dir.resolve(name);
            Files.write(file, config.getAppPublicCert());
            written.add(file.toAbsolutePath().toString());
        }
        if (config.getAlipayPublicCert() != null && config.getAlipayPublicCert().length > 0) {
            String name = safeCertFileName(config.getAlipayPublicCertName(), "alipay_public.crt");
            Path file = dir.resolve(name);
            Files.write(file, config.getAlipayPublicCert());
            written.add(file.toAbsolutePath().toString());
        }
        if (config.getAlipayRootCert() != null && config.getAlipayRootCert().length > 0) {
            String name = safeCertFileName(config.getAlipayRootCertName(), "alipay_root.crt");
            Path file = dir.resolve(name);
            Files.write(file, config.getAlipayRootCert());
            written.add(file.toAbsolutePath().toString());
        }
        return written;
    }

    /** 使用表存的文件名（仅取最后一段且不含路径），非法则用默认名 */
    private String safeCertFileName(String storedName, String defaultName) {
        if (storedName == null || storedName.trim().isEmpty()) {
            return defaultName;
        }
        String name = storedName.trim();
        int last = Math.max(name.lastIndexOf('/'), name.lastIndexOf('\\'));
        if (last >= 0 && last < name.length() - 1) {
            name = name.substring(last + 1);
        }
        if (name.isEmpty() || name.contains("..")) {
            return defaultName;
        }
        return name;
    }

    /** 将三个证书文件内容原样（byte[]）读入实体存入表，不经过字符编码，保证存取一致 */
    private void fillCertContent(StorePaymentConfig config,
                                 MultipartFile appPublicCertFile,
                                 MultipartFile alipayPublicCertFile,
                                 MultipartFile alipayRootCertFile) throws Exception {
        if (appPublicCertFile != null && !appPublicCertFile.isEmpty()) {
            config.setAppPublicCert(appPublicCertFile.getBytes());
            String fn = appPublicCertFile.getOriginalFilename();
            if (fn != null && !fn.trim().isEmpty()) {
                config.setAppPublicCertName(fn.trim());
            }
        }
        if (alipayPublicCertFile != null && !alipayPublicCertFile.isEmpty()) {
            config.setAlipayPublicCert(alipayPublicCertFile.getBytes());
            String fn = alipayPublicCertFile.getOriginalFilename();
            if (fn != null && !fn.trim().isEmpty()) {
                config.setAlipayPublicCertName(fn.trim());
            }
        }
        if (alipayRootCertFile != null && !alipayRootCertFile.isEmpty()) {
            config.setAlipayRootCert(alipayRootCertFile.getBytes());
            String fn = alipayRootCertFile.getOriginalFilename();
            if (fn != null && !fn.trim().isEmpty()) {
                config.setAlipayRootCertName(fn.trim());
            }
        }
    }

    @ApiOperationSupport(order = 4)
    @ApiOperation("删除支付配置")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "配置ID", dataType = "Integer", paramType = "query", required = true)
    })
    @PostMapping("/delete")
    public R<Boolean> delete(@RequestParam Integer id) {
        log.info("StorePaymentConfigController.delete?id={}", id);
        if (id == null) {
            return R.fail("配置ID不能为空");
        }
        try {
            boolean ok = storePaymentConfigService.removeById(id);
            return ok ? R.success("删除成功") : R.fail("删除失败");
        } catch (Exception e) {
            log.error("删除支付配置失败", e);
            return R.fail("删除失败：" + e.getMessage());
        }
    }

    @ApiOperationSupport(order = 5)
    @ApiOperation("根据ID查询支付配置详情")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "配置ID", dataType = "Integer", paramType = "query", required = true)
    })
    @GetMapping("/detail")
    public R<StorePaymentConfig> detail(@RequestParam Integer id) {
        log.info("StorePaymentConfigController.detail?id={}", id);
        if (id == null) {
            return R.fail("配置ID不能为空");
        }
        try {
            StorePaymentConfig config = storePaymentConfigService.getById(id);
            if (config == null) {
                return R.fail("配置不存在");
            }
            return R.data(config);
        } catch (Exception e) {
            log.error("查询支付配置详情失败", e);
            return R.fail("查询失败：" + e.getMessage());
        }
    }


    @ApiOperationSupport(order = 7)
    @ApiOperation("根据店铺ID查询支付配置")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "storeId", value = "店铺ID", dataType = "Integer", paramType = "query", required = true)
    })
    @GetMapping("/getByStoreId")
    public R<StorePaymentConfig> getByStoreId(@RequestParam Integer storeId) {
        log.info("StorePaymentConfigController.getByStoreId?storeId={}", storeId);
        if (storeId == null) {
            return R.fail("店铺ID不能为空");
        }
        try {
            StorePaymentConfig config = storePaymentConfigService.getByStoreId(storeId);
            if (config == null) {
                return R.fail("该店铺暂无支付配置");
            }
            return R.data(config);
        } catch (Exception e) {
            log.error("根据店铺ID查询支付配置失败", e);
            return R.fail("查询失败：" + e.getMessage());
        }
    }

    @ApiOperationSupport(order = 8)
    @ApiOperation("根据店铺用户ID查询支付配置（设置收款账号）")
    @ApiImplicitParam(name = "storeUserId", value = "店铺用户ID（store_user.id）", dataType = "int", paramType = "query", required = true)
    @GetMapping("/getByStoreUserId")
    public R<StorePaymentConfig> getByStoreUserId(@RequestParam Integer storeUserId) {
        log.info("StorePaymentConfigController.getByStoreUserId storeUserId={}", storeUserId);
        if (storeUserId == null) {
            return R.fail("店铺用户ID不能为空");
        }
        try {
            StorePaymentConfig config = storePaymentConfigService.getByStoreUserId(storeUserId);
            return R.data(config);
        } catch (Exception e) {
            log.error("根据店铺用户ID查询支付配置失败", e);
            return R.fail("查询失败：" + e.getMessage());
        }
    }

    @ApiOperationSupport(order = 9)
    @ApiOperation(value = "设置收款账号-保存微信", notes = "按 store_user_id 新增或更新微信支付参数及证书文件（内容存入表）")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "storeUserId", value = "店铺用户ID（store_user.id）", dataType = "int", paramType = "form", required = true),
            @ApiImplicitParam(name = "wechatMiniAppId", value = "微信支付mini appId", dataType = "string", paramType = "form"),
            @ApiImplicitParam(name = "wechatAppId", value = "微信appId", dataType = "string", paramType = "form"),
            @ApiImplicitParam(name = "wechatMchId", value = "微信mchId", dataType = "string", paramType = "form"),
            @ApiImplicitParam(name = "merchantSerialNumber", value = "API证书序列号", dataType = "string", paramType = "form"),
            @ApiImplicitParam(name = "apiV3Key", value = "APIv3 Key", dataType = "string", paramType = "form"),
            @ApiImplicitParam(name = "wechatPayPublicKeyId", value = "支付公钥ID", dataType = "string", paramType = "form"),
            @ApiImplicitParam(name = "wechatPrivateKeyFile", value = "私钥证书", dataType = "file", paramType = "form"),
            @ApiImplicitParam(name = "wechatPayPublicKeyFile", value = "公钥证书", dataType = "file", paramType = "form")
    })
    @PostMapping("/saveWechatByStoreUserId")
    public R<Integer> saveWechatByStoreUserId(
            @RequestParam Integer storeUserId,
            @RequestParam(required = false) String wechatMiniAppId,
            @RequestParam(required = false) String wechatAppId,
            @RequestParam(required = false) String wechatMchId,
            @RequestParam(required = false) String merchantSerialNumber,
            @RequestParam(required = false) String apiV3Key,
            @RequestParam(required = false) String wechatPayPublicKeyId,
            @RequestParam(value = "wechatPrivateKeyFile", required = false) MultipartFile wechatPrivateKeyFile,
            @RequestParam(value = "wechatPayPublicKeyFile", required = false) MultipartFile wechatPayPublicKeyFile) {

        log.info("StorePaymentConfigController.saveWechatByStoreUserId storeUserId={}", storeUserId);
        if (storeUserId == null) {
            return R.fail("店铺用户ID不能为空");
        }
        try {
            StoreUser storeUser = storeUserService.getById(storeUserId);
            if (storeUser == null) {
                return R.fail("店铺用户不存在");
            }
            StorePaymentConfig config = storePaymentConfigService.getByStoreUserId(storeUserId);
            if (config == null) {
                config = new StorePaymentConfig();
                config.setStoreId(storeUser.getStoreId());
                config.setStoreUserId(storeUserId);
                config.setAppId(wechatAppId != null ? wechatAppId : "");
                fillCreatedUser(config);
            } else {
                fillUpdatedUser(config);
            }
            config.setWechatMiniAppId(wechatMiniAppId);
            config.setWechatAppId(wechatAppId);
            config.setWechatMchId(wechatMchId);
            config.setMerchantSerialNumber(merchantSerialNumber);
            config.setApiV3Key(apiV3Key);
            config.setWechatPayPublicKeyId(wechatPayPublicKeyId);
            if (wechatPrivateKeyFile != null && !wechatPrivateKeyFile.isEmpty()) {
                config.setWechatPrivateKeyFile(wechatPrivateKeyFile.getBytes());
                String fn = wechatPrivateKeyFile.getOriginalFilename();
                if (fn != null && !fn.trim().isEmpty()) {
                    config.setWechatPrivateKeyName(fn.trim());
                }
            }
            if (wechatPayPublicKeyFile != null && !wechatPayPublicKeyFile.isEmpty()) {
                config.setWechatPayPublicKeyFile(wechatPayPublicKeyFile.getBytes());
                String fn = wechatPayPublicKeyFile.getOriginalFilename();
                if (fn != null && !fn.trim().isEmpty()) {
                    config.setWechatPayPublicKeyFileName(fn.trim());
                }
            }
            boolean ok = config.getId() == null ? storePaymentConfigService.save(config) : storePaymentConfigService.updateById(config);
            if (!ok) {
                return R.fail("保存失败");
            }
            return R.data(config.getId());
        } catch (Exception e) {
            log.error("保存微信收款账号失败 storeUserId={}", storeUserId, e);
            return R.fail("保存失败：" + e.getMessage());
        }
    }

    @ApiOperationSupport(order = 10)
    @ApiOperation(value = "设置收款账号-保存支付宝", notes = "按 store_user_id 新增或更新支付宝支付参数及证书文件（内容存入表）")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "storeUserId", value = "店铺用户ID（store_user.id）", dataType = "int", paramType = "form", required = true),
            @ApiImplicitParam(name = "appId", value = "应用ID", dataType = "string", paramType = "form"),
            @ApiImplicitParam(name = "appSecretCert", value = "应用私钥", dataType = "string", paramType = "form"),
            @ApiImplicitParam(name = "appPublicCert", value = "应用公钥证书", dataType = "file", paramType = "form"),
            @ApiImplicitParam(name = "alipayPublicCert", value = "支付宝公钥证书", dataType = "file", paramType = "form"),
            @ApiImplicitParam(name = "alipayRootCert", value = "支付宝根证书", dataType = "file", paramType = "form")
    })
    @PostMapping("/saveAlipayByStoreUserId")
    public R<Integer> saveAlipayByStoreUserId(
            @RequestParam Integer storeUserId,
            @RequestParam(required = false) String appId,
            @RequestParam(required = false) String appSecretCert,
            @RequestParam(value = "appPublicCert", required = false) MultipartFile appPublicCertFile,
            @RequestParam(value = "alipayPublicCert", required = false) MultipartFile alipayPublicCertFile,
            @RequestParam(value = "alipayRootCert", required = false) MultipartFile alipayRootCertFile) {
        log.info("StorePaymentConfigController.saveAlipayByStoreUserId storeUserId={}", storeUserId);
        if (storeUserId == null) {
            return R.fail("店铺用户ID不能为空");
        }
        try {
            StoreUser storeUser = storeUserService.getById(storeUserId);
            if (storeUser == null) {
                return R.fail("店铺用户不存在");
            }
            StorePaymentConfig config = storePaymentConfigService.getByStoreUserId(storeUserId);
            if (config == null) {
                config = new StorePaymentConfig();
                config.setStoreId(storeUser.getStoreId());
                config.setStoreUserId(storeUserId);
                config.setAppId(appId != null ? appId : "");
                fillCreatedUser(config);
            } else {
                fillUpdatedUser(config);
            }
            config.setAppId(appId);
            config.setAppSecretCert(appSecretCert);
            fillCertContent(config, appPublicCertFile, alipayPublicCertFile, alipayRootCertFile);
            boolean ok = config.getId() == null ? storePaymentConfigService.save(config) : storePaymentConfigService.updateById(config);
            if (!ok) {
                return R.fail("保存失败");
            }
            return R.data(config.getId());
        } catch (Exception e) {
            log.error("保存支付宝收款账号失败 storeUserId={}", storeUserId, e);
            return R.fail("保存失败：" + e.getMessage());
        }
    }

    @ApiOperationSupport(order = 11)
    @ApiOperation(value = "设置收款账号-保存银行卡", notes = "按 store_user_id 新增或更新银行卡号、开户银行名称（与微信/支付宝配置同一条 store_payment_config 记录）")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "storeUserId", value = "店铺用户ID（store_user.id）", dataType = "int", paramType = "form", required = true),
            @ApiImplicitParam(name = "bankCardNo", value = "银行卡号", dataType = "string", paramType = "form", required = true),
            @ApiImplicitParam(name = "bankName", value = "开户银行名称", dataType = "string", paramType = "form", required = true)
    })
    @PostMapping("/saveBankByStoreUserId")
    public R<Integer> saveBankByStoreUserId(
            @RequestParam Integer storeUserId,
            @RequestParam String bankCardNo,
            @RequestParam String bankName) {
        log.info("StorePaymentConfigController.saveBankByStoreUserId storeUserId={}", storeUserId);
        if (storeUserId == null) {
            return R.fail("店铺用户ID不能为空");
        }
        if (bankCardNo == null || bankCardNo.trim().isEmpty()) {
            return R.fail("银行卡号不能为空");
        }
        if (bankName == null || bankName.trim().isEmpty()) {
            return R.fail("银行名称不能为空");
        }
        try {
            StoreUser storeUser = storeUserService.getById(storeUserId);
            if (storeUser == null) {
                return R.fail("店铺用户不存在");
            }
            StorePaymentConfig config = storePaymentConfigService.getByStoreUserId(storeUserId);
            if (config == null) {
                config = new StorePaymentConfig();
                config.setStoreId(storeUser.getStoreId());
                config.setStoreUserId(storeUserId);
                config.setAppId("");
                fillCreatedUser(config);
            } else {
                fillUpdatedUser(config);
            }
            config.setBankCardNo(bankCardNo.trim());
            config.setBankName(bankName.trim());
            boolean ok = config.getId() == null ? storePaymentConfigService.save(config) : storePaymentConfigService.updateById(config);
            if (!ok) {
                return R.fail("保存失败");
            }
            return R.data(config.getId());
        } catch (Exception e) {
            log.error("保存银行卡收款信息失败 storeUserId={}", storeUserId, e);
            return R.fail("保存失败：" + e.getMessage());
        }
    }

    @ApiOperationSupport(order = 12)
    @ApiOperation(value = "设置收款账号-保存商家微信（展示）", notes = "按 store_user_id 新增或更新 store_wechat_id、store_wechat_name（与支付商户微信配置字段不同）")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "storeUserId", value = "店铺用户ID（store_user.id）", dataType = "int", paramType = "form", required = true),
            @ApiImplicitParam(name = "storeWechatId", value = "商家微信 appid", dataType = "string", paramType = "form", required = true),
            @ApiImplicitParam(name = "storeWechatName", value = "商家微信名称", dataType = "string", paramType = "form", required = true)
    })
    @PostMapping("/saveMerchantWechatByStoreUserId")
    public R<Integer> saveMerchantWechatByStoreUserId(
            @RequestParam Integer storeUserId,
            @RequestParam String storeWechatId,
            @RequestParam String storeWechatName) {
        log.info("StorePaymentConfigController.saveMerchantWechatByStoreUserId storeUserId={}", storeUserId);
        if (storeUserId == null) {
            return R.fail("店铺用户ID不能为空");
        }
        if (storeWechatId == null || storeWechatId.trim().isEmpty()) {
            return R.fail("商家微信 appid 不能为空");
        }
        if (storeWechatName == null || storeWechatName.trim().isEmpty()) {
            return R.fail("商家微信名称不能为空");
        }
        try {
            StoreUser storeUser = storeUserService.getById(storeUserId);
            if (storeUser == null) {
                return R.fail("店铺用户不存在");
            }
            StorePaymentConfig config = storePaymentConfigService.getByStoreUserId(storeUserId);
            if (config == null) {
                config = new StorePaymentConfig();
                config.setStoreId(storeUser.getStoreId());
                config.setStoreUserId(storeUserId);
                config.setAppId("");
                fillCreatedUser(config);
            } else {
                fillUpdatedUser(config);
            }
            config.setStoreWechatId(storeWechatId.trim());
            config.setStoreWechatName(storeWechatName.trim());
            boolean ok = config.getId() == null ? storePaymentConfigService.save(config) : storePaymentConfigService.updateById(config);
            if (!ok) {
                return R.fail("保存失败");
            }
            return R.data(config.getId());
        } catch (Exception e) {
            log.error("保存商家微信信息失败 storeUserId={}", storeUserId, e);
            return R.fail("保存失败：" + e.getMessage());
        }
    }

    @ApiOperationSupport(order = 13)
    @ApiOperation(value = "设置收款账号-保存商家支付宝（展示）", notes = "按 store_user_id 新增或更新 store_ali_id、store_ali_name（与支付宝应用 appId 等支付配置字段不同）")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "storeUserId", value = "店铺用户ID（store_user.id）", dataType = "int", paramType = "form", required = true),
            @ApiImplicitParam(name = "storeAliId", value = "商家支付宝 appid", dataType = "string", paramType = "form", required = true),
            @ApiImplicitParam(name = "storeAliName", value = "商家支付宝名称", dataType = "string", paramType = "form", required = true)
    })
    @PostMapping("/saveMerchantAlipayByStoreUserId")
    public R<Integer> saveMerchantAlipayByStoreUserId(
            @RequestParam Integer storeUserId,
            @RequestParam String storeAliId,
            @RequestParam String storeAliName) {
        log.info("StorePaymentConfigController.saveMerchantAlipayByStoreUserId storeUserId={}", storeUserId);
        if (storeUserId == null) {
            return R.fail("店铺用户ID不能为空");
        }
        if (storeAliId == null || storeAliId.trim().isEmpty()) {
            return R.fail("商家支付宝 appid 不能为空");
        }
        if (storeAliName == null || storeAliName.trim().isEmpty()) {
            return R.fail("商家支付宝名称不能为空");
        }
        try {
            StoreUser storeUser = storeUserService.getById(storeUserId);
            if (storeUser == null) {
                return R.fail("店铺用户不存在");
            }
            StorePaymentConfig config = storePaymentConfigService.getByStoreUserId(storeUserId);
            if (config == null) {
                config = new StorePaymentConfig();
                config.setStoreId(storeUser.getStoreId());
                config.setStoreUserId(storeUserId);
                config.setAppId("");
                fillCreatedUser(config);
            } else {
                fillUpdatedUser(config);
            }
            config.setStoreAliId(storeAliId.trim());
            config.setStoreAliName(storeAliName.trim());
            boolean ok = config.getId() == null ? storePaymentConfigService.save(config) : storePaymentConfigService.updateById(config);
            if (!ok) {
                return R.fail("保存失败");
            }
            return R.data(config.getId());
        } catch (Exception e) {
            log.error("保存商家支付宝信息失败 storeUserId={}", storeUserId, e);
            return R.fail("保存失败：" + e.getMessage());
        }
    }

    @ApiOperationSupport(order = 14)
    @ApiOperation("分页查询支付配置列表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "page", value = "页码", dataType = "Integer", paramType = "query", defaultValue = "1"),
            @ApiImplicitParam(name = "size", value = "每页条数", dataType = "Integer", paramType = "query", defaultValue = "10"),
            @ApiImplicitParam(name = "storeId", value = "店铺ID", dataType = "Integer", paramType = "query"),
            @ApiImplicitParam(name = "appId", value = "应用ID（模糊）", dataType = "String", paramType = "query")
    })
    @GetMapping("/page")
    public R<IPage<StorePaymentConfig>> page(
            @RequestParam(defaultValue = "1") Integer page,
            @RequestParam(defaultValue = "10") Integer size,
            @RequestParam(required = false) Integer storeId,
            @RequestParam(required = false) String appId) {
        log.info("StorePaymentConfigController.page?page={}, size={}, storeId={}, appId={}", page, size, storeId, appId);
        try {
            Page<StorePaymentConfig> pageParam = new Page<>(page, size);
            IPage<StorePaymentConfig> result = storePaymentConfigService.pageList(pageParam, storeId, appId);
            return R.data(result);
        } catch (Exception e) {
            log.error("分页查询支付配置失败", e);
            return R.fail("查询失败：" + e.getMessage());
        }
    }

    @ApiOperationSupport(order = 15)
    @ApiOperation(value = "新增/更新微信支付配置信息", notes = "按 storeId 查找配置，存在则更新微信字段；不存在则新建一条仅含 storeId 与微信信息的配置。可传表单+两个证书文件（内容存入表）。")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "storeId", value = "店铺ID", dataType = "int", paramType = "form", required = true),
            @ApiImplicitParam(name = "wechatAppId", value = "微信appId", dataType = "string", paramType = "form"),
            @ApiImplicitParam(name = "wechatMchId", value = "微信mchId", dataType = "string", paramType = "form"),
            @ApiImplicitParam(name = "merchantSerialNumber", value = "微信商户API证书序列号", dataType = "string", paramType = "form"),
            @ApiImplicitParam(name = "apiV3Key", value = "微信商户的 APIv3 Key", dataType = "string", paramType = "form"),
            @ApiImplicitParam(name = "wechatPayPublicKeyId", value = "微信支付公钥ID", dataType = "string", paramType = "form"),
            @ApiImplicitParam(name = "wechatPrivateKeyPath", value = "微信私钥路径", dataType = "string", paramType = "form"),
            @ApiImplicitParam(name = "wechatPrivateKeyName", value = "微信私钥文件名", dataType = "string", paramType = "form"),
            @ApiImplicitParam(name = "wechatPayPublicKeyFilePath", value = "微信公钥路径", dataType = "string", paramType = "form"),
            @ApiImplicitParam(name = "wechatPayPublicKeyFileName", value = "微信公钥文件名", dataType = "string", paramType = "form"),
            @ApiImplicitParam(name = "wechatPrivateKeyFile", value = "微信私钥文件（内容存入表）", dataType = "file", paramType = "form"),
            @ApiImplicitParam(name = "wechatPayPublicKeyFile", value = "微信公钥文件（内容存入表）", dataType = "file", paramType = "form")
    })
    @PostMapping("/saveWechat")
    public R<Boolean> saveWechat(
            @RequestParam Integer storeId,
            @RequestParam(required = false) String wechatAppId,
            @RequestParam(required = false) String wechatMchId,
            @RequestParam(required = false) String merchantSerialNumber,
            @RequestParam(required = false) String apiV3Key,
            @RequestParam(required = false) String wechatPayPublicKeyId,
            @RequestParam(required = false) String wechatPrivateKeyPath,
            @RequestParam(required = false) String wechatPrivateKeyName,
            @RequestParam(required = false) String wechatPayPublicKeyFilePath,
            @RequestParam(required = false) String wechatPayPublicKeyFileName,
            @RequestParam(value = "wechatPrivateKeyFile", required = false) MultipartFile wechatPrivateKeyFile,
            @RequestParam(value = "wechatPayPublicKeyFile", required = false) MultipartFile wechatPayPublicKeyFile) {
        log.info("StorePaymentConfigController.saveWechat storeId={}", storeId);
        if (storeId == null) {
            return R.fail("店铺ID不能为空");
        }
        try {
            StorePaymentConfig config = storePaymentConfigService.getByStoreId(storeId);
            if (config == null) {
                config = new StorePaymentConfig();
                config.setStoreId(storeId);
                config.setAppId(wechatAppId != null ? wechatAppId : "");
                fillCreatedUser(config);
            } else {
                fillUpdatedUser(config);
            }
            config.setWechatAppId(wechatAppId);
            config.setWechatMchId(wechatMchId);
            config.setMerchantSerialNumber(merchantSerialNumber);
            config.setApiV3Key(apiV3Key);
            config.setWechatPayPublicKeyId(wechatPayPublicKeyId);
            config.setWechatPrivateKeyPath(wechatPrivateKeyPath);
            config.setWechatPrivateKeyName(wechatPrivateKeyName);
            config.setWechatPayPublicKeyFilePath(wechatPayPublicKeyFilePath);
            config.setWechatPayPublicKeyFileName(wechatPayPublicKeyFileName);
            if (wechatPrivateKeyFile != null && !wechatPrivateKeyFile.isEmpty()) {
                config.setWechatPrivateKeyFile(wechatPrivateKeyFile.getBytes());
                if (wechatPrivateKeyName == null || wechatPrivateKeyName.trim().isEmpty()) {
                    String fn = wechatPrivateKeyFile.getOriginalFilename();
                    if (fn != null && !fn.trim().isEmpty()) {
                        config.setWechatPrivateKeyName(fn.trim());
                    }
                }
            }
            if (wechatPayPublicKeyFile != null && !wechatPayPublicKeyFile.isEmpty()) {
                config.setWechatPayPublicKeyFile(wechatPayPublicKeyFile.getBytes());
                if (wechatPayPublicKeyFileName == null || wechatPayPublicKeyFileName.trim().isEmpty()) {
                    String fn = wechatPayPublicKeyFile.getOriginalFilename();
                    if (fn != null && !fn.trim().isEmpty()) {
                        config.setWechatPayPublicKeyFileName(fn.trim());
                    }
                }
            }
            boolean ok = config.getId() == null ? storePaymentConfigService.save(config) : storePaymentConfigService.updateById(config);
            return ok ? R.success("微信配置保存成功") : R.fail("保存失败");
        } catch (Exception e) {
            log.error("保存微信支付配置失败", e);
            return R.fail("保存失败：" + e.getMessage());
        }
    }

    private void fillCreatedUser(StorePaymentConfig config) {
        try {
            JSONObject userInfo = JwtUtil.getCurrentUserInfo();
            if (userInfo != null) {
                config.setCreatedUserId(userInfo.getInteger("userId"));
            }
        } catch (Exception e) {
            log.warn("获取当前用户失败: {}", e.getMessage());
        }
    }

    private void fillUpdatedUser(StorePaymentConfig config) {
        try {
            JSONObject userInfo = JwtUtil.getCurrentUserInfo();
            if (userInfo != null) {
                config.setUpdatedUserId(userInfo.getInteger("userId"));
            }
        } catch (Exception e) {
            log.warn("获取当前用户失败: {}", e.getMessage());
        }
    }
}
