<template>
  <el-dialog
    :model-value="modelValue"
    title="设置收款账号"
    width="520px"
    destroy-on-close
    append-to-body
    @update:model-value="emit('update:modelValue', $event)"
  >
    <el-form ref="formRef" :model="form" :rules="rules" label-width="140px" label-position="top">
      <el-form-item label="账号类型" prop="accountType">
        <el-radio-group v-model="form.accountType">
          <el-radio value="wechat"> 微信 </el-radio>
          <el-radio value="alipay"> 支付宝 </el-radio>
        </el-radio-group>
      </el-form-item>
      <el-form-item label="appid" prop="wechatAppid" v-if="form.accountType === 'wechat'">
        <el-input v-model="form.wechatAppid" placeholder="请输入" clearable />
      </el-form-item>
      <el-form-item label="mchld" prop="wechatMchld" v-if="form.accountType === 'wechat'">
        <el-input v-model="form.wechatMchld" placeholder="请输入" clearable />
      </el-form-item>
      <el-form-item label="小程序appid" prop="wechatMiniAppId" v-if="form.accountType === 'wechat'">
        <el-input v-model="form.wechatMiniAppId" placeholder="请输入" clearable />
      </el-form-item>
      <el-form-item label="API证书序列号" prop="wechatApiCertSerialNo" v-if="form.accountType === 'wechat'">
        <el-input v-model="form.wechatApiCertSerialNo" placeholder="请输入" clearable />
      </el-form-item>
      <el-form-item label="APIv3 Key" prop="wechatApiV3Key" v-if="form.accountType === 'wechat'">
        <el-input v-model="form.wechatApiV3Key" placeholder="请输入" clearable />
      </el-form-item>
      <el-form-item label="支付公钥ID" prop="wechatPayPublicKeyId" v-if="form.accountType === 'wechat'">
        <el-input v-model="form.wechatPayPublicKeyId" placeholder="请输入" clearable />
      </el-form-item>
      <el-form-item label="私钥证书" prop="wechatPrivateKeyFile" v-if="form.accountType === 'wechat'">
        <el-upload
          v-model:file-list="form.wechatPrivateKeyFile"
          class="set-pay-key-upload"
          drag
          :auto-upload="false"
          :limit="1"
          accept=".pem"
          :on-exceed="() => ElMessage.warning('最多上传1个文件')"
        >
          <div class="set-pay-upload-box">
            <el-icon :size="32" color="#6c8ff8">
              <UploadFilled />
            </el-icon>
            <p>点击或拖拽文件至此处上传</p>
            <span>支持.pem 格式文件，大小不超过2MB</span>
          </div>
        </el-upload>
      </el-form-item>
      <el-form-item label="公钥证书" prop="wechatPayPublicKeyFile" v-if="form.accountType === 'wechat'">
        <el-upload
          v-model:file-list="form.wechatPayPublicKeyFile"
          class="set-pay-key-upload"
          drag
          :auto-upload="false"
          :limit="1"
          accept=".pem"
          :on-exceed="() => ElMessage.warning('最多上传1个文件')"
        >
          <div class="set-pay-upload-box">
            <el-icon :size="32" color="#6c8ff8">
              <UploadFilled />
            </el-icon>
            <p>点击或拖拽文件至此处上传</p>
            <span>支持.pem 格式文件，大小不超过2MB</span>
          </div>
        </el-upload>
      </el-form-item>

      <!-- 支付宝 -->
      <el-form-item label="应用ID" prop="aliAppid" v-if="form.accountType === 'alipay'">
        <el-input v-model="form.aliAppid" placeholder="请输入" clearable />
      </el-form-item>
      <el-form-item label="应用私钥" prop="aliPrivateId" v-if="form.accountType === 'alipay'">
        <el-input v-model="form.aliPrivateId" placeholder="请输入" clearable />
      </el-form-item>
      <el-form-item label="应用公钥证书" prop="appPublicCertFile" v-if="form.accountType === 'alipay'">
        <el-upload
          v-model:file-list="form.appPublicCertFile"
          class="set-pay-key-upload"
          drag
          :auto-upload="false"
          :limit="1"
          accept=".pem"
          :on-exceed="() => ElMessage.warning('最多上传1个文件')"
        >
          <div class="set-pay-upload-box">
            <el-icon :size="32" color="#6c8ff8">
              <UploadFilled />
            </el-icon>
            <p>点击或拖拽文件至此处上传</p>
            <span>支持.pem 格式文件，大小不超过2MB</span>
          </div>
        </el-upload>
      </el-form-item>
      <el-form-item label="支付宝公钥证书" prop="alipayPublicCertFile" v-if="form.accountType === 'alipay'">
        <el-upload
          v-model:file-list="form.alipayPublicCertFile"
          class="set-pay-key-upload"
          drag
          :auto-upload="false"
          :limit="1"
          accept=".pem"
          :on-exceed="() => ElMessage.warning('最多上传1个文件')"
        >
          <div class="set-pay-upload-box">
            <el-icon :size="32" color="#6c8ff8">
              <UploadFilled />
            </el-icon>
            <p>点击或拖拽文件至此处上传</p>
            <span>支持.pem 格式文件，大小不超过2MB</span>
          </div>
        </el-upload>
      </el-form-item>
      <el-form-item label="支付宝根证书" prop="alipayRootCertFile" v-if="form.accountType === 'alipay'">
        <el-upload
          v-model:file-list="form.alipayRootCertFile"
          class="set-pay-key-upload"
          drag
          :auto-upload="false"
          :limit="1"
          accept=".pem"
          :on-exceed="() => ElMessage.warning('最多上传1个文件')"
        >
          <div class="set-pay-upload-box">
            <el-icon :size="32" color="#6c8ff8">
              <UploadFilled />
            </el-icon>
            <p>点击或拖拽文件至此处上传</p>
            <span>支持.pem 格式文件，大小不超过2MB</span>
          </div>
        </el-upload>
      </el-form-item>
    </el-form>
    <template #footer>
      <el-button @click="emit('update:modelValue', false)"> 取消 </el-button>
      <el-button type="primary" @click="submit"> 确定 </el-button>
    </template>
  </el-dialog>
</template>

<script setup lang="ts">
import { ref, reactive, watch } from "vue";
import { ElMessage, type FormInstance, type UploadUserFile } from "element-plus";
import { UploadFilled } from "@element-plus/icons-vue";
import { getPaymentStoreUserId, saveWechatWithFiles, saveAlipayWithFiles } from "@/api/modules/newLoginApi";
import { localGet } from "@/utils/index";

const props = defineProps<{
  modelValue: boolean;
}>();

const emit = defineEmits<{
  (e: "update:modelValue", value: boolean): void;
  (e: "success"): void;
  (e: "hasConfig", value: boolean): void;
}>();

const formRef = ref<FormInstance>();
const form = reactive({
  accountType: "wechat",
  wechatAppid: "",
  wechatMchld: "",
  wechatMiniAppId: "",
  wechatApiCertSerialNo: "",
  wechatApiV3Key: "",
  wechatPayPublicKeyId: null as string | null,
  wechatPrivateKeyFile: [] as UploadUserFile[],
  wechatPayPublicKeyFile: [] as UploadUserFile[],
  aliAppid: "",
  aliPrivateId: "",
  alipayRootCertFile: [] as UploadUserFile[],
  alipayPublicCertFile: [] as UploadUserFile[],
  appPublicCertFile: [] as UploadUserFile[]
});

const rules = ref({
  accountType: [{ required: true, message: "请选择账号类型", trigger: "change" }],
  wechatAppid: [{ required: true, message: "请输入appid", trigger: "blur" }],
  wechatMchld: [{ required: true, message: "请输入mchId", trigger: "blur" }],
  wechatApiCertSerialNo: [{ required: true, message: "请输入API证书序列号", trigger: "blur" }],
  wechatApiV3Key: [{ required: true, message: "请输入APIv3 Key", trigger: "blur" }],
  wechatPayPublicKeyId: [{ required: true, message: "请输入支付公钥ID", trigger: "blur" }],
  wechatMiniAppId: [{ required: true, message: "请输入小程序AppId", trigger: "blur" }],
  wechatPrivateKeyFile: [{ required: true, type: "array" as const, min: 1, message: "请上传私钥证书", trigger: "change" }],
  wechatPayPublicKeyFile: [{ required: true, type: "array" as const, min: 1, message: "请上传公钥证书", trigger: "change" }]
});

const base64ToFile = (base64Str: string, fileName: string): File => {
  const bstr = atob(base64Str);
  const u8arr = new Uint8Array(bstr.length);
  for (let i = 0; i < bstr.length; i++) u8arr[i] = bstr.charCodeAt(i);
  return new File([u8arr], fileName, { type: "application/x-pem-file" });
};

const fetchPayAccountConfig = async () => {
  const storeUserId = localGet("geeker-user")?.userInfo?.id;
  if (!storeUserId) return;
  const res: any = await getPaymentStoreUserId({ storeUserId });
  if (res?.code !== 200 || !res.data) {
    emit("hasConfig", false);
    return;
  }
  const data = res.data;
  emit("hasConfig", !!(data.wechatAppId || data.appId));

  if (data.wechatAppId) {
    form.accountType = "wechat";
    form.wechatAppid = data.wechatAppId ?? "";
    form.wechatMchld = data.wechatMchId ?? "";
    form.wechatMiniAppId = data.wechatMiniAppId ?? "";
    form.wechatApiCertSerialNo = data.merchantSerialNumber ?? "";
    form.wechatApiV3Key = data.apiV3Key ?? "";
    form.wechatPayPublicKeyId = data.wechatPayPublicKeyId ?? null;
    form.wechatPrivateKeyFile = [];
    form.wechatPayPublicKeyFile = [];
    if (data.wechatPrivateKeyFile && data.wechatPrivateKeyName) {
      const file = base64ToFile(data.wechatPrivateKeyFile, data.wechatPrivateKeyName);
      form.wechatPrivateKeyFile = [{ name: file.name, raw: file, status: "success", uid: Date.now() } as UploadUserFile];
    }
    if (data.wechatPayPublicKeyFile && data.wechatPayPublicKeyFileName) {
      const file = base64ToFile(data.wechatPayPublicKeyFile, data.wechatPayPublicKeyFileName);
      form.wechatPayPublicKeyFile = [{ name: file.name, raw: file, status: "success", uid: Date.now() + 1 } as UploadUserFile];
    }
  }

  if (data.appId) {
    form.aliAppid = data.appId ?? "";
    form.aliPrivateId = data.appSecretCert ?? "";
    form.appPublicCertFile = [];
    form.alipayPublicCertFile = [];
    form.alipayRootCertFile = [];
    if (data.appPublicCert && data.appPublicCertName) {
      const file = base64ToFile(data.appPublicCert, data.appPublicCertName);
      form.appPublicCertFile = [{ name: file.name, raw: file, status: "success", uid: Date.now() } as UploadUserFile];
    }
    if (data.alipayPublicCert && data.alipayPublicCertName) {
      const file = base64ToFile(data.alipayPublicCert, data.alipayPublicCertName);
      form.alipayPublicCertFile = [{ name: file.name, raw: file, status: "success", uid: Date.now() + 1 } as UploadUserFile];
    }
    if (data.alipayRootCert && data.alipayRootCertName) {
      const file = base64ToFile(data.alipayRootCert, data.alipayRootCertName);
      form.alipayRootCertFile = [{ name: file.name, raw: file, status: "success", uid: Date.now() + 2 } as UploadUserFile];
    }
    if (!data.wechatAppId) form.accountType = "alipay";
  }
};

const submit = async () => {
  if (!formRef.value) return;
  await formRef.value.validate(async valid => {
    if (!valid) return;

    const storeUserId = localGet("geeker-user")?.userInfo?.id;
    if (!storeUserId) {
      ElMessage.warning("请先登录");
      return;
    }

    if (form.accountType === "alipay") {
      const appPublicCertFile = (form.appPublicCertFile as UploadUserFile[])[0]?.raw as File | undefined;
      const alipayPublicCertFile = (form.alipayPublicCertFile as UploadUserFile[])[0]?.raw as File | undefined;
      const alipayRootCertFile = (form.alipayRootCertFile as UploadUserFile[])[0]?.raw as File | undefined;

      if (!form.aliAppid?.trim()) {
        ElMessage.warning("请输入应用ID");
        return;
      }
      if (!form.aliPrivateId?.trim()) {
        ElMessage.warning("请输入应用私钥");
        return;
      }
      if (!appPublicCertFile || !alipayPublicCertFile || !alipayRootCertFile) {
        ElMessage.warning("请上传应用公钥证书、支付宝公钥证书和支付宝根证书");
        return;
      }

      try {
        const res: any = await saveAlipayWithFiles(
          {
            storeUserId: String(storeUserId),
            appId: form.aliAppid.trim(),
            appSecretCert: form.aliPrivateId.trim()
          },
          appPublicCertFile,
          alipayPublicCertFile,
          alipayRootCertFile
        );
        if (res?.code === 200) {
          ElMessage.success("保存成功");
          emit("success");
          emit("update:modelValue", false);
        } else {
          ElMessage.error(res?.msg || "保存失败");
        }
      } catch (e: any) {
        ElMessage.error(e?.message || "保存失败");
      }
      return;
    }

    if (form.accountType === "wechat") {
      const privateKeyUpload = (form.wechatPrivateKeyFile as UploadUserFile[])[0];
      const publicKeyUpload = (form.wechatPayPublicKeyFile as UploadUserFile[])[0];
      const privateKeyFile = privateKeyUpload?.raw as File | undefined;
      const publicKeyFile = publicKeyUpload?.raw as File | undefined;

      if (!privateKeyFile || !publicKeyFile) {
        ElMessage.warning("请上传私钥证书和公钥证书");
        return;
      }

      try {
        const res: any = await saveWechatWithFiles(
          {
            storeUserId: String(storeUserId),
            apiV3Key: form.wechatApiV3Key || "",
            merchantSerialNumber: form.wechatApiCertSerialNo || "",
            wechatAppId: form.wechatAppid || "",
            wechatMchId: form.wechatMchld || "",
            wechatMiniAppId: form.wechatMiniAppId || "",
            wechatPayPublicKeyId: form.wechatPayPublicKeyId || "",
            accountType: form.accountType || "wechat"
          },
          privateKeyFile,
          publicKeyFile
        );
        if (res?.code === 200) {
          ElMessage.success("保存成功");
          emit("success");
          emit("update:modelValue", false);
        } else {
          ElMessage.error(res?.msg || "保存失败");
        }
      } catch (e: any) {
        ElMessage.error(e?.message || "保存失败");
      }
    }
  });
};

watch(
  () => props.modelValue,
  visible => {
    if (visible) fetchPayAccountConfig();
  }
);
</script>

<style scoped>
.set-pay-key-upload :deep(.el-upload-dragger) {
  padding: 20px;
}
.set-pay-upload-box {
  color: var(--el-text-color-secondary);
  text-align: center;
}
.set-pay-upload-box p {
  margin: 8px 0 4px;
  font-size: 14px;
}
.set-pay-upload-box span {
  font-size: 12px;
}
</style>
