import { isPaidPreparationStableStatus } from '../../../domain/task-status.js'
import { kuaishouCloudExecutor } from './kuaishou-cloud-executor.js'
import { kuaishouFeifeiExecutor } from './kuaishou-feifei-executor.js'
import { manualDispatchExecutor } from './manual-executor.js'
import { affiliateDashExecutor } from './affiliate-dash-executor.js'
import {
  FULFILLMENT_EXECUTOR_KEYS,
  isManualDispatchExecutor,
  normalizeExecutorKey,
  type FulfillmentActionOptions,
  type FulfillmentDeliveryLink,
  type FulfillmentExecutor,
  type FulfillmentPrepareDeps,
} from './types.js'
import type { TaskRow } from '../../../types/repository/rows.js'

const EXECUTORS = new Map<string, FulfillmentExecutor>([
  [FULFILLMENT_EXECUTOR_KEYS.KUAISHOU_CLOUD, kuaishouCloudExecutor],
  [FULFILLMENT_EXECUTOR_KEYS.KUAISHOU_INDUSTRY, kuaishouCloudExecutor],
  [FULFILLMENT_EXECUTOR_KEYS.KUAISHOU_FEIFEI, kuaishouFeifeiExecutor],
  [FULFILLMENT_EXECUTOR_KEYS.AFFILIATE_DASH, affiliateDashExecutor],
  [FULFILLMENT_EXECUTOR_KEYS.MANUAL_DISPATCH, manualDispatchExecutor],
])

export function getFulfillmentExecutor(executorKey: unknown): FulfillmentExecutor | null {
  return EXECUTORS.get(normalizeExecutorKey(executorKey)) || null
}

export async function preparePaidFulfillmentTask(
  task: TaskRow,
  deps: FulfillmentPrepareDeps,
): Promise<TaskRow | null> {
  if (isPaidPreparationStableStatus(task.task_status)) {
    return task
  }

  const executor = getFulfillmentExecutor(task.executor_key)
  if (executor?.preparePaidTask) {
    return executor.preparePaidTask(task, deps)
  }

  if (!task.requires_claim || isManualDispatchExecutor(task.executor_key)) {
    return manualDispatchExecutor.preparePaidTask?.(task, deps) || task
  }

  return task
}

export async function resolveFulfillmentDeliveryLink(
  task: TaskRow,
): Promise<FulfillmentDeliveryLink | null> {
  const executor = getFulfillmentExecutor(task.executor_key)
  if (!executor?.resolveDeliveryLink) {
    return null
  }

  return executor.resolveDeliveryLink(task)
}

async function runExecutorAction(
  task: TaskRow,
  method:
    | 'prepareBinding'
    | 'rebindRole'
    | 'refreshRole'
    | 'confirmRole'
    | 'redeemTask'
    | 'dispatchTask'
    | 'returnNumber',
  options: FulfillmentActionOptions = {},
) {
  const executor = getFulfillmentExecutor(task.executor_key)
  const handler = executor?.[method]
  if (!handler) {
    return null
  }

  return handler(task, options)
}

export function prepareFulfillmentBinding(task: TaskRow, options: FulfillmentActionOptions = {}) {
  return runExecutorAction(task, 'prepareBinding', options)
}

export function rebindFulfillmentRole(task: TaskRow, options: FulfillmentActionOptions = {}) {
  return runExecutorAction(task, 'rebindRole', options)
}

export function refreshFulfillmentRole(task: TaskRow, options: FulfillmentActionOptions = {}) {
  return runExecutorAction(task, 'refreshRole', options)
}

export function confirmFulfillmentRole(task: TaskRow, options: FulfillmentActionOptions = {}) {
  return runExecutorAction(task, 'confirmRole', options)
}

export function redeemFulfillmentTask(task: TaskRow, options: FulfillmentActionOptions = {}) {
  return runExecutorAction(task, 'redeemTask', options)
}

export function dispatchFulfillmentTask(task: TaskRow, options: FulfillmentActionOptions = {}) {
  return runExecutorAction(task, 'dispatchTask', options)
}

export function returnFulfillmentNumber(task: TaskRow, options: FulfillmentActionOptions = {}) {
  return runExecutorAction(task, 'returnNumber', options)
}
