import { createTaskEvent } from '../../../repositories/task-event-repo.js'
import {
  getTaskById,
  updateTask,
  updateTaskStatusIfCurrent,
} from '../../../repositories/task-repo.js'
import {
  TASK_STATUS,
  canRedeemKuaishouCloudClaimStatus,
  isKuaishouCloudRedeemSettledStatus,
  normalizeTaskStatus,
} from '../../../domain/task-status.js'
import { createHttpError } from '../../../utils/http.js'
import { nowIso } from '../../../utils/time.js'
import type { TaskRow } from '../../../types/repository/rows.js'
import {
  assertBoundUidMatchesExpected,
  assertClaimExpectedUidReady,
  getClaimIdentityFromTask,
} from '../../claim/claim-identity.js'
import { isKuaishouCloudTask, normalizeKuaishouCloudFlow, type JsonObject } from './domain.js'
import { dispatchKuaishouCloudFulfillmentTask } from './dispatch-fulfillment.js'
import { completeMockKuaishouCloudTask, isKuaishouCloudMockTask } from './mock-helpers.js'
import { normalizeActor, parseTaskContext } from './task-context.js'

export type RedeemKuaishouCloudTaskResult = {
  task: TaskRow
  /** 是否已处于终态/已兑换，调用方无需再 dispatch */
  alreadySettled: boolean
  /** 并发抢锁失败（他人已推进） */
  concurrentSkipped: boolean
}

/**
 * lewan 一键兑换用例（履约引擎入口）：
 * waiting_binding + UID 匹配 → role_confirmed → redeeming → dispatch(+autoFinalize)
 *
 * claim / admin 应只调此函数，不要直接拼状态机。
 */
export async function redeemKuaishouCloudTask(
  task: TaskRow,
  options: JsonObject = {},
): Promise<RedeemKuaishouCloudTaskResult> {
  if (!isKuaishouCloudTask(task)) {
    throw createHttpError('当前任务不是 kuaishou-lewan 履约任务', {
      statusCode: 409,
      errorCode: 'kuaishou_cloud_task_invalid',
    })
  }

  const now = String(options.now || '').trim() || nowIso()
  const source = String(options.source || 'system_redeem').trim() || 'system_redeem'
  const actor = normalizeActor(options.actor) || { source }
  const autoFinalize = options.autoFinalize !== false
  const errorCodePrefix =
    String(options.errorCodePrefix || 'kuaishou_cloud_redeem').trim() || 'kuaishou_cloud_redeem'

  let workingTask = task
  const currentStatus = normalizeTaskStatus(workingTask.task_status)

  if (isKuaishouCloudRedeemSettledStatus(currentStatus)) {
    return { task: workingTask, alreadySettled: true, concurrentSkipped: false }
  }

  if (!canRedeemKuaishouCloudClaimStatus(currentStatus)) {
    throw createHttpError('当前状态不可兑换，请先完成绑定并匹配 UID', {
      statusCode: 409,
      errorCode: `${errorCodePrefix}_not_ready`,
    })
  }

  // WAITING_BINDING + UID 匹配：自动升为 ROLE_CONFIRMED，实现一键兑换
  if (currentStatus === TASK_STATUS.WAITING_BINDING) {
    const flow = normalizeKuaishouCloudFlow(parseTaskContext(workingTask).kuaishouCloudFulfillment)
    if (!isKuaishouCloudMockTask(workingTask)) {
      assertBoundUidMatchesExpected(workingTask, flow, {
        errorCodePrefix,
      })
    } else {
      assertClaimExpectedUidReady(workingTask)
    }

    const confirmed = await updateTask(workingTask.id, {
      task_status: TASK_STATUS.ROLE_CONFIRMED,
      role_id: flow.binding.roleId || workingTask.role_id || '',
      role_name: flow.binding.roleName || workingTask.role_name || '',
      user_action_status: TASK_STATUS.ROLE_CONFIRMED,
      role_confirmed_at: now,
      last_error: '',
      updated_at: now,
    })
    if (confirmed) {
      workingTask = confirmed
    }
    await createTaskEvent(
      workingTask.id,
      'kuaishou_cloud_role_confirmed',
      {
        expectedUid: getClaimIdentityFromTask(workingTask).expectedUid,
        vnPhone: flow.binding.vnPhone,
        roleName: flow.binding.roleName,
        roleId: flow.binding.roleId,
        source: `${source}_one_click`,
      },
      now,
    )
  }

  const flowBeforeRedeem = normalizeKuaishouCloudFlow(
    parseTaskContext(workingTask).kuaishouCloudFulfillment,
  )
  if (!isKuaishouCloudMockTask(workingTask)) {
    assertBoundUidMatchesExpected(workingTask, flowBeforeRedeem, {
      errorCodePrefix,
    })
  } else {
    assertClaimExpectedUidReady(workingTask)
  }

  const lockedTask = await updateTaskStatusIfCurrent(workingTask.id, TASK_STATUS.ROLE_CONFIRMED, {
    task_status: TASK_STATUS.REDEEMING,
    user_action_status: 'not_required',
    last_error: '',
    updated_at: now,
  })

  if (!lockedTask) {
    const latest = (await getTaskById(workingTask.id)) || workingTask
    return {
      task: latest,
      alreadySettled: isKuaishouCloudRedeemSettledStatus(latest.task_status),
      concurrentSkipped: true,
    }
  }

  if (isKuaishouCloudMockTask(lockedTask)) {
    await completeMockKuaishouCloudTask(lockedTask, now)
    const completed = (await getTaskById(lockedTask.id)) || lockedTask
    return { task: completed, alreadySettled: false, concurrentSkipped: false }
  }

  try {
    const result = await dispatchKuaishouCloudFulfillmentTask(lockedTask, {
      source,
      actor,
      autoFinalize,
    })
    return {
      task: result.task || lockedTask,
      alreadySettled: false,
      concurrentSkipped: false,
    }
  } catch (error) {
    const latestTask = await getTaskById(lockedTask.id)
    const latestStatus = latestTask ? normalizeTaskStatus(latestTask.task_status) : ''

    if (latestTask && latestStatus !== TASK_STATUS.REDEEMING) {
      if (
        latestStatus === TASK_STATUS.DISPATCHED_PENDING_RETURN ||
        latestStatus === TASK_STATUS.COMPLETED ||
        latestStatus === TASK_STATUS.REDEEMED
      ) {
        return { task: latestTask, alreadySettled: true, concurrentSkipped: false }
      }
      throw error
    }

    const message = error instanceof Error ? error.message : '兑换请求提交失败，请联系客服处理'
    await updateTask(lockedTask.id, {
      task_status: TASK_STATUS.MANUAL_REVIEW,
      user_action_status: 'not_required',
      last_error: message,
      result_code: 'kuaishou_cloud_redeem_failed',
      result_message: message,
      updated_at: nowIso(),
    })

    await createTaskEvent(
      lockedTask.id,
      'kuaishou_cloud_redeem_failed',
      {
        source,
        errorMessage: message,
      },
      nowIso(),
    )

    throw error
  }
}
