import crypto from 'node:crypto'
import path from 'node:path'
import { fileURLToPath } from 'node:url'

import { loadEnvFiles } from '../src/config/runtime-env.js'

type JsonObject = Record<string, unknown>

const CURRENT_DIR = path.dirname(fileURLToPath(import.meta.url))
const PROJECT_ROOT = path.resolve(CURRENT_DIR, '..')
const WORKSPACE_ROOT = path.resolve(PROJECT_ROOT, '../..')

loadEnvFiles([path.join(WORKSPACE_ROOT, '.env'), path.join(PROJECT_ROOT, '.env')])

const args = parseArgs(process.argv.slice(2))

if (args.help) {
  printHelp()
  process.exit(0)
}

const secret = readEnv('KAQUAN91_SECRET')
const version = readEnv('KAQUAN91_VERSION') || '1.0'
const baseUrl = String(
  args.baseUrl || process.env.OPEN91_MOCK_BASE_URL || 'http://127.0.0.1',
).replace(/\/$/, '')
const mode = String(args.mode || 'create').trim()

if (!secret || secret.length !== 32) {
  console.error('缺少 32 位 91 密钥：请配置 KAQUAN91_SECRET。')
  process.exit(1)
}

if (!['create', 'query'].includes(mode)) {
  console.error('mode 只能是 create 或 query。')
  process.exit(1)
}

const orderNo = String(args.orderNo || `MOCK91${Date.now()}`).trim()
const timestamp = Number(args.timestamp || Math.floor(Date.now() / 1000))

const payload =
  mode === 'query'
    ? {
        orderNo,
        timestamp,
        version,
      }
    : {
        buyNum: normalizePositiveInteger(args.buyNum, 1),
        callbackUrl: String(args.callbackUrl || ''),
        maxAmount: String(args.maxAmount || '0.01'),
        orderNo,
        productNo: String(args.productNo || '套装-浪漫天命').trim(),
        timestamp,
        version,
      }

const body = {
  ...payload,
  sign: signOpen91Payload(payload, secret),
}

const endpoint = `${baseUrl}/api/v1/open/91/orders/${mode}`

console.log(`POST ${endpoint}`)
console.log(JSON.stringify(maskPayload(body), null, 2))

const response = await fetch(endpoint, {
  method: 'POST',
  headers: {
    'content-type': 'application/json',
  },
  body: JSON.stringify(body),
}).catch((error) => {
  console.error('请求 91 mock 接口失败，请确认后端入口可访问。')
  console.error(`当前地址：${endpoint}`)
  console.error(
    'Docker 开发环境通常使用 http://127.0.0.1；本地直启后端通常使用 http://127.0.0.1:3000。',
  )
  throw error
})

const responseText = await response.text()
console.log(`HTTP ${response.status}`)

try {
  console.log(JSON.stringify(JSON.parse(responseText), null, 2))
} catch {
  console.log(responseText)
}

function parseArgs(rawArgs: string[]) {
  const parsed: JsonObject = {}

  for (const rawArg of rawArgs) {
    const arg = String(rawArg || '').trim()
    if (!arg) continue
    if (arg === '--help' || arg === '-h') {
      parsed.help = true
      continue
    }

    const normalized = arg.startsWith('--') ? arg.slice(2) : arg
    const separatorIndex = normalized.indexOf('=')
    if (separatorIndex < 0) {
      parsed[normalized] = true
      continue
    }

    const key = normalized.slice(0, separatorIndex).trim()
    const value = normalized.slice(separatorIndex + 1).trim()
    if (key) {
      parsed[key] = value
    }
  }

  return parsed
}

function readEnv(...keys: string[]) {
  for (const key of keys) {
    const value = String(process.env[key] || '').trim()
    if (value) return value
  }

  return ''
}

function signOpen91Payload(payload: JsonObject, currentSecret: string) {
  return crypto
    .createHash('md5')
    .update(buildOpen91SignSource(payload, currentSecret), 'utf8')
    .digest('hex')
    .toUpperCase()
}

function buildOpen91SignSource(payload: JsonObject, currentSecret: string) {
  const queryString = Object.entries(payload)
    .filter(([key]) => key !== 'sign')
    .sort(([left], [right]) => left.localeCompare(right))
    .map(([key, value]) => `${key}=${stringifySignValue(value)}`)
    .join('&')

  return `${currentSecret}${queryString}${currentSecret}`
}

function stringifySignValue(value: unknown) {
  if (typeof value === 'number' && Number.isFinite(value)) return String(value)
  if (typeof value === 'boolean') return value ? 'true' : 'false'
  if (value == null) return ''
  return String(value)
}

function normalizePositiveInteger(value: unknown, fallback: number) {
  const parsed = Number(value)
  return Number.isInteger(parsed) && parsed > 0 ? parsed : fallback
}

function maskPayload(payload: JsonObject) {
  return {
    ...payload,
    sign: String(payload.sign || '').replace(/^(.{6}).+(.{4})$/, '$1***$2'),
  }
}

function printHelp() {
  console.log(`
模拟 91 卡券请求：

  npm run mock:open91 -- --productNo=套装-浪漫天命
  npm run mock:open91 -- --productNo=荣耀勋章礼包（30个） --maxAmount=300 --buyNum=1
  npm run mock:open91 -- --mode=query --orderNo=MOCK911779000000000

参数：
  --baseUrl      后端地址，默认 http://127.0.0.1
  --mode         create 或 query，默认 create
  --orderNo      91 订单号，默认自动生成
  --productNo    91 商品名，默认 套装-浪漫天命
  --buyNum       购买数量，默认 1
  --maxAmount    最大金额/正常金额，默认 0.01
  --callbackUrl  回调地址，默认空
`)
}
