<script setup lang="ts">
import { ElMessage } from 'element-plus'
import { computed, ref, watch } from 'vue'

import {
  createPaymentConfig,
  updatePaymentConfig,
  fetchPaymentConfig,
  type PaymentConfig,
  type CreatePaymentConfigRequest,
  type UpdatePaymentConfigRequest,
} from '@/features/admin/api/paymentConfig'
import { readError } from '@/shared/utils/error'

const props = defineProps<{
  modelValue: boolean
  mode: 'create' | 'edit' | 'view'
  config: PaymentConfig | null
}>()

const emit = defineEmits<{
  (e: 'update:modelValue', val: boolean): void
  (e: 'close'): void
  (e: 'saved'): void
}>()

const submitting = ref(false)
const showSecrets = ref(false)
const loadingSecrets = ref(false)
const advancedOpen = ref<string[]>([])

const defaultGateways: Record<string, string> = {
  leshua: 'https://paygate.leshuazf.com/cgi-bin/lepos_pay_gateway.cgi',
  mock: '',
}

const lakalaGateways: Record<string, string> = {
  production: 'https://s2.lakala.com',
  sandbox: 'https://test.wsmsd.cn/sit',
}

const defaultNotifyURLs: Record<string, string> = {
  leshua: 'https://hao858.com/api/payments/leshua/notify',
  lakala: 'https://hao858.com/api/payments/lakala/notify',
  mock: '',
}

const defaultJumpURLs: Record<string, string> = {
  leshua: 'https://hao858.com/orders',
  lakala: 'https://hao858.com/orders',
  mock: '',
}

const lakalaPayModeByPayWay: Record<string, string> = {
  ZFBZF: 'ALIPAY',
  WXZF: 'WECHAT',
}

// defaultEnvironment 返回新建配置时的默认环境。
function defaultEnvironment(provider: string) {
  return provider === 'mock' ? 'production' : 'production'
}

// defaultGateway 根据服务商和环境生成默认网关地址。
function defaultGateway(provider: string, environment = defaultEnvironment(provider)) {
  if (provider === 'lakala') {
    return lakalaGateways[environment] || lakalaGateways.production
  }
  return defaultGateways[provider] || ''
}

// isDefaultLakalaGateway 判断当前网关是否仍是拉卡拉系统默认值。
function isDefaultLakalaGateway(value?: string) {
  return !value || Object.values(lakalaGateways).includes(value)
}

function defaultExtraConfig(provider: string) {
  if (provider === 'lakala') {
    return {
      app_id: '',
      serial_no: '',
      term_no: '',
      lakala_cert: '',
      pay_mode: 'ALIPAY',
      order_expire_minutes: 15,
    }
  }
  return {}
}

function makeDefaultForm(
  provider = 'leshua',
  environment = defaultEnvironment(provider)
): CreatePaymentConfigRequest {
  return {
    name: '',
    provider,
    merchant_id: '',
    gateway_url: defaultGateway(provider, environment),
    sign_key: '',
    notify_key: '',
    notify_url: defaultNotifyURLs[provider] || '',
    jump_url: defaultJumpURLs[provider] || '',
    pay_way: 'ZFBZF',
    jspay_flag: '2',
    sign_type: provider === 'lakala' ? 'SHA256withRSA' : 'MD5',
    extra_config: defaultExtraConfig(provider),
    is_default: false,
    status: 'active',
    environment,
    business_tags: [],
  }
}

const formData = ref<CreatePaymentConfigRequest>(makeDefaultForm())

const dialogTitle = computed(() => {
  const titles = {
    create: '新增支付配置',
    edit: '编辑支付配置',
    view: '查看支付配置',
  }
  return titles[props.mode]
})

const isReadonly = computed(() => props.mode === 'view')
const isLakala = computed(() => formData.value.provider === 'lakala')
const isMock = computed(() => formData.value.provider === 'mock')
const signKeyLabel = computed(() => (isLakala.value ? '商户私钥' : '签名密钥'))
const notifyKeyLabel = computed(() => (isLakala.value ? '通知证书' : '通知密钥'))
const extraConfig = computed<Record<string, any>>(() => formData.value.extra_config || {})

function normalizeExtraConfig(provider: string, extraConfig?: Record<string, any> | null) {
  const extra = {
    ...defaultExtraConfig(provider),
    ...(extraConfig || {}),
  }
  if (provider === 'lakala' && !extra.pay_mode) {
    extra.pay_mode = 'AUTO'
  }
  return extra
}

// syncLakalaPayMode 根据支付方式同步拉卡拉渠道模式。
function syncLakalaPayMode(payWay = formData.value.pay_way || 'ZFBZF') {
  if (!isLakala.value) return
  formData.value.extra_config = {
    ...normalizeExtraConfig('lakala', formData.value.extra_config),
    pay_mode: lakalaPayModeByPayWay[payWay] || 'AUTO',
  }
}

watch(
  () => props.modelValue,
  val => {
    if (val && props.config) {
      formData.value = {
        name: props.config.name,
        provider: props.config.provider,
        merchant_id: props.config.merchant_id,
        gateway_url: props.config.gateway_url,
        notify_url: props.config.notify_url,
        jump_url: props.config.jump_url,
        pay_way: props.config.pay_way,
        jspay_flag: props.config.jspay_flag,
        sign_type: props.config.sign_type,
        extra_config: normalizeExtraConfig(props.config.provider, props.config.extra_config),
        is_default: props.config.is_default,
        status: props.config.status,
        environment: props.config.environment,
        business_tags: props.config.business_tags || [],
      }
      showSecrets.value = false
      advancedOpen.value = []
    } else if (val && !props.config) {
      // 重置表单
      formData.value = makeDefaultForm()
      showSecrets.value = false
      advancedOpen.value = []
    }
  },
  { immediate: true }
)

function handleProviderChange(provider: string) {
  if (props.mode !== 'create') return
  const currentName = formData.value.name
  const currentPayWay = formData.value.pay_way || 'ZFBZF'
  const currentEnvironment = formData.value.environment || defaultEnvironment(provider)
  formData.value = {
    ...makeDefaultForm(provider, currentEnvironment),
    name: currentName,
    pay_way: currentPayWay,
  }
  syncLakalaPayMode(currentPayWay)
}

// handlePayWayChange 处理支付方式切换，并联动渠道扩展配置。
function handlePayWayChange(payWay: string | number | boolean) {
  syncLakalaPayMode(String(payWay))
}

// handleEnvironmentChange 处理环境切换，并同步拉卡拉默认网关。
function handleEnvironmentChange(environment: string) {
  if (!isLakala.value || !isDefaultLakalaGateway(formData.value.gateway_url)) return
  formData.value.gateway_url = defaultGateway('lakala', environment)
}

async function handleViewSecrets() {
  if (!props.config) return
  loadingSecrets.value = true
  try {
    const config = await fetchPaymentConfig(props.config.id, true)
    formData.value.sign_key = config.sign_key || ''
    formData.value.notify_key = config.notify_key || ''
    showSecrets.value = true
    ElMessage.success('密钥已加载')
  } catch (error) {
    ElMessage.error(readError(error, '加载密钥失败'))
  } finally {
    loadingSecrets.value = false
  }
}

async function handleSave() {
  submitting.value = true
  try {
    if (props.mode === 'create') {
      await createPaymentConfig(formData.value)
      ElMessage.success('创建成功')
    } else if (props.mode === 'edit') {
      if (!props.config) return
      const payload: UpdatePaymentConfigRequest = {
        name: formData.value.name,
        merchant_id: formData.value.merchant_id,
        gateway_url: formData.value.gateway_url,
        notify_url: formData.value.notify_url,
        jump_url: formData.value.jump_url,
        pay_way: formData.value.pay_way,
        jspay_flag: formData.value.jspay_flag,
        sign_type: formData.value.sign_type,
        extra_config: formData.value.extra_config,
        is_default: formData.value.is_default,
        status: formData.value.status,
        environment: formData.value.environment,
        business_tags: formData.value.business_tags,
      }
      // 只有在修改了密钥时才传递
      if (formData.value.sign_key) {
        payload.sign_key = formData.value.sign_key
      }
      if (formData.value.notify_key) {
        payload.notify_key = formData.value.notify_key
      }
      await updatePaymentConfig(props.config.id, payload)
      ElMessage.success('更新成功')
    }
    emit('saved')
  } catch (error) {
    ElMessage.error(readError(error, '保存失败'))
  } finally {
    submitting.value = false
  }
}

function handleClose() {
  emit('update:modelValue', false)
  emit('close')
}
</script>

<template>
  <el-dialog :model-value="modelValue" :title="dialogTitle" width="760px" @close="handleClose">
    <el-form :model="formData" label-width="120px">
      <el-form-item label="配置名称" required>
        <el-input v-model="formData.name" placeholder="如：乐刷生产商户1" :disabled="isReadonly" />
      </el-form-item>

      <el-form-item label="支付服务商" required>
        <el-select
          v-model="formData.provider"
          :disabled="mode !== 'create'"
          @change="handleProviderChange"
        >
          <el-option label="乐刷支付" value="leshua" />
          <el-option label="拉卡拉支付" value="lakala" />
          <el-option label="模拟支付" value="mock" />
        </el-select>
      </el-form-item>

      <el-form-item label="支付方式" required>
        <el-segmented
          v-model="formData.pay_way"
          :disabled="isReadonly"
          :options="[
            { label: '支付宝', value: 'ZFBZF' },
            { label: '微信', value: 'WXZF' },
          ]"
          @change="handlePayWayChange"
        />
      </el-form-item>

      <el-form-item label="商户号" required>
        <el-input v-model="formData.merchant_id" placeholder="渠道商户号" :disabled="isReadonly" />
      </el-form-item>

      <el-form-item v-if="!isMock" label="网关地址" required>
        <el-input v-model="formData.gateway_url" placeholder="支付网关URL" :disabled="isReadonly" />
      </el-form-item>

      <el-form-item v-if="isLakala" label="App ID" required>
        <el-input
          v-model="extraConfig.app_id"
          placeholder="拉卡拉开放平台 appId"
          :disabled="isReadonly"
        />
      </el-form-item>

      <el-form-item v-if="isLakala" label="证书序列号" required>
        <el-input
          v-model="extraConfig.serial_no"
          placeholder="商户证书序列号"
          :disabled="isReadonly"
        />
      </el-form-item>

      <el-form-item v-if="isLakala" label="终端号" required>
        <el-input v-model="extraConfig.term_no" placeholder="拉卡拉终端号" :disabled="isReadonly" />
      </el-form-item>

      <el-form-item v-if="!isMock" :label="signKeyLabel" required>
        <el-input
          v-model="formData.sign_key"
          :type="isLakala ? 'textarea' : 'password'"
          :rows="isLakala ? 5 : undefined"
          :show-password="!isLakala"
          :placeholder="
            mode === 'edit' ? '留空则不修改' : isLakala ? '请输入商户私钥 PEM' : '请输入签名密钥'
          "
          :disabled="isReadonly"
        />
      </el-form-item>

      <el-form-item v-if="!isMock" :label="notifyKeyLabel" required>
        <el-input
          v-model="formData.notify_key"
          :type="isLakala ? 'textarea' : 'password'"
          :rows="isLakala ? 5 : undefined"
          :show-password="!isLakala"
          :placeholder="
            mode === 'edit'
              ? '留空则不修改'
              : isLakala
                ? '请输入拉卡拉通知验签证书 PEM'
                : '请输入通知密钥'
          "
          :disabled="isReadonly"
        />
      </el-form-item>

      <el-form-item v-if="isLakala" label="平台证书">
        <el-input
          v-model="extraConfig.lakala_cert"
          type="textarea"
          :rows="4"
          placeholder="拉卡拉平台响应验签证书 PEM，可与通知证书一致"
          :disabled="isReadonly"
        />
      </el-form-item>

      <el-form-item v-if="mode === 'view' && !showSecrets" label="">
        <el-button :loading="loadingSecrets" @click="handleViewSecrets">查看密钥</el-button>
      </el-form-item>

      <el-form-item v-if="!isMock" label="回调地址" required>
        <el-input
          v-model="formData.notify_url"
          placeholder="异步通知回调地址"
          :disabled="isReadonly"
        />
      </el-form-item>

      <el-form-item label="是否默认">
        <el-switch v-model="formData.is_default" :disabled="isReadonly" />
        <span class="form-hint">同一支付方式只保留一个启用默认配置</span>
      </el-form-item>

      <el-form-item label="状态">
        <el-select v-model="formData.status" :disabled="isReadonly">
          <el-option label="启用" value="active" />
          <el-option label="禁用" value="disabled" />
          <el-option label="测试中" value="testing" />
        </el-select>
      </el-form-item>

      <el-form-item label="环境">
        <el-select
          v-model="formData.environment"
          :disabled="isReadonly"
          @change="handleEnvironmentChange"
        >
          <el-option label="生产环境" value="production" />
          <el-option label="测试环境" value="sandbox" />
        </el-select>
      </el-form-item>

      <el-collapse v-model="advancedOpen" class="advanced-config">
        <el-collapse-item name="advanced">
          <template #title>
            <span class="advanced-title">高级配置</span>
          </template>

          <el-form-item label="跳转地址">
            <el-input
              v-model="formData.jump_url"
              placeholder="支付完成跳转地址"
              :disabled="isReadonly"
            />
          </el-form-item>

          <el-form-item v-if="isLakala" label="拉卡拉模式">
            <el-select v-model="extraConfig.pay_mode" :disabled="isReadonly">
              <el-option label="支付宝" value="ALIPAY" />
              <el-option label="微信" value="WECHAT" />
              <el-option label="不限制，由收银台选择" value="AUTO" />
              <el-option label="银联" value="UQRCODEPAY" />
            </el-select>
          </el-form-item>

          <el-form-item v-if="isLakala" label="有效期分钟">
            <el-input-number
              v-model="extraConfig.order_expire_minutes"
              :min="1"
              :max="1440"
              :disabled="isReadonly"
            />
          </el-form-item>

          <el-form-item label="支付形态">
            <el-select v-model="formData.jspay_flag" :disabled="isReadonly">
              <el-option label="H5 / JSAPI" value="1" />
              <el-option label="简易支付 / 收银台" value="2" />
            </el-select>
          </el-form-item>

          <el-form-item label="签名类型">
            <el-select v-model="formData.sign_type" :disabled="isReadonly">
              <el-option label="MD5" value="MD5" />
              <el-option label="SHA256withRSA" value="SHA256withRSA" />
            </el-select>
          </el-form-item>
        </el-collapse-item>
      </el-collapse>
    </el-form>

    <template #footer>
      <el-button @click="handleClose">{{ isReadonly ? '关闭' : '取消' }}</el-button>
      <el-button v-if="!isReadonly" type="primary" :loading="submitting" @click="handleSave">
        保存
      </el-button>
    </template>
  </el-dialog>
</template>

<style scoped>
.advanced-config {
  margin-top: 4px;
  border-top: 1px solid #edf0f5;
  border-bottom: 0;
}

.advanced-config :deep(.el-collapse-item__header) {
  height: 44px;
  padding-left: 120px;
  border-bottom: 0;
  color: #4b5563;
  font-weight: 600;
}

.advanced-config :deep(.el-collapse-item__wrap) {
  border-bottom: 0;
}

.advanced-config :deep(.el-collapse-item__content) {
  padding-bottom: 0;
}

.advanced-title {
  font-size: 14px;
}

.form-hint {
  margin-left: 8px;
  color: #6b7280;
  font-size: 12px;
}
</style>
