import React, { useEffect, useState } from 'react';
import { useParams } from 'react-router-dom';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import {
  App,
  Card,
  Row,
  Col,
  Tag,
  Typography,
  Select,
  Space,
  Badge,
  Descriptions,
  Empty,
  Drawer,
  Button,
  Divider,
  Segmented,
  Checkbox,
  Alert,
  Collapse,
  Table,
  Input,
  InputNumber,
} from 'antd';
import {
  FileImageOutlined,
  CheckCircleOutlined,
  LoadingOutlined,
  CloseCircleOutlined,
  ZoomInOutlined,
  PlayCircleOutlined,
} from '@ant-design/icons';
import type { EvidenceImage, SourceApp, PageType } from '../../types';
import { fetchImageDetail, fetchImages, startCaseOcr } from '../../services/api';

const appLabel: Record<SourceApp, { label: string; color: string }> = {
  wechat: { label: '微信', color: 'green' },
  alipay: { label: '支付宝', color: 'blue' },
  bank: { label: '银行', color: 'purple' },
  digital_wallet: { label: '数字钱包', color: 'orange' },
  other: { label: '其他', color: 'default' },
};

const pageTypeLabel: Record<PageType, string> = {
  bill_list: '账单列表',
  bill_detail: '账单详情',
  transfer_receipt: '转账凭证',
  sms_notice: '短信通知',
  balance: '余额页',
  unknown: '页面类型未识别',
};

const ocrStatusMeta: Record<
  EvidenceImage['ocrStatus'],
  { badgeStatus: 'success' | 'processing' | 'error' | 'default'; text: string }
> = {
  done: { badgeStatus: 'success', text: 'OCR已完成' },
  processing: { badgeStatus: 'processing', text: 'OCR识别中' },
  pending: { badgeStatus: 'default', text: '待识别' },
  failed: { badgeStatus: 'error', text: '识别失败' },
};

const ocrStatusIcon: Record<string, React.ReactNode> = {
  done: <CheckCircleOutlined style={{ color: '#52c41a' }} />,
  processing: <LoadingOutlined style={{ color: '#1677ff' }} />,
  failed: <CloseCircleOutlined style={{ color: '#ff4d4f' }} />,
  pending: <FileImageOutlined style={{ color: '#d9d9d9' }} />,
};

type EditableTx = {
  id: string;
  blockId: string;
  data: Record<string, unknown>;
  jsonText: string;
  jsonError?: string;
};

const preferredFieldOrder = [
  'trade_time',
  'amount',
  'direction',
  'counterparty_name',
  'counterparty_account',
  'self_account_tail_no',
  'order_no',
  'remark',
  'confidence',
] as const;

const fieldLabelMap: Record<string, string> = {
  trade_time: '交易时间',
  amount: '金额',
  direction: '方向',
  counterparty_name: '对方名称',
  counterparty_account: '对方账号',
  self_account_tail_no: '本方尾号',
  order_no: '订单号',
  remark: '备注',
  confidence: '置信度',
  raw_content: '原始文本',
};

const tryParseJson = (text: string): unknown | null => {
  try {
    return JSON.parse(text);
  } catch {
    const match = text.match(/(\[[\s\S]*\]|\{[\s\S]*\})/);
    if (!match) return null;
    try {
      return JSON.parse(match[1]);
    } catch {
      return null;
    }
  }
};

const normalizeToObject = (value: unknown): Record<string, unknown> | null => {
  if (value && typeof value === 'object' && !Array.isArray(value)) {
    return value as Record<string, unknown>;
  }
  return null;
};

const buildEditableTransactions = (
  blocks: Array<{ id: string; content: string }>,
): EditableTx[] => {
  const items: EditableTx[] = [];
  blocks.forEach((block, blockIdx) => {
    const raw = (block.content || '').trim();
    const parsed = tryParseJson(raw);

    if (Array.isArray(parsed)) {
      parsed.forEach((entry, i) => {
        const obj = normalizeToObject(entry);
        if (!obj) return;
        items.push({
          id: `${block.id}-${i}`,
          blockId: block.id,
          data: obj,
          jsonText: JSON.stringify(obj, null, 2),
        });
      });
      return;
    }

    const obj = normalizeToObject(parsed);
    if (obj) {
      items.push({
        id: `${block.id}-0`,
        blockId: block.id,
        data: obj,
        jsonText: JSON.stringify(obj, null, 2),
      });
      return;
    }

    items.push({
      id: `${block.id}-${blockIdx}`,
      blockId: block.id,
      data: { raw_content: raw },
      jsonText: JSON.stringify({ raw_content: raw }, null, 2),
    });
  });
  return items;
};

const formatMoney = (v: unknown): string => {
  const n = Number(v);
  if (!Number.isFinite(n)) return '-';
  return n.toFixed(2);
};

const Screenshots: React.FC = () => {
  const { id = '1' } = useParams();
  const queryClient = useQueryClient();
  const { message } = App.useApp();
  const [filterApp, setFilterApp] = useState<string>('all');
  const [selectedImage, setSelectedImage] = useState<EvidenceImage | null>(null);
  const [drawerOpen, setDrawerOpen] = useState(false);
  const [selectedIds, setSelectedIds] = useState<string[]>([]);
  const [rerunTracking, setRerunTracking] = useState<Record<string, { sawProcessing: boolean }>>({});
  const [editableTxs, setEditableTxs] = useState<EditableTx[]>([]);

  const { data: allImages = [] } = useQuery({
    queryKey: ['images', id],
    queryFn: () => fetchImages(id),
    refetchInterval: Object.keys(rerunTracking).length > 0 ? 2000 : false,
  });
  const triggerOcrMutation = useMutation({
    mutationFn: (targetIds: string[]) =>
      startCaseOcr(
        id,
        targetIds.length > 0,
        targetIds.length > 0 ? targetIds : undefined,
      ),
    onMutate: (targetIds) => {
      message.open({
        key: 'screenshots-ocr',
        type: 'loading',
        content: targetIds.length > 0 ? `正在提交选中图片 OCR（${targetIds.length}）...` : '正在提交 OCR 任务...',
        duration: 0,
      });
      if (targetIds.length > 0) {
        setRerunTracking((prev) => {
          const next = { ...prev };
          targetIds.forEach((imageId) => {
            next[imageId] = { sawProcessing: false };
          });
          return next;
        });
      }
      return { targetIds };
    },
    onSuccess: (res) => {
      const isRerun = selectedIds.length > 0;
      if (isRerun) {
        setSelectedIds([]);
      }
      queryClient.invalidateQueries({ queryKey: ['images', id] });
      message.open({
        key: 'screenshots-ocr',
        type: 'success',
        content: res.message,
      });
    },
    onError: (_err, _vars, ctx) => {
      const rollbackIds = ctx?.targetIds || [];
      if (rollbackIds.length > 0) {
        setRerunTracking((prev) => {
          const next = { ...prev };
          rollbackIds.forEach((imageId) => {
            delete next[imageId];
          });
          return next;
        });
        message.open({
          key: 'screenshots-ocr',
          type: 'error',
          content: '选中图片 OCR 重跑提交失败',
        });
        return;
      }
      message.open({
        key: 'screenshots-ocr',
        type: 'error',
        content: 'OCR任务提交失败',
      });
    },
  });
  const { data: imageDetail } = useQuery({
    queryKey: ['image-detail', selectedImage?.id],
    queryFn: () => fetchImageDetail(selectedImage!.id),
    enabled: drawerOpen && !!selectedImage?.id,
  });

  const filtered =
    filterApp === 'all'
      ? allImages
      : allImages.filter((img: EvidenceImage) => img.sourceApp === filterApp);

  const appCounts = allImages.reduce<Record<string, number>>((acc, img: EvidenceImage) => {
    acc[img.sourceApp] = (acc[img.sourceApp] || 0) + 1;
    return acc;
  }, {});

  const handleSelect = (img: EvidenceImage) => {
    setSelectedImage(img);
    setDrawerOpen(true);
  };
  const resolveOcrStatus = (imageId: string, backendStatus: EvidenceImage['ocrStatus']): EvidenceImage['ocrStatus'] => {
    const tracking = rerunTracking[imageId];
    if (!tracking) return backendStatus;
    if (backendStatus === 'failed') return 'failed';
    if (backendStatus === 'done' && tracking.sawProcessing) return 'done';
    return 'processing';
  };
  React.useEffect(() => {
    if (Object.keys(rerunTracking).length === 0) return;
    const statusById = new Map(allImages.map((img) => [img.id, img.ocrStatus] as const));
    setRerunTracking((prev) => {
      let changed = false;
      const next: Record<string, { sawProcessing: boolean }> = { ...prev };
      Object.entries(prev).forEach(([imageId, tracking]) => {
        const status = statusById.get(imageId);
        if (!status) {
          delete next[imageId];
          changed = true;
          return;
        }
        if (status === 'processing' && !tracking.sawProcessing) {
          next[imageId] = { sawProcessing: true };
          changed = true;
          return;
        }
        if (status === 'failed' || (status === 'done' && tracking.sawProcessing)) {
          delete next[imageId];
          changed = true;
        }
      });
      return changed ? next : prev;
    });
  }, [allImages, rerunTracking]);
  const toggleChecked = (imageId: string, checked: boolean) => {
    setSelectedIds((prev) => (checked ? Array.from(new Set([...prev, imageId])) : prev.filter((id) => id !== imageId)));
  };
  const selectAllFiltered = () => {
    setSelectedIds(Array.from(new Set([...selectedIds, ...filtered.map((img) => img.id)])));
  };
  const clearSelection = () => setSelectedIds([]);
  const rawBlocks = imageDetail?.ocrBlocks || [];
  const visibleBlocks = rawBlocks.filter((b) => {
    const txt = (b.content || '').trim();
    return txt !== '' && txt !== '{}' && txt !== '[]';
  });
  const getEmptyReason = () => {
    const status = (imageDetail || selectedImage)?.ocrStatus;
    if (!status) return '';
    if (status === 'pending') return '该截图尚未开始 OCR 识别，请先触发识别。';
    if (status === 'processing') return 'OCR 正在进行中，稍后会自动刷新结果。';
    if (status === 'failed') return 'OCR 识别失败，请尝试重新识别或检查截图清晰度。';
    if (status === 'done' && rawBlocks.length === 0) {
      return 'OCR 已执行完成，但未提取到可用文本块。常见原因：截图内容非交易明细、清晰度不足或遮挡。';
    }
    if (status === 'done' && rawBlocks.length > 0 && visibleBlocks.length === 0) {
      return 'OCR 返回了空结构（如 {} / []），未形成可展示字段；可尝试重新识别或更换更清晰截图。';
    }
    return '';
  };
  useEffect(() => {
    if (!drawerOpen) return;
    setEditableTxs(buildEditableTransactions(visibleBlocks.map((b) => ({ id: b.id, content: b.content }))));
  }, [drawerOpen, selectedImage?.id, imageDetail?.id, imageDetail?.ocrBlocks]);

  const updateTxField = (txId: string, field: string, value: unknown) => {
    setEditableTxs((prev) =>
      prev.map((tx) => {
        if (tx.id !== txId) return tx;
        const nextData = { ...tx.data, [field]: value };
        return {
          ...tx,
          data: nextData,
          jsonText: JSON.stringify(nextData, null, 2),
          jsonError: undefined,
        };
      }),
    );
  };

  const updateTxJson = (txId: string, text: string) => {
    setEditableTxs((prev) =>
      prev.map((tx) => {
        if (tx.id !== txId) return tx;
        try {
          const parsed = JSON.parse(text);
          if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
            return { ...tx, jsonText: text, jsonError: 'JSON 顶层必须是对象' };
          }
          return {
            ...tx,
            jsonText: text,
            jsonError: undefined,
            data: parsed as Record<string, unknown>,
          };
        } catch {
          return { ...tx, jsonText: text, jsonError: 'JSON 格式错误' };
        }
      }),
    );
  };

  const getTxSummary = (tx: EditableTx, index: number) => {
    const tradeTime = String(tx.data.trade_time ?? tx.data.tradeTime ?? '-');
    const amount = tx.data.amount;
    return `#${index + 1}  时间：${tradeTime}  金额：${formatMoney(amount)}`;
  };

  const buildFieldRows = (tx: EditableTx) => {
    const keys = Object.keys(tx.data);
    const ordered = [
      ...preferredFieldOrder.filter((k) => keys.includes(k)),
      ...keys.filter((k) => !preferredFieldOrder.includes(k as (typeof preferredFieldOrder)[number])),
    ];
    return ordered.map((key) => ({
      key,
      label: fieldLabelMap[key] || key,
      value: tx.data[key],
    }));
  };

  return (
    <div>
      <Card
        title={
          <Space>
            <FileImageOutlined />
            <span>截图管理</span>
            <Tag>{allImages.length} 张</Tag>
          </Space>
        }
        extra={
          <Space>
            <Button
              type="primary"
              icon={<PlayCircleOutlined />}
              loading={triggerOcrMutation.isPending}
              disabled={selectedIds.length === 0}
              onClick={() => triggerOcrMutation.mutate(selectedIds)}
            >
              {selectedIds.length > 0 ? `对选中图片重新OCR（${selectedIds.length}）` : '开始 OCR 识别'}
            </Button>
            <Button onClick={selectAllFiltered}>全选当前筛选</Button>
            <Button onClick={clearSelection} disabled={selectedIds.length === 0}>清空选择</Button>
            {selectedIds.length > 0 && <Tag color="blue">已选 {selectedIds.length} 张</Tag>}
            <Select
              value={filterApp}
              onChange={setFilterApp}
              style={{ width: 140 }}
              options={[
                { label: '全部来源', value: 'all' },
                ...Object.entries(appLabel).map(([k, v]) => ({
                  label: `${v.label} (${appCounts[k] || 0})`,
                  value: k,
                })),
              ]}
            />
            <Segmented
              options={[
                { label: '网格', value: 'grid' },
                { label: '列表', value: 'list' },
              ]}
              defaultValue="grid"
            />
          </Space>
        }
      >
        <Row gutter={[16, 16]}>
          {filtered.map((img) => {
            const viewStatus = resolveOcrStatus(img.id, img.ocrStatus);
            return (
              <Col key={img.id} xs={12} sm={8} md={6} lg={4}>
              <Card
                hoverable
                onClick={() => handleSelect(img)}
                styles={{
                  body: { padding: 12 },
                }}
                cover={
                  <div
                    style={{
                      height: 200,
                      background: '#f5f5f5',
                      display: 'flex',
                      flexDirection: 'column',
                      alignItems: 'center',
                      justifyContent: 'center',
                      position: 'relative',
                      overflow: 'hidden',
                    }}
                  >
                    {(img.thumbUrl || img.url) ? (
                      <img
                        src={img.thumbUrl || img.url}
                        alt="截图缩略图"
                        style={{ width: '100%', height: '100%', objectFit: 'cover' }}
                      />
                    ) : (
                      <>
                        <FileImageOutlined
                          style={{ fontSize: 40, color: '#bfbfbf' }}
                        />
                        <Typography.Text
                          type="secondary"
                          style={{ fontSize: 12, marginTop: 8 }}
                        >
                          截图预览区
                        </Typography.Text>
                      </>
                    )}
                    <div
                      style={{
                        position: 'absolute',
                        top: 8,
                        right: 8,
                      }}
                    >
                      {ocrStatusIcon[viewStatus]}
                    </div>
                    <div
                      style={{
                        position: 'absolute',
                        top: 8,
                        left: 8,
                      }}
                      onClick={(e) => e.stopPropagation()}
                    >
                      <Checkbox
                        checked={selectedIds.includes(img.id)}
                        onChange={(e) => toggleChecked(img.id, e.target.checked)}
                        style={{ marginRight: 6 }}
                      />
                      <Tag
                        color={appLabel[img.sourceApp].color}
                        style={{ fontSize: 11 }}
                      >
                        {appLabel[img.sourceApp].label}
                      </Tag>
                    </div>
                  </div>
                }
              >
                <Typography.Text ellipsis style={{ fontSize: 13 }}>
                  {pageTypeLabel[img.pageType]}
                </Typography.Text>
                <br />
                <Typography.Text type="secondary" style={{ fontSize: 12 }}>
                  {ocrStatusMeta[viewStatus].text}
                </Typography.Text>
                <br />
                <Typography.Text type="secondary" style={{ fontSize: 11 }}>
                  {img.uploadedAt}
                </Typography.Text>
              </Card>
            </Col>
            );
          })}
        </Row>

        {filtered.length === 0 && <Empty description="暂无截图" />}
      </Card>

      <Drawer
        title={
          selectedImage ? (
            <Space>
              <Tag color={appLabel[selectedImage.sourceApp].color}>
                {appLabel[selectedImage.sourceApp].label}
              </Tag>
              <span>{pageTypeLabel[selectedImage.pageType]}</span>
              <Badge
                status={ocrStatusMeta[
                  resolveOcrStatus(selectedImage.id, (imageDetail || selectedImage).ocrStatus)
                ].badgeStatus}
                text={ocrStatusMeta[
                  resolveOcrStatus(selectedImage.id, (imageDetail || selectedImage).ocrStatus)
                ].text}
              />
            </Space>
          ) : '截图详情'
        }
        placement="right"
        width={560}
        open={drawerOpen}
        onClose={() => setDrawerOpen(false)}
      >
        {selectedImage && (
          <>
            <div
              style={{
                background: '#fafafa',
                borderRadius: 8,
                height: 300,
                display: 'flex',
                alignItems: 'center',
                justifyContent: 'center',
                marginBottom: 24,
                border: '1px dashed #d9d9d9',
                overflow: 'hidden',
              }}
            >
              {(imageDetail?.url || selectedImage.url) ? (
                <img
                  src={imageDetail?.url || selectedImage.url}
                  alt="原始截图"
                  style={{ width: '100%', height: '100%', objectFit: 'contain' }}
                />
              ) : (
                <Space direction="vertical" align="center">
                  <FileImageOutlined style={{ fontSize: 64, color: '#bfbfbf' }} />
                  <Typography.Text type="secondary">
                    原始截图预览
                  </Typography.Text>
                  <Button icon={<ZoomInOutlined />} size="small">
                    放大查看
                  </Button>
                </Space>
              )}
            </div>

            <Typography.Title level={5}>OCR 提取字段</Typography.Title>
            <Typography.Text type="secondary" style={{ marginBottom: 16, display: 'block' }}>
              以下为 OCR 文本块（实时读取后端识别结果）
            </Typography.Text>
            {visibleBlocks.length === 0 && (
              <Alert
                type="info"
                showIcon
                style={{ marginBottom: 12 }}
                message="暂无 OCR 提取结果"
                description={getEmptyReason()}
              />
            )}
            {editableTxs.length > 0 && (
              <Collapse
                size="small"
                items={editableTxs.map((tx, idx) => ({
                  key: tx.id,
                  label: (
                    <Space>
                      <Typography.Text strong>{getTxSummary(tx, idx)}</Typography.Text>
                      <Tag color="blue">来源块 {idx + 1}</Tag>
                    </Space>
                  ),
                  children: (
                    <Space direction="vertical" style={{ width: '100%' }} size={12}>
                      <Table
                        size="small"
                        pagination={false}
                        rowKey="key"
                        dataSource={buildFieldRows(tx)}
                        columns={[
                          {
                            title: '字段',
                            dataIndex: 'label',
                            key: 'label',
                            width: 160,
                          },
                          {
                            title: '值',
                            key: 'value',
                            render: (_, row: { key: string; value: unknown }) => {
                              if (row.key === 'direction') {
                                return (
                                  <Select
                                    style={{ width: 140 }}
                                    value={String(row.value ?? 'out')}
                                    options={[
                                      { label: '转入(in)', value: 'in' },
                                      { label: '转出(out)', value: 'out' },
                                    ]}
                                    onChange={(val) => updateTxField(tx.id, row.key, val)}
                                  />
                                );
                              }
                              if (row.key === 'amount' || row.key === 'confidence') {
                                const numVal = Number(row.value);
                                return (
                                  <InputNumber
                                    style={{ width: '100%' }}
                                    value={Number.isFinite(numVal) ? numVal : undefined}
                                    onChange={(val) => updateTxField(tx.id, row.key, val ?? 0)}
                                  />
                                );
                              }
                              return (
                                <Input
                                  value={String(row.value ?? '')}
                                  onChange={(e) => updateTxField(tx.id, row.key, e.target.value)}
                                />
                              );
                            },
                          },
                        ]}
                      />
                      <div>
                        <Typography.Text type="secondary">JSON（可编辑）</Typography.Text>
                        <Input.TextArea
                          value={tx.jsonText}
                          rows={8}
                          onChange={(e) => updateTxJson(tx.id, e.target.value)}
                          style={{ marginTop: 8, fontFamily: 'monospace' }}
                        />
                        {tx.jsonError && (
                          <Typography.Text type="danger">{tx.jsonError}</Typography.Text>
                        )}
                      </div>
                    </Space>
                  ),
                }))}
              />
            )}

            <Divider />

            <Descriptions column={1} size="small">
              <Descriptions.Item label="图片ID">
                {selectedImage.id}
              </Descriptions.Item>
              <Descriptions.Item label="文件哈希">
                {selectedImage.fileHash}
              </Descriptions.Item>
              <Descriptions.Item label="上传时间">
                {selectedImage.uploadedAt}
              </Descriptions.Item>
            </Descriptions>
          </>
        )}
      </Drawer>
    </div>
  );
};

export default Screenshots;
