import {
  DownloadOutlined,
  FileImageOutlined,
  ReloadOutlined,
  SearchOutlined,
} from '@ant-design/icons'
import {
  Alert,
  Button,
  Card,
  Image as AntdImage,
  Input,
  Modal,
  Select,
  Space,
  Table,
  Tag,
  Typography,
} from 'antd'
import type { TableColumnsType } from 'antd'
import { useEffect, useMemo, useState } from 'react'

import { AdminRangePicker } from '@/components/admin/AdminDatePicker'
import PageHeader from '@/components/admin/PageHeader'
import dayjs, { type Dayjs } from '@/lib/dayjs'
import { showError, showSuccess } from '@/lib/feedback'
import {
  fetchAdminCloudtentaclesDeliveryRecords,
  fetchAdminCloudtentaclesRecordSources,
} from '@/services/admin'
import type { AdminCloudtentaclesDeliveryRecordItem } from '@/types/admin'
import { getAdminToken } from '@/utils/admin-auth'
import {
  buildCloudtentaclesTablePagination,
  CLOUDTENTACLES_DEFAULT_PAGE_SIZE,
} from '@/utils/admin-pagination'
import { formatAdminDateTime } from '@/utils/admin-time'

type RecordSourceOption = {
  key: string
  label: string
  enabled: boolean
  hasToken: boolean
  loggedInAt: string
}

type DateRangeValue = [Dayjs | null, Dayjs | null] | null

export default function AdminCloudtentaclesRecordsPage() {
  const [loading, setLoading] = useState(false)
  const [sourceLoading, setSourceLoading] = useState(false)
  const [errorMessage, setErrorMessage] = useState('')
  const [sourceKey, setSourceKey] = useState('')
  const [platformOrderId, setPlatformOrderId] = useState('')
  const [dateRange, setDateRange] = useState<DateRangeValue>(createDefaultDateRange())
  const [page, setPage] = useState(1)
  const [pageSize, setPageSize] = useState(CLOUDTENTACLES_DEFAULT_PAGE_SIZE)
  const [total, setTotal] = useState(0)
  const [items, setItems] = useState<AdminCloudtentaclesDeliveryRecordItem[]>([])
  const [sourceOptions, setSourceOptions] = useState<RecordSourceOption[]>([])
  const [previewVisible, setPreviewVisible] = useState(false)
  const [previewImageUrl, setPreviewImageUrl] = useState('')
  const [previewFileName, setPreviewFileName] = useState('')

  const currentSourceLabel = useMemo(() => {
    const matched = sourceOptions.find((source) => source.key === sourceKey)
    return matched?.label || sourceKey || '-'
  }, [sourceKey, sourceOptions])

  const columns: TableColumnsType<AdminCloudtentaclesDeliveryRecordItem> = [
    {
      title: '商品 / 角色',
      minWidth: 260,
      render: (_, row) => (
        <div className="cell-stack">
          <Typography.Text strong ellipsis={{ tooltip: row.name || '-' }}>
            {row.name || '-'}
          </Typography.Text>
          <span className="muted">账号：{row.fulfillUser || '-'}</span>
          {row.roleName || row.roleId ? (
            <span className="muted">
              角色：{row.roleName || '-'}
              {row.roleId ? `（${row.roleId}）` : ''}
            </span>
          ) : null}
        </div>
      ),
    },
    {
      title: '订单 / 店铺',
      minWidth: 260,
      render: (_, row) => (
        <div className="cell-stack">
          <Typography.Text strong ellipsis={{ tooltip: row.platformOrderId || '-' }}>
            {row.platformOrderId || '-'}
          </Typography.Text>
          <span className="muted">订单店铺：{row.orderShopName || row.orderShopId || '-'}</span>
          <span className="muted">核销店铺：{row.consumeShopName || row.consumeShopId || '-'}</span>
        </div>
      ),
    },
    {
      title: '虚拟号',
      minWidth: 160,
      render: (_, row) => (
        <div className="cell-stack">
          <span>{row.phone || '-'}</span>
          <span className="muted">VN {row.virtualNumberId || '-'}</span>
        </div>
      ),
    },
    {
      title: '状态',
      width: 140,
      render: (_, row) => (
        <div className="status-stack">
          <Tag color={getStatusColor(row.status)}>{getStatusLabel(row.status)}</Tag>
          {row.localDispatchStatus ? (
            <span className="muted">{getLocalDispatchStatusLabel(row.localDispatchStatus)}</span>
          ) : null}
        </div>
      ),
    },
    {
      title: '操作人',
      minWidth: 120,
      render: (_, row) => row.operatorName || '-',
    },
    {
      title: '发货时间',
      minWidth: 170,
      render: (_, row) => formatAdminDateTime(row.createdAt),
    },
    {
      title: '记录 ID',
      minWidth: 230,
      render: (_, row) => (
        <div className="cell-stack">
          <Typography.Text type="secondary" ellipsis={{ tooltip: row.recordId || '-' }}>
            {row.recordId || '-'}
          </Typography.Text>
          {row.taskNo ? (
            <span className="muted">
              任务：{row.taskNo}
              {getMatchConfidenceLabel(row.matchConfidence)
                ? ` · 匹配${getMatchConfidenceLabel(row.matchConfidence)}`
                : ''}
            </span>
          ) : null}
        </div>
      ),
    },
    {
      title: '操作',
      fixed: 'right',
      width: 136,
      render: (_, row) => (
        <Button
          size="small"
          type="primary"
          ghost
          icon={<FileImageOutlined />}
          onClick={() => generateRecordImage(row)}
        >
          生成图片
        </Button>
      ),
    },
  ]

  useEffect(() => {
    void bootstrap()
  }, [])

  async function bootstrap() {
    const nextSourceKey = await loadSources()
    if (nextSourceKey) {
      await loadRecords(1, { sourceKey: nextSourceKey })
    }
  }

  async function loadSources() {
    setSourceLoading(true)

    try {
      const response = await fetchAdminCloudtentaclesRecordSources()
      const nextSources = response.data.sources || []
      const usableSources = nextSources.filter((source) => source.enabled && source.hasToken)
      const nextSourceKey = sourceKey || usableSources[0]?.key || nextSources[0]?.key || ''
      setSourceOptions(nextSources)
      setSourceKey(nextSourceKey)
      return nextSourceKey
    } catch (error) {
      setErrorMessage(error instanceof Error ? error.message : '读取 kuaishou-lewan 账号失败')
      return ''
    } finally {
      setSourceLoading(false)
    }
  }

  async function loadRecords(
    nextPage = page,
    options: {
      sourceKey?: string
      pageSize?: number
      platformOrderId?: string
      dateRange?: DateRangeValue
    } = {},
  ) {
    const nextSourceKey = options.sourceKey ?? sourceKey
    const nextPageSize = options.pageSize ?? pageSize
    const nextDateRange = options.dateRange ?? dateRange
    const orderKeyword = (options.platformOrderId ?? platformOrderId).trim()

    if (!nextSourceKey && !orderKeyword) {
      showError('请先选择 kuaishou-lewan 账号')
      return
    }

    const [startDate, endDate] = nextDateRange || []
    if (!startDate || !endDate) {
      showError('请选择查询时间范围')
      return
    }

    setLoading(true)
    setErrorMessage('')

    try {
      const response = await fetchAdminCloudtentaclesDeliveryRecords({
        sourceKey: nextSourceKey || undefined,
        page: nextPage,
        size: nextPageSize,
        startDate: formatQueryDateTime(startDate),
        endDate: formatQueryDateTime(endDate),
        platformOrderId: orderKeyword || undefined,
      })

      if (response.data.sourceKey && response.data.sourceKey !== sourceKey) {
        setSourceKey(response.data.sourceKey)
      }

      setPage(response.data.page)
      setPageSize(response.data.size)
      setTotal(response.data.total)
      setItems(response.data.items || [])
    } catch (error) {
      setErrorMessage(error instanceof Error ? error.message : '查询发货记录失败')
    } finally {
      setLoading(false)
    }
  }

  function resetFilters() {
    const nextDateRange = createDefaultDateRange()
    setPlatformOrderId('')
    setDateRange(nextDateRange)
    setPage(1)
    setPageSize(CLOUDTENTACLES_DEFAULT_PAGE_SIZE)
    void loadRecords(1, {
      pageSize: CLOUDTENTACLES_DEFAULT_PAGE_SIZE,
      platformOrderId: '',
      dateRange: nextDateRange,
    })
  }

  async function generateRecordImage(record: AdminCloudtentaclesDeliveryRecordItem) {
    try {
      const dataUrl = await drawRecordImage(record)
      setPreviewImageUrl(dataUrl)
      setPreviewFileName(buildRecordImageFileName(record))
      setPreviewVisible(true)
    } catch (error) {
      showError(error instanceof Error ? error.message : '生成发货记录图片失败')
    }
  }

  function downloadPreviewImage() {
    if (!previewImageUrl) {
      return
    }

    const link = document.createElement('a')
    link.href = previewImageUrl
    link.download = previewFileName || 'cloudtentacles-delivery-record.png'
    link.click()
    showSuccess('发货记录图片已生成')
  }

  return (
    <section className="page-stack">
      <PageHeader
        title="查询发货记录"
        description="按订单号、kuaishou-lewan 账号和时间范围查询平台发货记录。"
        extra={<span className="total-badge">共 {total} 条记录</span>}
      />

      <Card
        title="查询条件"
        extra={
          <Typography.Text type="secondary">
            输入订单号时会先关联本地任务，再匹配 kuaishou-lewan 发货记录。
          </Typography.Text>
        }
      >
        <div className="cloud-records-filter">
          <Select
            value={sourceKey || undefined}
            loading={sourceLoading}
            placeholder="kuaishou-lewan 账号"
            options={sourceOptions.map((source) => ({
              label: `${source.label || source.key}${source.hasToken ? '' : ' · 未登录'}`,
              value: source.key,
              disabled: !source.enabled || !source.hasToken,
            }))}
            onChange={setSourceKey}
          />
          <Input
            allowClear
            value={platformOrderId}
            placeholder="订单号"
            onChange={(event) => setPlatformOrderId(event.target.value)}
            onPressEnter={() => loadRecords(1)}
          />
          <AdminRangePicker
            showTime
            value={dateRange}
            className="full-width"
            onChange={(value) => setDateRange(value)}
          />
          <Space>
            <Button icon={<ReloadOutlined />} onClick={resetFilters}>
              重置
            </Button>
            <Button
              type="primary"
              icon={<SearchOutlined />}
              loading={loading}
              onClick={() => loadRecords(1)}
            >
              查询
            </Button>
          </Space>
        </div>
      </Card>

      {errorMessage ? <Alert type="error" showIcon message={errorMessage} /> : null}

      <Card>
        <div className="table-toolbar">
          <strong>发货记录</strong>
          <span>
            账号 {currentSourceLabel} · 第 {page} 页，当前展示 {items.length} 条
          </span>
        </div>

        <Table<AdminCloudtentaclesDeliveryRecordItem>
          rowKey={(row) => row.recordId || `${row.virtualNumberId}-${row.createdAt}`}
          loading={loading}
          columns={columns}
          dataSource={items}
          size="small"
          scroll={{ x: 1450 }}
          pagination={buildCloudtentaclesTablePagination({
            current: page,
            pageSize,
            total,
            onChange: (nextPage, nextPageSize) => {
              void loadRecords(nextPage, { pageSize: nextPageSize })
            },
          })}
          locale={{ emptyText: loading ? '发货记录加载中' : '当前筛选条件下暂无发货记录' }}
        />
      </Card>

      <Modal
        title="发货记录图片"
        open={previewVisible}
        width={780}
        destroyOnHidden
        onCancel={() => setPreviewVisible(false)}
        footer={[
          <Button key="close" onClick={() => setPreviewVisible(false)}>
            关闭
          </Button>,
          <Button
            key="download"
            type="primary"
            icon={<DownloadOutlined />}
            onClick={downloadPreviewImage}
          >
            下载图片
          </Button>,
        ]}
      >
        <div className="record-preview">
          {previewImageUrl ? (
            <AntdImage src={previewImageUrl} alt="发货记录图片预览" preview={false} />
          ) : null}
        </div>
      </Modal>
    </section>
  )
}

function getStatusLabel(status: number) {
  if (status === 4) return '已完成'
  if (status === 1) return '处理中'
  if (status === 2) return '待处理'
  if (status === 3) return '失败'
  return `状态 ${status || '-'}`
}

function getStatusColor(status: number) {
  if (status === 4) return 'green'
  if (status === 3) return 'red'
  if (status === 1) return 'orange'
  return 'blue'
}

function getLocalDispatchStatusLabel(status: string) {
  const normalized = String(status || '').trim()
  if (normalized === 'success') return '本地已发货'
  if (normalized === 'failed') return '本地发货失败'
  if (normalized === 'pending') return '本地待发货'
  return normalized || '-'
}

function getMatchConfidenceLabel(value: string) {
  if (value === 'high') return '高'
  if (value === 'medium') return '中'
  if (value === 'low') return '低'
  if (value === 'local') return '本地'
  return ''
}

function createDefaultDateRange(): DateRangeValue {
  const end = dayjs()
  return [end.subtract(7, 'day').startOf('day'), end]
}

function formatQueryDateTime(value: Dayjs) {
  return value.format('YYYY-MM-DD HH:mm:ss')
}

async function drawRecordImage(record: AdminCloudtentaclesDeliveryRecordItem) {
  const productImage = await loadRecordProductImage(record.skuImage)
  const canvas = document.createElement('canvas')
  const scale = window.devicePixelRatio || 1
  const width = 720
  const height = 330
  canvas.width = width * scale
  canvas.height = height * scale
  canvas.style.width = `${width}px`
  canvas.style.height = `${height}px`

  const ctx = canvas.getContext('2d')
  if (!ctx) {
    throw new Error('当前浏览器不支持图片生成')
  }

  ctx.scale(scale, scale)
  ctx.fillStyle = '#ffffff'
  ctx.fillRect(0, 0, width, height)
  ctx.fillStyle = '#1f2937'
  ctx.font = '20px sans-serif'
  ctx.fillText('订单详情', 28, 38)
  ctx.fillStyle = '#9ca3af'
  ctx.font = '24px sans-serif'
  ctx.fillText('x', width - 40, 38)

  ctx.fillStyle = '#111827'
  ctx.font = '13px sans-serif'
  ctx.textAlign = 'center'
  ctx.fillText(`购买时间：${formatAdminDateTime(record.createdAt)}`, width / 2, 88)
  ctx.textAlign = 'left'

  drawTicketCard(ctx, record, productImage)
  drawRecordMeta(ctx, record)
  return canvas.toDataURL('image/png')
}

function drawTicketCard(
  ctx: CanvasRenderingContext2D,
  record: AdminCloudtentaclesDeliveryRecordItem,
  productImage: HTMLImageElement | null,
) {
  const x = 170
  const y = 108
  const width = 392
  const height = 108
  const imageWidth = 106

  ctx.save()
  ctx.beginPath()
  ctx.moveTo(x + 18, y)
  ctx.lineTo(x + width, y)
  ctx.lineTo(x + width, y + height - 22)
  ctx.lineTo(x + width - 18, y + height)
  ctx.lineTo(x, y + height)
  ctx.lineTo(x, y + 18)
  ctx.closePath()
  ctx.fillStyle = '#f8fbff'
  ctx.fill()
  ctx.strokeStyle = '#2f80d1'
  ctx.lineWidth = 1
  ctx.stroke()
  ctx.restore()

  const gradient = ctx.createLinearGradient(x, y, x + imageWidth, y + height)
  gradient.addColorStop(0, '#e7f1ff')
  gradient.addColorStop(1, '#b8d7ff')
  ctx.fillStyle = gradient
  ctx.fillRect(x, y, imageWidth, height)

  if (productImage) {
    drawCoverImage(ctx, productImage, x, y, imageWidth, height)
  } else {
    ctx.fillStyle = '#355d91'
    ctx.font = '12px sans-serif'
    ctx.textAlign = 'center'
    ctx.fillText('套装发货记录', x + imageWidth / 2, y + 25)
    ctx.fillStyle = '#ffffff'
    ctx.fillRect(x + 34, y + 42, 38, 38)
    ctx.strokeStyle = '#8ab6ef'
    ctx.strokeRect(x + 34, y + 42, 38, 38)
    ctx.fillStyle = '#2f80d1'
    ctx.font = '20px sans-serif'
    ctx.fillText('GP', x + imageWidth / 2, y + 69)
  }
  ctx.textAlign = 'left'

  const contentX = x + imageWidth + 16
  const orderText = `订单号：${record.platformOrderId || record.recordId.slice(-8) || '-'}`
  ctx.fillStyle = '#1d5ea8'
  ctx.font = '16px sans-serif'
  drawEllipsisText(ctx, record.name || '未命名商品', contentX, y + 31, 170)
  ctx.fillStyle = '#3478c6'
  ctx.font = '13px sans-serif'
  ctx.textAlign = 'right'
  ctx.fillText(orderText, x + width - 12, y + 30)
  ctx.textAlign = 'left'

  ctx.strokeStyle = '#c8d8ec'
  ctx.beginPath()
  ctx.moveTo(contentX, y + 42)
  ctx.lineTo(x + width - 12, y + 42)
  ctx.stroke()

  ctx.fillStyle = '#f59e0b'
  ctx.font = '14px sans-serif'
  ctx.fillText(`购买机会 x ${record.count || 1}`, contentX, y + 66)
  ctx.fillStyle = '#16a34a'
  ctx.textAlign = 'right'
  ctx.fillText(getStatusLabel(record.status), x + width - 12, y + 66)
  ctx.textAlign = 'left'

  ctx.fillStyle = '#3478c6'
  ctx.font = '14px sans-serif'
  drawEllipsisText(ctx, `账号：${record.fulfillUser || record.phone || '-'}`, contentX, y + 90, 250)
}

function drawRecordMeta(
  ctx: CanvasRenderingContext2D,
  record: AdminCloudtentaclesDeliveryRecordItem,
) {
  const left = 80
  const top = 250
  const lineHeight = 22
  const values = [
    `订单店铺：${record.orderShopName || record.orderShopId || '-'}`,
    `核销店铺：${record.consumeShopName || record.consumeShopId || '-'}`,
    `绑定角色：${record.roleName || record.fulfillUser || '-'}${record.roleId ? `（${record.roleId}）` : ''}`,
  ]

  ctx.fillStyle = '#374151'
  ctx.font = '13px sans-serif'
  values.forEach((value, index) => {
    drawEllipsisText(ctx, value, left, top + index * lineHeight, 560)
  })
}

async function loadRecordProductImage(imageUrl: string) {
  const normalizedUrl = String(imageUrl || '').trim()
  if (!normalizedUrl) {
    return null
  }

  const proxyUrl = `/api/v1/admin/cloudtentacles-records/image?url=${encodeURIComponent(
    normalizedUrl,
  )}`
  return loadProtectedImage(proxyUrl).catch(() => null)
}

async function loadProtectedImage(src: string) {
  const token = getAdminToken()
  const response = await fetch(src, {
    headers: token ? { Authorization: `Bearer ${token}` } : {},
  })

  if (!response.ok) {
    throw new Error('商品图片加载失败')
  }

  const objectUrl = URL.createObjectURL(await response.blob())
  try {
    return await loadImage(objectUrl)
  } finally {
    URL.revokeObjectURL(objectUrl)
  }
}

function loadImage(src: string) {
  return new Promise<HTMLImageElement>((resolve, reject) => {
    const image = new Image()
    image.onload = () => resolve(image)
    image.onerror = () => reject(new Error('商品图片加载失败'))
    image.src = src
  })
}

function drawCoverImage(
  ctx: CanvasRenderingContext2D,
  image: HTMLImageElement,
  x: number,
  y: number,
  width: number,
  height: number,
) {
  const ratio = Math.max(width / image.naturalWidth, height / image.naturalHeight)
  const drawWidth = image.naturalWidth * ratio
  const drawHeight = image.naturalHeight * ratio
  const drawX = x + (width - drawWidth) / 2
  const drawY = y + (height - drawHeight) / 2

  ctx.save()
  ctx.beginPath()
  ctx.rect(x, y, width, height)
  ctx.clip()
  ctx.drawImage(image, drawX, drawY, drawWidth, drawHeight)
  ctx.restore()
}

function drawEllipsisText(
  ctx: CanvasRenderingContext2D,
  text: string,
  x: number,
  y: number,
  maxWidth: number,
) {
  let output = text
  while (output.length > 0 && ctx.measureText(output).width > maxWidth) {
    output = `${output.slice(0, -2)}...`
  }
  ctx.fillText(output || '-', x, y)
}

function buildRecordImageFileName(record: AdminCloudtentaclesDeliveryRecordItem) {
  const name = sanitizeFileName(record.name || '发货记录')
  const id = sanitizeFileName(
    record.platformOrderId ||
      record.recordId.slice(0, 8) ||
      String(record.virtualNumberId || 'record'),
  )
  return `${name}-${id}.png`
}

function sanitizeFileName(value: string) {
  return value.replace(/[\\/:*?"<>|]/g, '_').slice(0, 48)
}
