import {
  ArrowLeftOutlined,
  CheckCircleOutlined,
  CloseCircleOutlined,
  CopyOutlined,
  ReloadOutlined,
  RollbackOutlined,
  SendOutlined,
  SwapOutlined,
  ToolOutlined,
  UserSwitchOutlined,
} from '@ant-design/icons'
import {
  Alert,
  App,
  Button,
  Card,
  Descriptions,
  Empty,
  Image,
  Input,
  Skeleton,
  Space,
  Table,
  Tabs,
  Tag,
  Typography,
} from 'antd'
import type { TableColumnsType } from 'antd'
import { useQuery } from '@tanstack/react-query'
import { useEffect, useMemo, useState } from 'react'
import { useNavigate, useParams } from 'react-router'

import JsonPreview from '@/components/admin/JsonPreview'
import PageHeader from '@/components/admin/PageHeader'
import StatusTag from '@/components/admin/StatusTag'
import {
  closeAdminTask,
  completeAdminTaskManualDispatch,
  consumeAdminTaskKuaishouIndustryVoucher,
  dispatchAdminTaskKuaishouCloudFulfillment,
  fetchAdminTaskDetail,
  fetchAdminTaskScreenshot,
  markAdminTaskManualReview,
  prepareAdminTaskKuaishouCloudFulfillment,
  rebindAdminTaskKuaishouCloudRole,
  refreshAdminTaskKuaishouCloudRoleInfo,
  resendAdminTaskKuaishouIndustryVoucherCode,
  retryAdminTask,
  returnNumberAdminTaskKuaishouCloudFulfillment,
} from '@/services/admin'
import type { AdminTaskActionResponse, AdminTaskDetail } from '@/types/admin'
import { hasAdminRole } from '@/utils/admin-auth'
import {
  formatKuaishouRoleInfoLabel,
  formatRedeemOutcomeLabel,
  formatRedeemResolutionStatus,
  formatTaskEventPayload,
  formatTaskEventType,
} from '@/utils/admin-display'
import { formatAdminDateTime } from '@/utils/admin-time'

type TaskEvent = AdminTaskDetail['events'][number]
type KuaishouIndustryVoucher = NonNullable<AdminTaskDetail['kuaishouIndustryVoucher']>
type ManualDispatchForm = {
  deliveryReference: string
  deliveredCredential: string
  resultMessage: string
}

export default function AdminTaskDetailPage() {
  const { taskId = '' } = useParams()
  const { message, modal } = App.useApp()
  const [actionLoadingKey, setActionLoadingKey] = useState('')
  const [lastClaimUrl, setLastClaimUrl] = useState('')
  const [screenshotPreviewUrl, setScreenshotPreviewUrl] = useState('')
  const [manualDispatchForm, setManualDispatchForm] = useState<ManualDispatchForm>({
    deliveryReference: '',
    deliveredCredential: '',
    resultMessage: '',
  })
  const query = useQuery({
    queryKey: ['admin-task-detail', taskId],
    queryFn: () => fetchAdminTaskDetail(taskId),
    enabled: Boolean(taskId),
  })
  const detail = query.data?.data
  const canManageTaskLifecycle = hasAdminRole('operator')
  const canOperateIndustryVoucher = hasAdminRole('support')
  const canCloseTasks = hasAdminRole('support')
  const claimTokenStatus = String(detail?.claimToken?.status || '').trim()
  const isExternalClaimLink = claimTokenStatus.toLowerCase() === 'external'
  const claimUrl = useMemo(() => {
    const tokenStatus = String(detail?.claimToken?.status || '').trim()
    const taskStatus = String(detail?.task.status || '').trim()

    if (!isUsableClaimLinkStatus(tokenStatus) || ['closed', 'expired'].includes(taskStatus)) {
      return ''
    }

    return lastClaimUrl || detail?.claimToken?.claimUrl || ''
  }, [detail?.claimToken?.claimUrl, detail?.claimToken?.status, detail?.task.status, lastClaimUrl])
  const claimLinkInvalid = Boolean(
    detail?.claimToken?.claimUrl && claimTokenStatus && !isUsableClaimLinkStatus(claimTokenStatus),
  )

  useEffect(() => {
    if (!detail) return

    setManualDispatchForm({
      deliveryReference: detail.manualDispatch?.deliveryReference || '',
      deliveredCredential: detail.manualDispatch?.deliveredCredential || '',
      resultMessage: detail.manualDispatch?.resultMessage || detail.task.resultMessage || '',
    })
  }, [detail])

  useEffect(() => {
    let objectUrl = ''
    setScreenshotPreviewUrl('')

    if (!detail?.screenshotUrl) {
      return undefined
    }

    fetchAdminTaskScreenshot(detail.task.taskId)
      .then((blob) => {
        objectUrl = URL.createObjectURL(blob)
        setScreenshotPreviewUrl(objectUrl)
      })
      .catch(() => {
        setScreenshotPreviewUrl('')
      })

    return () => {
      if (objectUrl) {
        URL.revokeObjectURL(objectUrl)
      }
    }
  }, [detail?.screenshotUrl, detail?.task.taskId])

  if (query.isLoading) {
    return (
      <section className="page-stack">
        <PageHeader title="任务详情" extra={<BackButton />} />
        <Card>
          <Skeleton active paragraph={{ rows: 10 }} />
        </Card>
      </section>
    )
  }

  if (query.error || !detail) {
    return (
      <section className="page-stack">
        <PageHeader title="任务详情" extra={<BackButton />} />
        <Alert
          type="error"
          showIcon
          message={query.error instanceof Error ? query.error.message : '任务不存在或读取失败'}
        />
      </section>
    )
  }

  const resolvedDetail = detail
  const flow = resolvedDetail.kuaishouCloudFulfillment
  const eventColumns: TableColumnsType<TaskEvent> = [
    {
      title: '时间',
      dataIndex: 'createdAt',
      width: 180,
      render: (value) => formatAdminDateTime(value),
    },
    {
      title: '事件',
      dataIndex: 'eventType',
      width: 180,
      render: (value) => formatTaskEventType(value),
    },
    {
      title: '摘要',
      render: (_, row) => formatTaskEventPayload(row.payload),
    },
  ]

  async function copyClaimUrl() {
    if (!claimUrl) return
    await navigator.clipboard.writeText(claimUrl)
    message.success('领取链接已复制')
  }

  function runTaskAction(
    actionKey: string,
    action: () => Promise<{ data: AdminTaskActionResponse }>,
    successMessage: string,
    confirmText: string,
  ) {
    modal.confirm({
      title: '确认操作',
      content: confirmText,
      okText: '继续执行',
      cancelText: '取消',
      centered: true,
      onOk: async () => {
        setActionLoadingKey(actionKey)
        try {
          const response = await action()
          if (response.data.claimUrl) {
            setLastClaimUrl(response.data.claimUrl)
          }
          message.success(successMessage)
          await query.refetch()
        } catch (error) {
          message.error(error instanceof Error ? error.message : '操作失败')
        } finally {
          setActionLoadingKey('')
        }
      },
    })
  }

  function submitManualDispatch(outcome: 'delivered' | 'failed') {
    const actionLabel = outcome === 'failed' ? '标记履约失败' : '标记已完成履约'
    const confirmText =
      outcome === 'failed'
        ? `确认把任务 ${resolvedDetail.task.taskNo} 回写为人工履约失败吗？这会把任务直接收口并保留失败原因。`
        : `确认把任务 ${resolvedDetail.task.taskNo} 回写为人工履约完成吗？这会把任务直接标记为已发放。`

    runTaskAction(
      `manual-${outcome}`,
      () =>
        completeAdminTaskManualDispatch(resolvedDetail.task.taskId, {
          outcome,
          resultMessage: manualDispatchForm.resultMessage,
          deliveryReference: manualDispatchForm.deliveryReference,
          deliveredCredential: manualDispatchForm.deliveredCredential,
        }),
      actionLabel,
      confirmText,
    )
  }

  return (
    <section className="page-stack">
      <PageHeader
        title="任务详情"
        description={resolvedDetail.task.taskNo}
        extra={
          <Space wrap>
            <Button icon={<ReloadOutlined />} onClick={() => query.refetch()}>
              刷新
            </Button>
            <BackButton />
          </Space>
        }
      />

      <FulfillmentOverviewPanel
        detail={resolvedDetail}
        claimUrl={claimUrl}
        claimLinkInvalid={claimLinkInvalid}
      />

      <TaskActionPanel
        detail={resolvedDetail}
        canManageTaskLifecycle={canManageTaskLifecycle}
        canOperateIndustryVoucher={canOperateIndustryVoucher}
        canCloseTasks={canCloseTasks}
        actionLoadingKey={actionLoadingKey}
        onRetry={() =>
          runTaskAction(
            'retry',
            () => retryAdminTask(resolvedDetail.task.taskId),
            '任务已重试',
            `确认重试任务 ${resolvedDetail.task.taskNo} 吗？`,
          )
        }
        onRebindRole={() =>
          runTaskAction(
            'rebind-role',
            () => rebindAdminTaskKuaishouCloudRole(resolvedDetail.task.taskId),
            '换绑完成：已生成新的绑定链接',
            `确认为任务 ${resolvedDetail.task.taskNo} 换绑吗？会退还当前虚拟号并生成新绑链；若旧号已被系统回收会自动跳过退号并直接新取号。原领取链接可继续使用。`,
          )
        }
        onPrepareKuaishouCloud={() =>
          runTaskAction(
            'prepare-kuaishou-cloud',
            () => prepareAdminTaskKuaishouCloudFulfillment(resolvedDetail.task.taskId),
            '绑定资源已准备完成',
            `确认开始为任务 ${resolvedDetail.task.taskNo} 准备绑定资源吗？系统会自动检查库存配置并申请虚拟号。`,
          )
        }
        onDispatchKuaishouCloud={() =>
          runTaskAction(
            'dispatch-kuaishou-cloud',
            () => dispatchAdminTaskKuaishouCloudFulfillment(resolvedDetail.task.taskId),
            '已完成绑定确认并发货',
            `确认客户已经完成绑定，并立即为任务 ${resolvedDetail.task.taskNo} 执行发货吗？这个动作会把"确认绑定完成"和"发货"合并为一步。`,
          )
        }
        onReturnKuaishouCloud={() =>
          runTaskAction(
            'return-kuaishou-cloud',
            () => returnNumberAdminTaskKuaishouCloudFulfillment(resolvedDetail.task.taskId),
            '号码已退还',
            `确认退还任务 ${resolvedDetail.task.taskNo} 当前使用的虚拟号吗？退号后该流程会正式收口。`,
          )
        }
        onResendIndustryVoucher={() =>
          runTaskAction(
            'resend-industry-voucher',
            () => resendAdminTaskKuaishouIndustryVoucherCode(resolvedDetail.task.taskId),
            '电子凭证发码回调已重发',
            `确认重新发送任务 ${resolvedDetail.task.taskNo} 的电子凭证发码回调吗？`,
          )
        }
        onConsumeIndustryVoucher={() =>
          runTaskAction(
            'consume-industry-voucher',
            () => consumeAdminTaskKuaishouIndustryVoucher(resolvedDetail.task.taskId),
            '电子凭证已执行核销',
            `确认立即核销任务 ${resolvedDetail.task.taskNo} 绑定的电子凭证吗？`,
          )
        }
        onMarkManualReview={() =>
          runTaskAction(
            'manual-review',
            () => markAdminTaskManualReview(resolvedDetail.task.taskId),
            '任务已转人工处理',
            `确认将任务 ${resolvedDetail.task.taskNo} 转为人工处理吗？`,
          )
        }
        onCloseTask={() =>
          runTaskAction(
            'close',
            () => closeAdminTask(resolvedDetail.task.taskId),
            '任务已关闭',
            `确认关闭任务 ${resolvedDetail.task.taskNo} 吗？关闭后不会自动继续推进。`,
          )
        }
      />

      <Card title="基础信息">
        <Descriptions column={{ xs: 1, md: 2, xl: 3 }} bordered size="small">
          <Descriptions.Item label="任务 ID">{resolvedDetail.task.taskId}</Descriptions.Item>
          <Descriptions.Item label="任务号">{resolvedDetail.task.taskNo}</Descriptions.Item>
          <Descriptions.Item label="平台订单号">
            {resolvedDetail.task.platformOrderId || resolvedDetail.order?.platformOrderId || '-'}
          </Descriptions.Item>
          <Descriptions.Item label="任务状态">
            <StatusTag value={resolvedDetail.task.status} kind="task" />
          </Descriptions.Item>
          <Descriptions.Item label="资源状态">
            <StatusTag value={resolvedDetail.task.resourceStatus} kind="resource" />
          </Descriptions.Item>
          <Descriptions.Item label="客户步骤">
            <StatusTag value={resolvedDetail.task.customerStatus} kind="customer" />
          </Descriptions.Item>
          <Descriptions.Item label="商品">
            {resolvedDetail.orderItem?.skuName || resolvedDetail.task.skuName || '-'}
          </Descriptions.Item>
          <Descriptions.Item label="角色">
            {resolvedDetail.task.roleName || '-'}{' '}
            {resolvedDetail.task.roleId ? `(${resolvedDetail.task.roleId})` : ''}
          </Descriptions.Item>
          <Descriptions.Item label="更新时间">
            {formatAdminDateTime(resolvedDetail.task.updatedAt)}
          </Descriptions.Item>
          <Descriptions.Item label="最近错误" span={3}>
            {resolvedDetail.task.lastError || '-'}
          </Descriptions.Item>
        </Descriptions>
      </Card>

      {resolvedDetail.claimToken ? (
        <Card title="领取链接">
          <Space direction="vertical" size={8} className="full-width">
            {claimUrl ? (
              <Typography.Text copyable={{ text: claimUrl }}>{claimUrl}</Typography.Text>
            ) : claimLinkInvalid ? (
              <Typography.Text type="secondary">领取链接已失效</Typography.Text>
            ) : (
              <Typography.Text type="secondary">暂无可用领取链接</Typography.Text>
            )}
            <Space wrap>
              <StatusTag value={resolvedDetail.claimToken.status} />
              {isExternalClaimLink ? (
                <Typography.Text type="secondary">外部交付链接</Typography.Text>
              ) : (
                <Typography.Text type="secondary">
                  {resolvedDetail.claimToken.expiredAt
                    ? `到期：${formatAdminDateTime(resolvedDetail.claimToken.expiredAt)}`
                    : '长期有效'}
                </Typography.Text>
              )}
              <Button icon={<CopyOutlined />} disabled={!claimUrl} onClick={copyClaimUrl}>
                复制链接
              </Button>
            </Space>
          </Space>
        </Card>
      ) : null}

      {resolvedDetail.task.executorKey === 'manual_dispatch' ||
      resolvedDetail.operations.canCompleteManualDispatch ||
      resolvedDetail.manualDispatch ? (
        <ManualDispatchPanel
          detail={resolvedDetail}
          form={manualDispatchForm}
          canSubmit={canManageTaskLifecycle && resolvedDetail.operations.canCompleteManualDispatch}
          actionLoadingKey={actionLoadingKey}
          onChange={setManualDispatchForm}
          onSubmit={submitManualDispatch}
        />
      ) : null}

      <Tabs
        items={[
          {
            key: 'cloud',
            label: 'kuaishou-lewan',
            children: flow ? (
              <KuaishouCloudPanel
                flow={flow}
                canRefresh={resolvedDetail.operations.canRefreshKuaishouCloudRoleInfo}
                actionLoadingKey={actionLoadingKey}
                onRefreshRole={() =>
                  runTaskAction(
                    'refresh-role',
                    () => refreshAdminTaskKuaishouCloudRoleInfo(resolvedDetail.task.taskId),
                    '角色信息已刷新',
                    `确认刷新任务 ${resolvedDetail.task.taskNo} 当前云绑定角色信息吗？系统会重新查询 kuaishou-lewan 的绑定结果。`,
                  )
                }
              />
            ) : (
              <Empty description="无 kuaishou-lewan 履约上下文" />
            ),
          },
          {
            key: 'industry-voucher',
            label: '电子凭证',
            children: resolvedDetail.kuaishouIndustryVoucher ? (
              <KuaishouIndustryVoucherPanel voucher={resolvedDetail.kuaishouIndustryVoucher} />
            ) : (
              <Empty description="无电子凭证绑定" />
            ),
          },
          {
            key: 'resolution',
            label: '兑换重试',
            children: resolvedDetail.redeemResolution ? (
              <RedeemResolutionPanel resolution={resolvedDetail.redeemResolution} />
            ) : (
              <Empty description="无兑换重试记录" />
            ),
          },
          {
            key: 'screenshot',
            label: '截图',
            children: resolvedDetail.screenshotUrl ? (
              <ScreenshotPanel screenshotPreviewUrl={screenshotPreviewUrl} />
            ) : (
              <Empty description="当前任务没有截图" />
            ),
          },
          {
            key: 'events',
            label: '事件流水',
            children: (
              <Table<TaskEvent>
                rowKey="eventId"
                pagination={false}
                columns={eventColumns}
                dataSource={resolvedDetail.events}
                scroll={{ x: 760 }}
              />
            ),
          },
          {
            key: 'raw',
            label: '原始数据',
            children: <JsonPreview value={resolvedDetail} />,
          },
        ]}
      />
    </section>
  )
}

function TaskActionPanel({
  detail,
  canManageTaskLifecycle,
  canOperateIndustryVoucher,
  canCloseTasks,
  actionLoadingKey,
  onRetry,
  onRebindRole,
  onPrepareKuaishouCloud,
  onDispatchKuaishouCloud,
  onReturnKuaishouCloud,
  onResendIndustryVoucher,
  onConsumeIndustryVoucher,
  onMarkManualReview,
  onCloseTask,
}: {
  detail: AdminTaskDetail
  canManageTaskLifecycle: boolean
  canOperateIndustryVoucher: boolean
  canCloseTasks: boolean
  actionLoadingKey: string
  onRetry: () => void
  onRebindRole: () => void
  onPrepareKuaishouCloud: () => void
  onDispatchKuaishouCloud: () => void
  onReturnKuaishouCloud: () => void
  onResendIndustryVoucher: () => void
  onConsumeIndustryVoucher: () => void
  onMarkManualReview: () => void
  onCloseTask: () => void
}) {
  const operations = detail.operations
  const loading = Boolean(actionLoadingKey)
  const hasCloudActions =
    operations.canPrepareKuaishouCloudFulfillment ||
    operations.canRebindKuaishouCloudRole ||
    operations.canDispatchKuaishouCloudFulfillment ||
    operations.canReturnKuaishouCloudFulfillment
  const hasIndustryVoucherActions =
    operations.canResendKuaishouIndustryVoucherCode ||
    operations.canConsumeKuaishouIndustryVoucher ||
    Boolean(detail.kuaishouIndustryVoucher)

  return (
    <Card title="任务操作">
      <div className="task-action-groups">
        {canManageTaskLifecycle ? (
          <section className="task-action-group">
            <Typography.Text type="secondary">通用</Typography.Text>
            <Space wrap>
              <Button
                type="primary"
                icon={<ReloadOutlined />}
                disabled={loading || !operations.canRetry}
                loading={actionLoadingKey === 'retry'}
                onClick={onRetry}
              >
                重试任务
              </Button>
              <Button
                icon={<UserSwitchOutlined />}
                disabled={loading || !operations.canMarkManualReview}
                loading={actionLoadingKey === 'manual-review'}
                onClick={onMarkManualReview}
              >
                转人工
              </Button>
            </Space>
          </section>
        ) : null}

        {hasCloudActions ? (
          <section className="task-action-group">
            <Typography.Text type="secondary">kuaishou-lewan</Typography.Text>
            <Space wrap>
              {canManageTaskLifecycle && operations.canPrepareKuaishouCloudFulfillment ? (
                <Button
                  type="primary"
                  ghost
                  icon={<ToolOutlined />}
                  disabled={loading}
                  loading={actionLoadingKey === 'prepare-kuaishou-cloud'}
                  onClick={onPrepareKuaishouCloud}
                >
                  准备资源
                </Button>
              ) : null}
              {operations.canRebindKuaishouCloudRole ? (
                <Button
                  icon={<SwapOutlined />}
                  disabled={loading}
                  loading={actionLoadingKey === 'rebind-role'}
                  onClick={onRebindRole}
                >
                  换绑
                </Button>
              ) : null}
              {canManageTaskLifecycle && operations.canDispatchKuaishouCloudFulfillment ? (
                <Button
                  type="primary"
                  icon={<SendOutlined />}
                  disabled={loading}
                  loading={actionLoadingKey === 'dispatch-kuaishou-cloud'}
                  onClick={onDispatchKuaishouCloud}
                >
                  发货
                </Button>
              ) : null}
              {canManageTaskLifecycle && operations.canReturnKuaishouCloudFulfillment ? (
                <Button
                  icon={<RollbackOutlined />}
                  disabled={loading}
                  loading={actionLoadingKey === 'return-kuaishou-cloud'}
                  onClick={onReturnKuaishouCloud}
                >
                  退号
                </Button>
              ) : null}
            </Space>
          </section>
        ) : null}

        {canOperateIndustryVoucher && hasIndustryVoucherActions ? (
          <section className="task-action-group">
            <Typography.Text type="secondary">电子凭证</Typography.Text>
            <Space wrap>
              <Button
                icon={<ReloadOutlined />}
                disabled={loading || !operations.canResendKuaishouIndustryVoucherCode}
                loading={actionLoadingKey === 'resend-industry-voucher'}
                onClick={onResendIndustryVoucher}
              >
                重发发码
              </Button>
              <Button
                type="primary"
                ghost
                icon={<CheckCircleOutlined />}
                disabled={loading || !operations.canConsumeKuaishouIndustryVoucher}
                loading={actionLoadingKey === 'consume-industry-voucher'}
                onClick={onConsumeIndustryVoucher}
              >
                核销凭证
              </Button>
            </Space>
          </section>
        ) : null}

        {canCloseTasks ? (
          <section className="task-action-group">
            <Typography.Text type="secondary">收口</Typography.Text>
            <Button
              danger
              icon={<CloseCircleOutlined />}
              disabled={loading || !operations.canClose}
              loading={actionLoadingKey === 'close'}
              onClick={onCloseTask}
            >
              关闭任务
            </Button>
          </section>
        ) : null}

        {!canManageTaskLifecycle &&
        !canOperateIndustryVoucher &&
        !canCloseTasks &&
        !hasCloudActions ? (
          <Typography.Text type="secondary">当前账号没有可执行的任务操作</Typography.Text>
        ) : null}
      </div>
      {loading ? (
        <Typography.Text className="task-action-hint" type="secondary">
          操作执行中，请稍候。
        </Typography.Text>
      ) : null}
    </Card>
  )
}

function isUsableClaimLinkStatus(value: unknown) {
  const normalized = String(value || '')
    .trim()
    .toLowerCase()
  return normalized === 'active' || normalized === 'external'
}

function FulfillmentOverviewPanel({
  detail,
  claimUrl,
  claimLinkInvalid,
}: {
  detail: AdminTaskDetail
  claimUrl: string
  claimLinkInvalid: boolean
}) {
  const executor = resolveTaskExecutorDisplay(detail.task.executorKey)
  const steps = buildFulfillmentOverviewSteps(detail, claimUrl, claimLinkInvalid)
  const claimIdentity = detail.claimIdentity
  const currentBlocker = resolveTaskBlocker(detail.task, claimUrl, claimLinkInvalid, claimIdentity)
  const uidMatchTag =
    claimIdentity?.uidMatched === true
      ? { color: 'success' as const, text: 'UID 已匹配' }
      : claimIdentity?.uidMatched === false
        ? { color: 'error' as const, text: 'UID 不一致' }
        : claimIdentity?.ready
          ? { color: 'processing' as const, text: '已填 UID' }
          : { color: 'warning' as const, text: '未填 UID' }

  return (
    <Card title="履约链路总览" extra={<Tag color={executor.color}>{executor.label}</Tag>}>
      <Descriptions
        size="small"
        column={{ xs: 1, sm: 2, md: 3 }}
        className="platform-section-gap"
        style={{ marginBottom: 12 }}
      >
        <Descriptions.Item label="填写 UID">
          {claimIdentity?.expectedUid || <Typography.Text type="warning">未提交</Typography.Text>}
        </Descriptions.Item>
        <Descriptions.Item label="绑定角色 ID">
          {claimIdentity?.boundUid || detail.task.roleId || '-'}
          {claimIdentity?.displaySource === 'shipped' ? (
            <Tag color="blue" style={{ marginLeft: 6 }}>
              发货快照
            </Tag>
          ) : null}
        </Descriptions.Item>
        <Descriptions.Item label="绑定角色名">
          {claimIdentity?.boundRoleName || detail.task.roleName || '-'}
        </Descriptions.Item>
        <Descriptions.Item label="匹配状态">
          <Tag color={uidMatchTag.color}>{uidMatchTag.text}</Tag>
        </Descriptions.Item>
        <Descriptions.Item label="兼容模式">
          {claimIdentity?.compatibilityMode === 'legacy_no_uid' ? '旧单无 UID' : 'UID 闸门'}
        </Descriptions.Item>
        {claimIdentity?.shippedUid ? (
          <Descriptions.Item label="发货 UID / 角色" span={2}>
            {claimIdentity.shippedUid}
            {claimIdentity.shippedRoleName ? ` / ${claimIdentity.shippedRoleName}` : ''}
            {claimIdentity.shippedAt ? (
              <Typography.Text type="secondary" style={{ marginLeft: 8 }}>
                {claimIdentity.shippedAt}
              </Typography.Text>
            ) : null}
          </Descriptions.Item>
        ) : null}
        <Descriptions.Item label="说明" span={3}>
          <Typography.Text type="secondary">
            {claimIdentity?.note || '暂无 UID 信息'}
          </Typography.Text>
        </Descriptions.Item>
      </Descriptions>

      <div className="fulfillment-overview-grid">
        {steps.map((step) => (
          <div key={step.key} className="fulfillment-step-card">
            <Space size={[6, 6]} wrap>
              <StatusTag value={step.status} />
              <Typography.Text strong>{step.label}</Typography.Text>
            </Space>
            <Typography.Text type="secondary">{step.detail}</Typography.Text>
          </div>
        ))}
      </div>

      <Alert
        className="platform-section-gap"
        type={currentBlocker.level}
        showIcon
        message={currentBlocker.title}
        description={currentBlocker.detail}
      />
    </Card>
  )
}

function buildFulfillmentOverviewSteps(
  detail: AdminTaskDetail,
  claimUrl: string,
  claimLinkInvalid: boolean,
) {
  const task = detail.task
  const executor = resolveTaskExecutorDisplay(task.executorKey)
  const voucher = detail.kuaishouIndustryVoucher
  const manualDispatch = detail.manualDispatch
  const claimStatus = claimUrl
    ? 'success'
    : claimLinkInvalid
      ? 'failed'
      : detail.claimToken?.status || 'pending'

  return [
    {
      key: 'source',
      label: '订单来源',
      status: detail.order?.payStatus || task.status,
      detail: `${detail.order?.provider || '-'} / ${detail.order?.platform || '-'} / ${task.platformOrderId || '-'}`,
    },
    {
      key: 'product',
      label: '商品解析',
      status: detail.orderItem || task.skuName ? 'success' : 'pending_config',
      detail: detail.orderItem?.skuName || task.skuName || task.skuCode || '未命中履约商品',
    },
    {
      key: 'planner',
      label: '履约计划',
      status: task.executorKey ? 'success' : 'pending_config',
      detail: executor.label,
    },
    {
      key: 'prepare',
      label: '任务准备',
      status: task.resourceStatus || task.status,
      detail: resolveTaskPrepareSummary(detail),
    },
    {
      key: 'delivery',
      label: '平台执行',
      status: resolveDeliveryStepStatus(detail),
      detail: resolveDeliveryStepSummary(detail),
    },
    {
      key: 'voucher',
      label: '电子凭证',
      status: voucher ? voucher.sendCallbackStatus || voucher.status : 'skipped',
      detail: voucher
        ? `发码 ${voucher.sendCallbackStatus || '-'} / 凭证 ${voucher.status || '-'}`
        : '当前任务未绑定电子凭证',
    },
    {
      key: 'claim',
      label: '交付链接',
      status: task.executorKey === 'manual_dispatch' ? 'skipped' : claimStatus,
      detail:
        task.executorKey === 'manual_dispatch'
          ? '人工履约不需要客户领取链接'
          : claimUrl
            ? '已有可用链接'
            : claimLinkInvalid
              ? '链接已失效'
              : '等待生成或同步链接',
    },
    {
      key: 'finish',
      label: '履约收口',
      status: manualDispatch?.outcome || task.deliveryStatus || task.status,
      detail: task.resultMessage || task.lastError || '等待履约完成',
    },
  ]
}

function resolveTaskBlocker(
  task: AdminTaskDetail['task'],
  claimUrl: string,
  claimLinkInvalid: boolean,
  claimIdentity?: AdminTaskDetail['claimIdentity'],
): { level: 'success' | 'info' | 'warning' | 'error'; title: string; detail: string } {
  if (
    ['completed', 'redeemed', 'delivered'].includes(task.status) ||
    task.deliveryStatus === 'delivered'
  ) {
    return {
      level: 'success',
      title: '履约已完成',
      detail: task.resultMessage || '任务已经收口。',
    }
  }

  if (['manual_review', 'retry_pending', 'failed'].includes(task.status)) {
    return {
      level: 'error',
      title: '当前卡在异常处理',
      detail: task.lastError || task.resultMessage || '需要人工检查后重试或收口。',
    }
  }

  if (task.executorKey === 'kuaishou_ct_assisted' && claimIdentity && !claimIdentity.ready) {
    return {
      level: 'warning',
      title: '等待用户填写 UID',
      detail: '旧单或新单均需用户打开领取页提交游戏 UID，否则禁止自动发货。',
    }
  }

  if (task.executorKey === 'kuaishou_ct_assisted' && claimIdentity?.uidMatched === false) {
    return {
      level: 'error',
      title: 'UID 与绑定角色不一致',
      detail: `填写 ${claimIdentity.expectedUid || '-'}，绑定 ${claimIdentity.boundUid || '-'}，请用户换绑或更正 UID。`,
    }
  }

  if (claimLinkInvalid) {
    return {
      level: 'warning',
      title: '领取链接不可用',
      detail: '链接状态不是 active，可重新生成或检查平台交付链接。',
    }
  }

  if (!claimUrl && task.executorKey !== 'manual_dispatch') {
    return {
      level: 'warning',
      title: '等待交付链接',
      detail: '任务尚未拿到可交付链接，先检查任务准备和平台执行状态。',
    }
  }

  if (task.customerStatus === 'waiting_customer') {
    return {
      level: 'info',
      title: '等待客户操作',
      detail: '资源已准备，客户还没有完成绑定或领取动作。',
    }
  }

  return {
    level: 'info',
    title: '履约推进中',
    detail: task.lastError || '当前任务没有明确异常，可按链路状态继续观察。',
  }
}

function resolveTaskPrepareSummary(detail: AdminTaskDetail) {
  const flow = detail.kuaishouCloudFulfillment
  if (flow) {
    return flow.binding.bindPreparedAt
      ? `绑定资源 ${flow.binding.vnPhone || flow.binding.vnId || '-'}`
      : '等待准备 Cloud 资源'
  }

  if (detail.task.executorKey === 'manual_dispatch') {
    return '人工履约任务无需自动准备资源'
  }

  return detail.task.resultMessage || detail.task.lastError || '等待执行器准备'
}

function resolveDeliveryStepStatus(detail: AdminTaskDetail) {
  const flow = detail.kuaishouCloudFulfillment
  if (flow) {
    return flow.dispatch.status || detail.task.deliveryStatus || detail.task.status
  }

  if (detail.manualDispatch) {
    return detail.manualDispatch.outcome || detail.task.deliveryStatus
  }

  return detail.task.deliveryStatus || detail.task.status
}

function resolveDeliveryStepSummary(detail: AdminTaskDetail) {
  const flow = detail.kuaishouCloudFulfillment
  if (flow) {
    if (flow.dispatch.dispatchAt) {
      return `已于 ${formatAdminDateTime(flow.dispatch.dispatchAt)} 发货`
    }
    return flow.dispatch.note || '等待平台发货执行'
  }

  if (detail.manualDispatch) {
    return (
      detail.manualDispatch.resultMessage ||
      detail.manualDispatch.deliveryReference ||
      '人工履约已回写'
    )
  }

  return detail.task.resultMessage || detail.task.lastError || '等待执行器推进'
}

function resolveTaskExecutorDisplay(value: unknown) {
  const executorKey = String(value || '').trim()
  if (executorKey === 'kuaishou_ct_assisted') {
    return { label: 'kuaishou-lewan', color: 'blue' }
  }
  if (executorKey === 'kuaishou-industry') {
    return { label: '行业电子凭证', color: 'cyan' }
  }
  if (executorKey === 'kuaishou_feifei') {
    return { label: 'kuaishou-feifei', color: 'purple' }
  }
  if (executorKey === 'manual_dispatch') {
    return { label: '人工履约', color: 'orange' }
  }
  return { label: executorKey || '未分配执行器', color: 'default' }
}

function ManualDispatchPanel({
  detail,
  form,
  canSubmit,
  actionLoadingKey,
  onChange,
  onSubmit,
}: {
  detail: AdminTaskDetail
  form: ManualDispatchForm
  canSubmit: boolean
  actionLoadingKey: string
  onChange: (form: ManualDispatchForm) => void
  onSubmit: (outcome: 'delivered' | 'failed') => void
}) {
  return (
    <Card
      title="人工履约"
      extra={
        canSubmit ? (
          <Space>
            <Button
              type="primary"
              icon={<CheckCircleOutlined />}
              disabled={Boolean(actionLoadingKey)}
              loading={actionLoadingKey === 'manual-delivered'}
              onClick={() => onSubmit('delivered')}
            >
              人工完成
            </Button>
            <Button
              danger
              icon={<CloseCircleOutlined />}
              disabled={Boolean(actionLoadingKey)}
              loading={actionLoadingKey === 'manual-failed'}
              onClick={() => onSubmit('failed')}
            >
              履约失败
            </Button>
          </Space>
        ) : null
      }
    >
      <div className="manual-dispatch-grid">
        <div>
          <Typography.Text type="secondary">履约单号 / 回执</Typography.Text>
          <Input
            value={form.deliveryReference}
            disabled={!canSubmit || Boolean(actionLoadingKey)}
            placeholder="例如快递单号、平台消息回执号"
            onChange={(event) => onChange({ ...form, deliveryReference: event.target.value })}
          />
        </div>
        <div>
          <Typography.Text type="secondary">发放凭据</Typography.Text>
          <Input.TextArea
            value={form.deliveredCredential}
            disabled={!canSubmit || Boolean(actionLoadingKey)}
            placeholder="可填写人工发送的卡密、链接或关键信息"
            rows={3}
            onChange={(event) => onChange({ ...form, deliveredCredential: event.target.value })}
          />
        </div>
        <div>
          <Typography.Text type="secondary">处理备注</Typography.Text>
          <Input.TextArea
            value={form.resultMessage}
            disabled={!canSubmit || Boolean(actionLoadingKey)}
            placeholder="说明实际履约结果，失败时建议写清原因"
            rows={3}
            onChange={(event) => onChange({ ...form, resultMessage: event.target.value })}
          />
        </div>
      </div>

      <Alert
        className="platform-section-gap"
        type="info"
        showIcon
        message="回写后会直接更新任务终态，不再走旧式领取链接流程。"
      />

      {detail.manualDispatch ? (
        <Descriptions
          className="platform-section-gap"
          column={{ xs: 1, md: 2, xl: 3 }}
          bordered
          size="small"
        >
          <Descriptions.Item label="处理结果">
            <StatusTag value={detail.manualDispatch.outcome || detail.task.deliveryStatus} />
          </Descriptions.Item>
          <Descriptions.Item label="处理时间">
            {formatAdminDateTime(detail.manualDispatch.completedAt)}
          </Descriptions.Item>
          <Descriptions.Item label="处理人">
            {detail.manualDispatch.completedBy?.username || '-'} /{' '}
            {detail.manualDispatch.completedBy?.role || '-'}
          </Descriptions.Item>
          <Descriptions.Item label="履约单号">
            {detail.manualDispatch.deliveryReference || '-'}
          </Descriptions.Item>
          <Descriptions.Item label="发放凭据">
            {detail.manualDispatch.deliveredCredential || '-'}
          </Descriptions.Item>
          <Descriptions.Item label="备注">
            {detail.manualDispatch.resultMessage || '-'}
          </Descriptions.Item>
        </Descriptions>
      ) : null}
    </Card>
  )
}

function KuaishouIndustryVoucherPanel({ voucher }: { voucher: KuaishouIndustryVoucher }) {
  const consumeDetails = Array.isArray(voucher.consumeDetails) ? voucher.consumeDetails : []

  return (
    <Card title="电子凭证">
      <Descriptions column={{ xs: 1, md: 2, xl: 3 }} bordered size="small">
        <Descriptions.Item label="订单号">{voucher.oid || '-'}</Descriptions.Item>
        <Descriptions.Item label="凭证码">{voucher.voucherCode || '-'}</Descriptions.Item>
        <Descriptions.Item label="序号">{voucher.unitIndex || '-'}</Descriptions.Item>
        <Descriptions.Item label="凭证状态">
          <StatusTag value={voucher.status} />
        </Descriptions.Item>
        <Descriptions.Item label="发码回调">
          <StatusTag value={voucher.sendCallbackStatus} />
        </Descriptions.Item>
        <Descriptions.Item label="发码次数">{voucher.sendCallbackAttemptCount}</Descriptions.Item>
        <Descriptions.Item label="发码时间">
          {formatAdminDateTime(voucher.sendCallbackSentAt)}
        </Descriptions.Item>
        <Descriptions.Item label="核销流水">{voucher.consumeSerialNum || '-'}</Descriptions.Item>
        <Descriptions.Item label="核销时间">
          {formatAdminDateTime(voucher.consumedAt)}
        </Descriptions.Item>
        <Descriptions.Item label="最近异常" span={3}>
          {voucher.sendCallbackLastError || '-'}
        </Descriptions.Item>
      </Descriptions>

      {voucher.sendCallbackLastError ? (
        <Alert
          className="platform-section-gap"
          type="warning"
          showIcon
          message="电子凭证发码回调存在异常"
          description={voucher.sendCallbackLastError}
        />
      ) : null}

      {consumeDetails.length > 0 ? (
        <Table<Record<string, unknown>>
          className="platform-section-gap"
          rowKey={(_, index) => String(index ?? 0)}
          pagination={false}
          dataSource={consumeDetails}
          scroll={{ x: 760 }}
          columns={[
            {
              title: '核销明细',
              render: (_, row) => <JsonPreview value={row} />,
            },
          ]}
        />
      ) : null}
    </Card>
  )
}

function KuaishouCloudPanel({
  flow,
  canRefresh,
  actionLoadingKey,
  onRefreshRole,
}: {
  flow: NonNullable<AdminTaskDetail['kuaishouCloudFulfillment']>
  canRefresh: boolean
  actionLoadingKey: string
  onRefreshRole: () => void
}) {
  const roleInfoEntries = flow.role.rawInfo
    ? Object.entries(flow.role.rawInfo).filter(
        ([, value]) => value !== null && value !== undefined && String(value).trim() !== '',
      )
    : []
  const checklist = [
    {
      key: 'ticket',
      label: '凭证确认',
      status: flow.ticket.status || 'pending',
      detail: flow.ticket.verifiedAt
        ? `已于 ${formatAdminDateTime(flow.ticket.verifiedAt)} 确认`
        : '等待电子凭证同步确认',
    },
    {
      key: 'bind',
      label: '绑定资源',
      status: flow.binding.prepareStatus || 'pending',
      detail: flow.binding.bindPreparedAt
        ? `绑定资源已准备，VN ${flow.binding.vnId || '-'}`
        : '等待准备 Cloud 绑定资源',
    },
    {
      key: 'role',
      label: '角色识别',
      status: flow.role.status || 'pending',
      detail:
        flow.role.name || flow.role.rid
          ? `${flow.role.name || '-'} / ${flow.role.rid || '-'}`
          : '客户绑定后刷新角色信息',
    },
    {
      key: 'dispatch',
      label: '发货执行',
      status: flow.dispatch.status || 'pending',
      detail: flow.dispatch.dispatchAt
        ? `已于 ${formatAdminDateTime(flow.dispatch.dispatchAt)} 发货`
        : '等待客服确认绑定并发货',
    },
    {
      key: 'return',
      label: '退还号码',
      status: flow.returnNumber.status || 'pending',
      detail: flow.returnNumber.returnedAt
        ? `已于 ${formatAdminDateTime(flow.returnNumber.returnedAt)} 退号`
        : '发货后执行退还号码',
    },
    {
      key: 'consume',
      label: '电子凭证核销',
      status: flow.consume.status || 'pending',
      detail: flow.consume.consumedAt
        ? `已于 ${formatAdminDateTime(flow.consume.consumedAt)} 核销（链接交付或履约收口）`
        : flow.consume.errorMessage || '等待 91 交付链接时核销，或发货收口时补核销',
    },
  ]

  return (
    <section className="kuaishou-cloud-stack">
      <Card
        title="kuaishou-lewan 履约"
        extra={
          <Button
            icon={<ReloadOutlined />}
            disabled={Boolean(actionLoadingKey) || !canRefresh}
            loading={actionLoadingKey === 'refresh-role'}
            onClick={onRefreshRole}
          >
            刷新角色
          </Button>
        }
      >
        <Descriptions column={{ xs: 1, md: 2, xl: 3 }} bordered size="small">
          <Descriptions.Item label="来源账号">
            {flow.binding.resolvedSourceLabel || flow.binding.resolvedSourceKey || '-'}
          </Descriptions.Item>
          <Descriptions.Item label="虚拟号">
            {flow.binding.vnPhone || flow.binding.vnId || '-'}
          </Descriptions.Item>
          <Descriptions.Item label="绑定状态">
            <StatusTag value={flow.binding.prepareStatus} />
          </Descriptions.Item>
          <Descriptions.Item label="角色">
            {flow.role.name || '-'} {flow.role.rid ? `(${flow.role.rid})` : ''}
          </Descriptions.Item>
          <Descriptions.Item label="卡券">
            <StatusTag value={flow.ticket.status} />
          </Descriptions.Item>
          <Descriptions.Item label="发货">
            <StatusTag value={flow.dispatch.status} kind="delivery" />
          </Descriptions.Item>
          <Descriptions.Item label="核销">
            <StatusTag value={flow.consume.status} />
          </Descriptions.Item>
          <Descriptions.Item label="退号">
            <StatusTag value={flow.returnNumber.status} />
          </Descriptions.Item>
          <Descriptions.Item label="绑定链接" span={3}>
            {flow.binding.bindUrl ? (
              <Typography.Text copyable={{ text: flow.binding.bindUrl }}>
                {flow.binding.bindUrl}
              </Typography.Text>
            ) : (
              '-'
            )}
          </Descriptions.Item>
        </Descriptions>
      </Card>

      <Card title="流程检查">
        <div className="task-flow-grid">
          {checklist.map((item) => (
            <div key={item.key} className="task-flow-item">
              <Space>
                <StatusTag value={item.status} />
                <Typography.Text strong>{item.label}</Typography.Text>
              </Space>
              <Typography.Text type="secondary">{item.detail}</Typography.Text>
            </div>
          ))}
        </div>
      </Card>

      {roleInfoEntries.length > 0 ? (
        <Card title="角色原始字段">
          <Descriptions column={{ xs: 1, md: 2 }} bordered size="small">
            {roleInfoEntries.map(([key, value]) => (
              <Descriptions.Item key={key} label={formatKuaishouRoleInfoLabel(key)}>
                {typeof value === 'object' ? JSON.stringify(value) : String(value)}
              </Descriptions.Item>
            ))}
          </Descriptions>
        </Card>
      ) : null}

      {flow.rebind.history.length > 0 ? (
        <Card title="换绑记录">
          <Table
            rowKey={(row) => `${row.attempt}-${row.requestedAt || ''}`}
            pagination={false}
            dataSource={flow.rebind.history}
            scroll={{ x: 860 }}
            columns={[
              { title: '次数', dataIndex: 'attempt', width: 80 },
              {
                title: '时间',
                dataIndex: 'requestedAt',
                width: 180,
                render: (value) => formatAdminDateTime(value),
              },
              {
                title: '状态',
                dataIndex: 'status',
                width: 120,
                render: (value) => (
                  <Tag color={value === 'success' ? 'green' : value === 'failed' ? 'red' : 'blue'}>
                    {String(value || '-')}
                  </Tag>
                ),
              },
              {
                title: '旧角色',
                render: (_, row) =>
                  `${row.oldBinding.roleName || '-'} / ${row.oldBinding.roleId || '-'}`,
              },
              {
                title: '旧虚拟号',
                render: (_, row) =>
                  row.oldBinding.vnPhone || row.oldBinding.vnId || row.oldBinding.vnKey || '-',
              },
              {
                title: '异常',
                dataIndex: 'errorMessage',
                render: (value) => value || '-',
              },
            ]}
          />
        </Card>
      ) : null}
    </section>
  )
}

function RedeemResolutionPanel({
  resolution,
}: {
  resolution: NonNullable<AdminTaskDetail['redeemResolution']>
}) {
  return (
    <Card title="兑换重试链路">
      <Descriptions column={{ xs: 1, md: 2, xl: 4 }} bordered size="small">
        <Descriptions.Item label="处理结果">
          {formatRedeemResolutionStatus(resolution.status)}
        </Descriptions.Item>
        <Descriptions.Item label="任务状态">{resolution.taskStatus || '-'}</Descriptions.Item>
        <Descriptions.Item label="替换次数">{resolution.replacementCount}</Descriptions.Item>
        <Descriptions.Item label="完成时间">
          {formatAdminDateTime(resolution.finishedAt)}
        </Descriptions.Item>
      </Descriptions>

      <Table
        className="platform-section-gap"
        rowKey={(row) => `${row.attempt}-${row.codeMasked}`}
        pagination={false}
        dataSource={resolution.attempts}
        scroll={{ x: 760 }}
        columns={[
          { title: '次数', dataIndex: 'attempt', width: 80 },
          { title: '凭据', dataIndex: 'codeMasked', minWidth: 160 },
          { title: '类型', dataIndex: 'credentialType', minWidth: 120 },
          {
            title: '结果',
            dataIndex: 'outcome',
            minWidth: 160,
            render: (value) => formatRedeemOutcomeLabel(value),
          },
          { title: '代码', dataIndex: 'resultCode', minWidth: 120 },
          { title: '说明', dataIndex: 'resultMessage', minWidth: 220 },
        ]}
      />
    </Card>
  )
}

function ScreenshotPanel({ screenshotPreviewUrl }: { screenshotPreviewUrl: string }) {
  return (
    <Card title="任务截图">
      {screenshotPreviewUrl ? (
        <div className="task-screenshot-preview">
          <Image src={screenshotPreviewUrl} alt="任务截图" />
        </div>
      ) : (
        <Empty description="截图加载中或当前不可读取" />
      )}
    </Card>
  )
}

function BackButton() {
  const navigate = useNavigate()
  return (
    <Button icon={<ArrowLeftOutlined />} onClick={() => navigate('/admin/tasks')}>
      返回任务
    </Button>
  )
}
