import { createHttpError } from '../../../utils/http.js'
import { kuaishouEticketRequest } from './http-client.js'
import { resolveKuaishouEticketConfig } from './shared.js'

type JsonObject = Record<string, any>

type KuaishouEticketDetailPayload = {
  eTicketId: string
  oid: string
  formToken: string
  leftCount: number
  [key: string]: unknown
}

type KuaishouEticketDetailResult = {
  detail: KuaishouEticketDetailPayload | null
  [key: string]: any
}

export async function queryKuaishouEticketConsumeDetail(payload: JsonObject = {}) {
  const context = resolveKuaishouEticketActionContext(payload)
  const response = await kuaishouEticketRequest(context.detailPath, {
    baseUrl: context.baseUrl,
    cookie: context.cookie,
    timeoutMs: context.timeoutMs,
    body: {
      eTicketId: context.eTicketId,
    },
  })

  return mapKuaishouEticketDetailResult(response.payload, {
    baseUrl: context.baseUrl,
    eTicketId: context.eTicketId,
  })
}

export async function consumeKuaishouEticket(payload: JsonObject = {}) {
  const context = resolveKuaishouEticketActionContext(payload)
  const detailResult = shouldResolveConsumeDetail(payload)
    ? await queryKuaishouEticketConsumeDetail({
      baseUrl: context.baseUrl,
      cookie: context.cookie,
      eTicketId: context.eTicketId,
      timeoutMs: context.timeoutMs,
    })
    : null
  const consumePayload = resolveKuaishouEticketConsumePayload(payload, detailResult)

  const response = await kuaishouEticketRequest(context.consumePath, {
    baseUrl: context.baseUrl,
    cookie: context.cookie,
    timeoutMs: context.timeoutMs,
    body: consumePayload,
  })

  return mapKuaishouEticketConsumeResult(response.payload, {
    baseUrl: context.baseUrl,
    eTicketId: consumePayload.eTicketId,
    oid: consumePayload.oid,
    formToken: consumePayload.formToken,
    num: consumePayload.num,
    storeId: consumePayload.storeId,
    detailResult,
  })
}

export function mapKuaishouEticketDetailResult(payload: JsonObject = {}, context: JsonObject = {}) {
  const normalized = normalizeKuaishouEticketApiResult(payload)
  const detail = mapKuaishouEticketDetailPayload(payload?.data?.eTicket)
  const goods = mapKuaishouEticketGoodsPayload(payload?.data?.goods)

  return {
    baseUrl: String(context.baseUrl || '').trim(),
    eTicketId: String(context.eTicketId || detail?.eTicketId || '').trim(),
    ok: normalized.ok,
    alreadyConsumed: normalized.result === 21,
    result: normalized.result,
    errorMessage: normalized.errorMessage,
    requestId: normalized.requestId,
    serverTimestamp: normalized.serverTimestamp,
    detail,
    goods,
    raw: payload && typeof payload === 'object' ? payload : {},
  }
}

export function mapKuaishouEticketConsumeResult(payload: JsonObject = {}, context: JsonObject = {}) {
  const normalized = normalizeKuaishouEticketApiResult(payload)

  return {
    baseUrl: String(context.baseUrl || '').trim(),
    eTicketId: String(context.eTicketId || '').trim(),
    oid: String(context.oid || '').trim(),
    formToken: String(context.formToken || '').trim(),
    num: normalizePositiveInteger(context.num, 1),
    storeId: String(context.storeId || '0').trim() || '0',
    ok: normalized.ok,
    consumed: normalized.result === 1 || normalized.result === 21,
    alreadyConsumed: normalized.result === 21,
    result: normalized.result,
    errorMessage: normalized.errorMessage,
    requestId: normalized.requestId,
    serverTimestamp: normalized.serverTimestamp,
    detail: context.detailResult?.detail || null,
    raw: payload && typeof payload === 'object' ? payload : {},
  }
}

export function resolveKuaishouEticketConsumePayload(
  payload: JsonObject = {},
  detailResult: KuaishouEticketDetailResult | null = null,
) {
  const detail = detailResult?.detail || null
  const eTicketId = pickFirstNonEmpty([payload.eTicketId, detail?.eTicketId])
  const oid = pickFirstNonEmpty([payload.oid, detail?.oid])
  const formToken = pickFirstNonEmpty([payload.formToken, detail?.formToken])
  const storeId = pickFirstNonEmpty([payload.storeId, '0'])
  const num = normalizePositiveInteger(payload.num, normalizePositiveInteger(detail?.leftCount, 1))

  if (!eTicketId) {
    throw createHttpError('请先填写 eTicketId', {
      statusCode: 400,
      errorCode: 'kuaishou_eticket_missing_eticket_id',
    })
  }

  if (!oid) {
    throw createHttpError('缺少核销所需 oid，请先查询核销信息', {
      statusCode: 400,
      errorCode: 'kuaishou_eticket_missing_oid',
    })
  }

  if (!formToken) {
    throw createHttpError('缺少核销所需 formToken，请先查询核销信息', {
      statusCode: 400,
      errorCode: 'kuaishou_eticket_missing_form_token',
    })
  }

  return {
    eTicketId,
    num,
    storeId,
    oid,
    formToken,
  }
}

export function normalizeKuaishouEticketApiResult(payload: JsonObject = {}) {
  const result = Number(payload?.result || 0)

  return {
    ok: result === 1,
    result,
    errorMessage: String(payload?.error_msg || '').trim(),
    requestId: String(payload?.requestId || '').trim(),
    serverTimestamp: String(payload?.serverTimestamp || '').trim(),
  }
}

export function mapKuaishouEticketDetailPayload(value: unknown): KuaishouEticketDetailPayload | null {
  if (!isPlainObject(value)) {
    return null
  }

  return {
    uid: String(value.uid || '').trim(),
    fulfillDetailId: String(value.fulfillDetailId || '').trim(),
    sellerId: String(value.sellerId || '').trim(),
    formToken: String(value.formToken || '').trim(),
    validEndTime: String(value.validEndTime || '').trim(),
    validStartTime: String(value.validStartTime || '').trim(),
    leftReverseCount: normalizeInteger(value.leftReverseCount, 0),
    eTicketId: String(value.eTicketId || '').trim(),
    oid: String(value.oid || '').trim(),
    totalCount: normalizeInteger(value.totalCount, 0),
    leftCount: normalizeInteger(value.leftCount, 0),
    status: String(value.status || '').trim(),
  }
}

export function mapKuaishouEticketGoodsPayload(value: unknown) {
  if (!isPlainObject(value)) {
    return null
  }

  return {
    itemId: String(value.itemId || '').trim(),
    itemPicUrl: String(value.itemPicUrl || '').trim(),
    itemTitle: String(value.itemTitle || '').trim(),
    price: String(value.price || '').trim(),
    skuDesc: String(value.skuDesc || '').trim(),
    skuId: String(value.skuId || '').trim(),
  }
}

function resolveKuaishouEticketActionContext(payload: JsonObject = {}) {
  const config = resolveKuaishouEticketConfig(payload)
  const eTicketId = String(payload.eTicketId || '').trim()

  if (!config.cookie) {
    throw createHttpError('请先配置快手小店 Cookie', {
      statusCode: 400,
      errorCode: 'kuaishou_eticket_missing_cookie',
    })
  }

  if (!eTicketId) {
    throw createHttpError('请先填写 eTicketId', {
      statusCode: 400,
      errorCode: 'kuaishou_eticket_missing_eticket_id',
    })
  }

  return {
    ...config,
    eTicketId,
  }
}

function shouldResolveConsumeDetail(payload: JsonObject = {}): boolean {
  return !String(payload.oid || '').trim() || !String(payload.formToken || '').trim()
}

function pickFirstNonEmpty(values: unknown[]): string {
  for (const value of values) {
    const normalized = String(value || '').trim()
    if (normalized) {
      return normalized
    }
  }

  return ''
}

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

function normalizeInteger(value: unknown, fallback: number): number {
  const parsed = Number(value)
  return Number.isInteger(parsed) ? parsed : fallback
}

function isPlainObject(value: unknown): value is JsonObject {
  return Object.prototype.toString.call(value) === '[object Object]'
}
