/**
 * bankUtils.uts
 * 银行卡工具集：BIN 识别、OCR 适配、银行列表、表单校验
 * 所有接口均与真实 OCR 厂商解耦，需接入时只修改 recognizeBankCardFromImage 内部实现
 */

// ─────────────────────────────────────────────
// 1. 银行列表数据源
// ─────────────────────────────────────────────
export type BankItem = {
  code: string      // 内部 code
  name: string      // 银行全称
  shortName: string // 简称，用于 UI 显示
  logo: string      // 本地 logo 路径（没有则为空串，前端显示占位）
}

export const BANK_LIST: BankItem[] = [
  { code: 'ICBC',  name: '中国工商银行', shortName: '工商银行', logo: '' },
  { code: 'CCB',   name: '中国建设银行', shortName: '建设银行', logo: '' },
  { code: 'ABC',   name: '中国农业银行', shortName: '农业银行', logo: '' },
  { code: 'BOC',   name: '中国银行',     shortName: '中国银行', logo: '' },
  { code: 'COMM',  name: '交通银行',     shortName: '交通银行', logo: '' },
  { code: 'CMB',   name: '招商银行',     shortName: '招商银行', logo: '' },
  { code: 'CITIC', name: '中信银行',     shortName: '中信银行', logo: '' },
  { code: 'SPDB',  name: '浦发银行',     shortName: '浦发银行', logo: '' },
  { code: 'CEB',   name: '光大银行',     shortName: '光大银行', logo: '' },
  { code: 'HXB',   name: '华夏银行',     shortName: '华夏银行', logo: '' },
  { code: 'CMBC',  name: '民生银行',     shortName: '民生银行', logo: '' },
  { code: 'PAB',   name: '平安银行',     shortName: '平安银行', logo: '' },
  { code: 'GDB',   name: '广发银行',     shortName: '广发银行', logo: '' },
  { code: 'BOBJ',  name: '北京银行',     shortName: '北京银行', logo: '' },
  { code: 'SHRCB', name: '上海银行',     shortName: '上海银行', logo: '' },
  { code: 'PSBC',  name: '中国邮政储蓄银行', shortName: '邮储银行', logo: '' },
]

// ─────────────────────────────────────────────
// 2. BIN → 银行名称映射（仅 6 位前缀）
//    来源：公开 BIN 数据，仅做参考识别用途
// ─────────────────────────────────────────────
type BinEntry = {
  prefix: string
  bankCode: string
}

const BIN_MAP: BinEntry[] = [
  // 工商银行
  { prefix: '6212', bankCode: 'ICBC' },
  { prefix: '6216', bankCode: 'ICBC' },
  { prefix: '6217', bankCode: 'ICBC' },
  { prefix: '6222', bankCode: 'ICBC' },
  // 建设银行
  { prefix: '6217', bankCode: 'CCB' },
  { prefix: '6227', bankCode: 'CCB' },
  { prefix: '6236', bankCode: 'CCB' },
  // 农业银行
  { prefix: '6225', bankCode: 'ABC' },
  { prefix: '6228', bankCode: 'ABC' },
  { prefix: '9559', bankCode: 'ABC' },
  // 中国银行
  { prefix: '6013', bankCode: 'BOC' },
  { prefix: '6259', bankCode: 'BOC' },
  { prefix: '6539', bankCode: 'BOC' },
  // 交通银行
  { prefix: '6222', bankCode: 'COMM' },
  { prefix: '6230', bankCode: 'COMM' },
  { prefix: '6266', bankCode: 'COMM' },
  // 招商银行
  { prefix: '6214', bankCode: 'CMB' },
  { prefix: '6225', bankCode: 'CMB' },
  { prefix: '6245', bankCode: 'CMB' },
  // 中信银行
  { prefix: '6217', bankCode: 'CITIC' },
  { prefix: '4367', bankCode: 'CITIC' },
  // 浦发银行
  { prefix: '6217', bankCode: 'SPDB' },
  { prefix: '6216', bankCode: 'SPDB' },
  // 平安银行
  { prefix: '6214', bankCode: 'PAB' },
  { prefix: '6216', bankCode: 'PAB' },
  // 邮储银行
  { prefix: '6210', bankCode: 'PSBC' },
  { prefix: '6221', bankCode: 'PSBC' },
  { prefix: '6230', bankCode: 'PSBC' },
]

/**
 * 根据卡号前缀匹配银行（优先匹配最长前缀）
 * @param cardNo 银行卡号（至少 6 位）
 * @returns BankItem | null
 */
export function detectBankByBin(cardNo: string): BankItem | null {
  const cleaned = cardNo.replace(/\s/g, '')
  if (cleaned.length < 6) return null
  const prefix6 = cleaned.substring(0, 6)
  const prefix4 = cleaned.substring(0, 4)

  // 优先 6 位匹配
  for (let i = 0; i < BIN_MAP.length; i++) {
    if (BIN_MAP[i].prefix === prefix6) {
      return findBankByCode(BIN_MAP[i].bankCode)
    }
  }
  // 降级 4 位匹配
  for (let i = 0; i < BIN_MAP.length; i++) {
    if (BIN_MAP[i].prefix === prefix4) {
      return findBankByCode(BIN_MAP[i].bankCode)
    }
  }
  return null
}

function findBankByCode(code: string): BankItem | null {
  for (let i = 0; i < BANK_LIST.length; i++) {
    if (BANK_LIST[i].code === code) return BANK_LIST[i]
  }
  return null
}

// ─────────────────────────────────────────────
// 3. 银行卡号格式化（每 4 位一空格，仅展示用）
// ─────────────────────────────────────────────
export function formatCardNo(raw: string): string {
  const digits = raw.replace(/\D/g, '')
  let result = ''
  for (let i = 0; i < digits.length; i++) {
    if (i > 0 && i % 4 === 0) result += ' '
    result += digits[i]
  }
  return result
}

/** 去除格式化空格，返回纯数字 */
export function cleanCardNo(formatted: string): string {
  return formatted.replace(/\s/g, '')
}

// ─────────────────────────────────────────────
// 4. 银行卡号脱敏（验证页展示用）
// ─────────────────────────────────────────────
export function maskCardNo(cardNo: string): string {
  const digits = cardNo.replace(/\s/g, '')
  if (digits.length < 8) return digits
  const prefix = digits.substring(0, 4)
  const suffix = digits.substring(digits.length - 4)
  return prefix + ' **** **** ' + suffix
}

// ─────────────────────────────────────────────
// 5. Luhn 校验（可选，建议开启）
// ─────────────────────────────────────────────
export function luhnCheck(cardNo: string): boolean {
  const digits = cardNo.replace(/\s/g, '')
  if (digits.length < 13 || digits.length > 19) return false
  let sum = 0
  let alternate = false
  for (let i = digits.length - 1; i >= 0; i--) {
    const digitStr = digits.substring(i, i + 1)
    let n = parseInt(digitStr)
    if (alternate) {
      n *= 2
      if (n > 9) n -= 9
    }
    sum += n
    alternate = !alternate
  }
  return sum % 10 === 0
}

// ─────────────────────────────────────────────
// 6. 手机号校验
// ─────────────────────────────────────────────
export function isValidPhone(phone: string): boolean {
  return /^1[3-9]\d{9}$/.test(phone)
}

// ─────────────────────────────────────────────
// 7. OCR 适配层（银行卡识别）
//    【接入说明】真实接入时，在此处替换实现：
//    - 腾讯云：调用 /ocr/v3/BankCardOCR
//    - 阿里云：调用 /cardrecog/recognize_bank_card
//    - 自有服务：调用项目后端 OCR 接口
//    注意：不要在此硬编码任何 SecretKey / AccessKey
// ─────────────────────────────────────────────
export type OCRResult = {
  success: boolean
  cardNo: string
  bankName: string   // 识别出的银行名称（可能为空）
  errorMsg: string
}

/**
 * 选择图片并识别银行卡
 * 当前为"前端完整流程 + 后端待接入"占位实现
 * @returns OCRResult
 */
export async function recognizeBankCardFromImage(): Promise<OCRResult> {
  return new Promise<OCRResult>((resolve) => {
    function handleSelectedImage(filePath: string): void {
      if (filePath === '') {
        resolve({ success: false, cardNo: '', bankName: '', errorMsg: '未选择图片' } as OCRResult)
        return
      }

      console.log('[OCR] 已选择图片:', filePath, '，OCR 服务待接入')
      resolve({
        success: false,
        cardNo: '',
        bankName: '',
        errorMsg: 'OCR 服务待接入，请手动输入卡号'
      } as OCRResult)
    }

    uni.chooseImage({
      count: 1,
      sourceType: ['camera', 'album'],
      success: (imgRes: ChooseImageSuccess): void => {
        const filePath = (imgRes.tempFilePaths as string[])[0]
        try {
          handleSelectedImage(filePath)
        } catch (e) {
          console.error('[OCR] 识别异常:', e)
          resolve({ success: false, cardNo: '', bankName: '', errorMsg: 'OCR 识别失败' } as OCRResult)
        }
      },
      fail: () => {
        resolve({ success: false, cardNo: '', bankName: '', errorMsg: '取消选择' } as OCRResult)
      }
    })
  })
}

// ─────────────────────────────────────────────
// 8. 短信验证码适配层
//    【接入说明】项目后端接入短信服务后，替换此方法
// ─────────────────────────────────────────────
export type SmsResult = {
  success: boolean
  errorMsg: string
}

/**
 * 发送短信验证码
 * 当前为占位实现，接入阿里云/腾讯云短信后替换此处
 * @param phone 11 位手机号
 */
export async function sendSmsCode(phone: string): Promise<SmsResult> {
  if (!isValidPhone(phone)) {
    return { success: false, errorMsg: '手机号格式不正确' } as SmsResult
  }

  try {
    // ─── TODO: 接入真实短信服务 ────────────────────────────────
    // 示例（项目后端代理）：
    // const res = await uni.request({
    //   url: '/api/sms/send',
    //   method: 'POST',
    //   data: { phone, scene: 'bind_bank_card' }
    // })
    // if (res.data.code === 0) return { success: true, errorMsg: '' }
    // return { success: false, errorMsg: res.data.message }
    // ─────────────────────────────────────────────────────────

    // 占位实现：模拟发送成功，验证码请查看控制台
    console.log('[SMS] 占位发送验证码到:', phone, '，模拟验证码: 123456')
    return { success: true, errorMsg: '' } as SmsResult
  } catch (e) {
    console.error('[SMS] 发送异常:', e)
    return { success: false, errorMsg: '发送失败，请稍后重试' } as SmsResult
  }
}

/**
 * 验证短信验证码
 * 当前为占位实现：任何 6 位数字均视为通过
 * @param phone 手机号
 * @param code  用户输入的验证码
 */
export async function verifySmsCode(phone: string, code: string): Promise<SmsResult> {
  if (code.length !== 6) {
    return { success: false, errorMsg: '请输入 6 位验证码' } as SmsResult
  }

  try {
    // ─── TODO: 接入真实验证逻辑 ────────────────────────────────
    // const res = await uni.request({ ... })
    // ─────────────────────────────────────────────────────────

    // 占位：校验通过
    console.log('[SMS] 占位验证通过, phone:', phone, 'code:', code)
    return { success: true, errorMsg: '' } as SmsResult
  } catch (e) {
    console.error('[SMS] 验证异常:', e)
    return { success: false, errorMsg: '验证失败，请重试' } as SmsResult
  }
}
