import { listKuaishouIndustryVouchersByOid } from '../../repositories/kuaishou-industry-voucher-repo.js'
import { listTasksByOrderId } from '../../repositories/task-repo.js'
import type { KuaishouIndustryVoucherRow, TaskRow } from '../../types/repository/rows.js'
import type { WorkOrderRow } from '../../repositories/worker-platform/index.js'
import { attachKuaishouIndustryVoucherToTask } from '../platforms/kuaishou-industry/voucher-binding-service.js'
import { consumeKuaishouIndustryVoucher } from '../platforms/kuaishou-industry/voucher-service.js'

export type WorkOrderVoucherConsumeResult = {
  ok: boolean
  voucherCount: number
  consumedCount: number
  alreadyConsumedCount: number
  failedCount: number
  voucherCodes: string[]
  errorMessage: string
}

type WorkOrderVoucherServiceDeps = {
  listVouchersByOid: typeof listKuaishouIndustryVouchersByOid
  listTasksByOrderId: typeof listTasksByOrderId
  consumeVoucher: typeof consumeKuaishouIndustryVoucher
  attachVoucherToTask: typeof attachKuaishouIndustryVoucherToTask
}

const defaultDeps: WorkOrderVoucherServiceDeps = {
  listVouchersByOid: listKuaishouIndustryVouchersByOid,
  listTasksByOrderId,
  consumeVoucher: consumeKuaishouIndustryVoucher,
  attachVoucherToTask: attachKuaishouIndustryVoucherToTask,
}

export async function consumeIndustryVouchersBeforeWorkOrderPublish(
  workOrder: WorkOrderRow,
  deps: WorkOrderVoucherServiceDeps = defaultDeps,
): Promise<WorkOrderVoucherConsumeResult> {
  return consumeIndustryVouchersBeforeWorkOrderAction(workOrder, 'work_order_publish', deps)
}

export async function consumeIndustryVouchersBeforeWorkOrderAssign(
  workOrder: WorkOrderRow,
  deps: WorkOrderVoucherServiceDeps = defaultDeps,
): Promise<WorkOrderVoucherConsumeResult> {
  return consumeIndustryVouchersBeforeWorkOrderAction(workOrder, 'work_order_assign', deps)
}

async function consumeIndustryVouchersBeforeWorkOrderAction(
  workOrder: WorkOrderRow,
  source: 'work_order_publish' | 'work_order_assign',
  deps: WorkOrderVoucherServiceDeps,
): Promise<WorkOrderVoucherConsumeResult> {
  const oid = String(workOrder.platform_order_id || '').trim()
  if (!oid) {
    return buildConsumeResult([])
  }

  const [vouchers, tasks] = await Promise.all([
    deps.listVouchersByOid(oid),
    workOrder.order_id ? deps.listTasksByOrderId(workOrder.order_id) : Promise.resolve([]),
  ])
  const targets = resolveWorkOrderVoucherTargets(workOrder, tasks, vouchers)
  let consumedCount = 0
  let alreadyConsumedCount = 0

  for (const target of targets) {
    const voucherCode = String(target.voucher.voucher_code || '').trim()
    const alreadyConsumed = normalizeVoucherStatus(target.voucher.status) === 'CONSUMED'
    let consumeResult: Awaited<ReturnType<typeof consumeKuaishouIndustryVoucher>>

    try {
      consumeResult = await deps.consumeVoucher(target.voucher, {
        source,
        consumeTime: Date.now(),
        ...(target.task ? { task: target.task } : {}),
      })
    } catch (error) {
      return buildConsumeResult(targets, {
        consumedCount,
        alreadyConsumedCount,
        errorMessage: error instanceof Error ? error.message : '电子凭证核销失败',
      })
    }

    if (!consumeResult.ok || !consumeResult.voucher) {
      return buildConsumeResult(targets, {
        consumedCount,
        alreadyConsumedCount,
        errorMessage: consumeResult.errorMessage || `电子凭证 ${voucherCode} 核销失败`,
      })
    }

    if (alreadyConsumed) {
      alreadyConsumedCount += 1
    } else {
      consumedCount += 1
    }

    try {
      if (target.task) {
        await deps.attachVoucherToTask(target.task, consumeResult.voucher, {
          source,
          now: new Date().toISOString(),
        })
      }
    } catch (error) {
      return buildConsumeResult(targets, {
        consumedCount,
        alreadyConsumedCount,
        errorMessage: `电子凭证 ${voucherCode} 已核销，但任务状态同步失败：${
          error instanceof Error ? error.message : '未知错误'
        }`,
      })
    }
  }

  return buildConsumeResult(targets, {
    consumedCount,
    alreadyConsumedCount,
  })
}

export function resolveWorkOrderVoucherTargets(
  workOrder: WorkOrderRow,
  tasks: TaskRow[],
  vouchers: KuaishouIndustryVoucherRow[],
) {
  const taskById = new Map(tasks.map((task) => [Number(task.id), task]))
  const linkedTaskIds = new Set<number>()

  if (workOrder.task_id) {
    linkedTaskIds.add(Number(workOrder.task_id))
  }
  if (workOrder.order_item_id) {
    for (const task of tasks) {
      if (Number(task.order_item_id) === Number(workOrder.order_item_id)) {
        linkedTaskIds.add(Number(task.id))
      }
    }
  }

  const linkedVouchers = vouchers.filter(
    (voucher) => voucher.task_id && linkedTaskIds.has(Number(voucher.task_id)),
  )
  // 历史数据可能尚未完成任务绑定；此时回退到同一平台订单，避免仍需人工核销。
  const hasTaskBoundVoucher = vouchers.some((voucher) => Number(voucher.task_id || 0) > 0)
  const selectedVouchers =
    linkedVouchers.length > 0
      ? linkedVouchers
      : linkedTaskIds.size > 0 && hasTaskBoundVoucher
        ? []
        : vouchers

  return deduplicateVouchers(selectedVouchers).map((voucher) => ({
    voucher,
    task: voucher.task_id ? taskById.get(Number(voucher.task_id)) || null : null,
  }))
}

function buildConsumeResult(
  targets: Array<{ voucher: KuaishouIndustryVoucherRow }>,
  input: {
    consumedCount?: number
    alreadyConsumedCount?: number
    errorMessage?: string
  } = {},
): WorkOrderVoucherConsumeResult {
  const errorMessage = String(input.errorMessage || '').trim()
  const processedCount = Number(input.consumedCount || 0) + Number(input.alreadyConsumedCount || 0)

  return {
    ok: !errorMessage,
    voucherCount: targets.length,
    consumedCount: Number(input.consumedCount || 0),
    alreadyConsumedCount: Number(input.alreadyConsumedCount || 0),
    failedCount: errorMessage ? Math.max(1, targets.length - processedCount) : 0,
    voucherCodes: targets.map((target) => String(target.voucher.voucher_code || '').trim()),
    errorMessage,
  }
}

function deduplicateVouchers(vouchers: KuaishouIndustryVoucherRow[]) {
  const seen = new Set<string>()
  return vouchers.filter((voucher) => {
    const key = String(voucher.voucher_code || voucher.id || '').trim()
    if (!key || seen.has(key)) return false
    seen.add(key)
    return true
  })
}

function normalizeVoucherStatus(value: unknown) {
  return String(value || '')
    .trim()
    .toUpperCase()
}
