import { useEffect, useMemo, useState } from 'react'
import { useSearchParams } from 'react-router-dom'
import {
  Alert, Button, Card, Col, Collapse, Descriptions, Empty, Row, Segmented,
  Select, Space, Spin, Statistic, Table, Tag, Tooltip, Badge, message,
} from 'antd'
import {
  CheckCircleOutlined, CloseCircleOutlined, ClearOutlined,
  DownloadOutlined, UserOutlined, RobotOutlined, ReloadOutlined,
  DiffOutlined, FileMarkdownOutlined,
} from '@ant-design/icons'
import { reportsApi, runsApi, type Run } from '../api'
import PageWrapper from '../components/PageWrapper'
import { colors, triggerColors, triggerLabels } from '../tokens'
import { formatDateTime } from '../utils/date'
import { useResource } from '../hooks/useResource'

interface TurnData {
  sent_text: string
  reply_text: string | null
  latency_ms: number | null
}

interface RuleResultData {
  rule_type: string
  passed: boolean
  score: number | null
  reason: string
}

interface CaseReport {
  case_id: string
  connectivity: boolean
  turns: TurnData[]
  results: RuleResultData[]
}

interface Report {
  run_id: string
  target_name: string
  scenario_name: string
  scenario_version?: number
  triggered_by?: string
  status: string
  started_at: string
  completed_at: string | null
  summary: {
    total_cases: number
    passed_cases: number
    failed_cases: number
    total_rules: number
    passed_rules: number
    pass_rate: number
    connectivity_cases: number
    judged_pass_rate: number | null
  }
  cases: CaseReport[]
}

interface CompareResult {
  run_a: { run_id: string; target_name: string; scenario_name: string; scenario_version?: number; triggered_by?: string; status: string; started_at: string; summary: Report['summary'] }
  run_b: { run_id: string; target_name: string; scenario_name: string; scenario_version?: number; triggered_by?: string; status: string; started_at: string; summary: Report['summary'] }
  delta: { pass_rate: number; passed_cases: number; passed_rules: number }
  cases: Array<{
    case_id: string
    connectivity: boolean
    run_a_passed: boolean | null
    run_b_passed: boolean | null
    changed: boolean
    run_a_results: RuleResultData[]
    run_b_results: RuleResultData[]
  }>
  changed_cases: number
}

type ViewMode = 'single' | 'compare'

export default function ReportsPage() {
  const [searchParams, setSearchParams] = useSearchParams()
  const runQuery = searchParams.get('run') ?? ''

  const [scenarioFilter, setScenarioFilter] = useState<string>('')
  const [selectedRunId, setSelectedRunId] = useState<string>('')
  const [compareRunId, setCompareRunId] = useState<string>('')
  const [report, setReport] = useState<Report | null>(null)
  const [compareResult, setCompareResult] = useState<CompareResult | null>(null)
  const [loading, setLoading] = useState(false)
  const [viewMode, setViewMode] = useState<ViewMode>('single')

  // Keep-alive tabs never remount: refresh whenever this tab is re-activated
  // so runs triggered elsewhere (e.g. AI assistant) show up.
  const { data: runsData, reload: reloadRuns } = useResource(
    () => runsApi.list().then((r) => r.data.filter((run) => run.status === 'completed')),
    { tabPath: '/reports' },
  )
  const runs = useMemo(() => runsData ?? [], [runsData])

  const loadReport = async (runId: string) => {
    setSelectedRunId(runId)
    setCompareResult(null)
    setLoading(true)
    try {
      const res = await reportsApi.get(runId)
      setReport(res.data as Report)
    } finally {
      setLoading(false)
    }
  }

  useEffect(() => {
    if (runQuery && runQuery !== selectedRunId) {
      loadReport(runQuery)
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [runQuery])

  const handleView = (runId: string) => {
    setSearchParams({ run: runId })
    loadReport(runId)
    // 对比报告要求同场景同版本：A 变更后若 B 不可比则清空
    const a = runs.find((r) => r.id === runId)
    const b = runs.find((r) => r.id === compareRunId)
    if (a && b && (a.scenario_id !== b.scenario_id
      || (a.scenario_version ?? 1) !== (b.scenario_version ?? 1))) setCompareRunId('')
  }

  const handleCompare = async () => {
    if (!selectedRunId || !compareRunId) return
    setLoading(true)
    try {
      const res = await reportsApi.compare(selectedRunId, compareRunId)
      setCompareResult(res.data as CompareResult)
    } catch (e: any) {
      const detail = e?.response?.data?.detail
      if (detail) message.error(detail)
    } finally {
      setLoading(false)
    }
  }

  const clearSelection = () => {
    setSelectedRunId('')
    setCompareRunId('')
    setReport(null)
    setCompareResult(null)
    setSearchParams({})
  }

  const resetFilters = () => {
    setScenarioFilter('')
    clearSelection()
  }

  // 场景筛选项：从 run 列表聚合（含各场景 run 数量与出现过的考纲版本）
  const scenarioOptions = useMemo(() => {
    const map = new Map<string, { name: string; count: number; versions: Set<number> }>()
    for (const r of runs) {
      const entry = map.get(r.scenario_id)
      if (entry) {
        entry.count += 1
        entry.versions.add(r.scenario_version ?? 1)
      } else {
        map.set(r.scenario_id, {
          name: r.scenario_name || r.scenario_id.slice(0, 8),
          count: 1,
          versions: new Set([r.scenario_version ?? 1]),
        })
      }
    }
    return [...map.entries()].map(([id, s]) => {
      const versions = [...s.versions].sort((a, b) => a - b).map((v) => `v${v}`).join('/')
      return { value: id, label: `${s.name}（${s.count} · ${versions}）` }
    })
  }, [runs])

  const filteredRuns = useMemo(
    () => (scenarioFilter ? runs.filter((r) => r.scenario_id === scenarioFilter) : runs),
    [runs, scenarioFilter],
  )

  const buildOption = (r: Run) => {
    const passRate = r.summary?.pass_rate
    const pct = passRate != null ? `${Math.round(passRate * 100)}%` : '-'
    const scenario = r.scenario_name || r.scenario_id.slice(0, 8)
    const version = `v${r.scenario_version ?? 1}`
    const target = r.target_name || r.target_id.slice(0, 8)
    const time = r.started_at ? formatDateTime(r.started_at) : ''
    const trigger = r.triggered_by ?? 'manual'
    return {
      value: r.id,
      searchText: `${scenario} ${version} ${target} ${time} ${r.id} ${triggerLabels[trigger] ?? trigger}`.toLowerCase(),
      label: (
        <span style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
          <span style={{ fontWeight: 500, overflow: 'hidden', textOverflow: 'ellipsis' }}>{scenario}</span>
          <Tag color="geekblue" style={{ marginRight: 0, fontSize: 10, lineHeight: '16px', padding: '0 4px' }}>{version}</Tag>
          <span style={{ color: colors.textMuted }}>· {target}</span>
          <span style={{ color: colors.textMuted, fontSize: 12 }}>{time}</span>
          <span style={{
            color: passRate != null && passRate >= 0.8 ? '#3f8600' : '#cf1322',
            fontSize: 12, fontWeight: 600,
          }}>{pct}</span>
          <Tag color={triggerColors[trigger] ?? 'default'} style={{ marginRight: 0, fontSize: 10, lineHeight: '16px', padding: '0 4px' }}>
            {triggerLabels[trigger] ?? trigger}
          </Tag>
        </span>
      ),
    }
  }

  const runSelectOptions = filteredRuns.map(buildOption)

  // 报告 B 只能选与报告 A 同场景同版本（同考纲）的 run
  const selectedRun = runs.find((r) => r.id === selectedRunId)
  const compareOptions = runs
    .filter((r) =>
      r.id !== selectedRunId
      && selectedRun
      && r.scenario_id === selectedRun.scenario_id
      && (r.scenario_version ?? 1) === (selectedRun.scenario_version ?? 1))
    .map(buildOption)

  const optionFilter = (input: string, opt?: { searchText?: string }) =>
    (opt?.searchText ?? '').includes(input.toLowerCase())

  return (
    <PageWrapper title="评测报告" description="查看评测结果详情与统计分析" inline fullHeight>
      <div style={{ height: '100%', display: 'flex', flexDirection: 'column', overflow: 'hidden' }}>
      {/* 选择栏：两行布局，避免对比模式下控件换行错乱 */}
      <div style={{
        padding: '8px 16px', flexShrink: 0,
        borderBottom: `1px solid ${colors.border}`,
        background: colors.bgSubtle,
        display: 'flex', flexDirection: 'column', gap: 8,
      }}>
        {/* 第一行：视图模式 + 场景筛选 + 重置/刷新 */}
        <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
          <Segmented
            value={viewMode}
            onChange={(v) => { setViewMode(v as ViewMode); setCompareResult(null) }}
            options={[
              { label: '单次报告', value: 'single' },
              { label: '对比报告', value: 'compare', icon: <DiffOutlined /> },
            ]}
          />
          <Select
            style={{ width: 320 }}
            value={scenarioFilter || undefined}
            placeholder={`全部场景（${runs.length}）`}
            allowClear
            onChange={(v) => setScenarioFilter(v ?? '')}
            options={scenarioOptions}
            popupMatchSelectWidth={false}
          />
          <div style={{ marginLeft: 'auto', display: 'flex', gap: 8 }}>
            <Tooltip title="重置筛选与选择">
              <Button size="middle" icon={<ClearOutlined />} onClick={resetFilters}>重置</Button>
            </Tooltip>
            <Tooltip title="刷新列表">
              <Button size="middle" icon={<ReloadOutlined />} onClick={() => reloadRuns()} />
            </Tooltip>
          </div>
        </div>

        {/* 第二行：报告选择 + 操作 */}
        <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
          <Select
            style={{ flex: 1, minWidth: 320, maxWidth: 680 }}
            placeholder={viewMode === 'compare' ? '选择报告 A' : '选择已完成的评测记录'}
            value={selectedRunId || undefined}
            onChange={(v) => (v ? handleView(v) : clearSelection())}
            allowClear
            showSearch
            filterOption={optionFilter}
            options={runSelectOptions}
            popupMatchSelectWidth={false}
          />

          {viewMode === 'compare' && (
            <>
              <span style={{ color: colors.textMuted, fontSize: 12, flexShrink: 0 }}>vs</span>
              <Tooltip title={selectedRunId ? '仅可选择与报告 A 相同场景的记录' : '请先选择报告 A'}>
                <Select
                  style={{ flex: 1, minWidth: 320, maxWidth: 680 }}
                  placeholder="选择报告 B（同场景）"
                  value={compareRunId || undefined}
                  onChange={(v) => { setCompareRunId(v ?? ''); if (!v) setCompareResult(null) }}
                  allowClear
                  showSearch
                  disabled={!selectedRunId}
                  filterOption={optionFilter}
                  options={compareOptions}
                  popupMatchSelectWidth={false}
                  notFoundContent={<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} description="没有同场景同版本的其他评测记录" />}
                />
              </Tooltip>
              <Button
                type="primary"
                icon={<DiffOutlined />}
                disabled={!selectedRunId || !compareRunId}
                onClick={handleCompare}
                style={{ flexShrink: 0 }}
              >
                对比
              </Button>
            </>
          )}

          {viewMode === 'single' && report && (
            <Space style={{ flexShrink: 0 }}>
              <Button icon={<DownloadOutlined />} onClick={() => reportsApi.download(selectedRunId, 'html')}>
                导出 HTML
              </Button>
              <Button icon={<FileMarkdownOutlined />} onClick={() => reportsApi.download(selectedRunId, 'markdown')}>
                导出 MD
              </Button>
            </Space>
          )}
        </div>
      </div>

      {/* 报告内容区 */}
      <div style={{ flex: 1, minHeight: 0, overflowY: 'auto', padding: '16px' }}>
        <Spin spinning={loading}>
          {viewMode === 'compare'
            ? <CompareView result={compareResult} />
            : <SingleReportView report={report} />
          }
        </Spin>
      </div>
      </div>
    </PageWrapper>
  )
}

// ── Single Report View ───────────────────────────────────────────────────

function SingleReportView({ report }: { report: Report | null }) {
  if (!report) {
    return (
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', minHeight: 200 }}>
        <Empty description="请选择一个评测记录查看报告" />
      </div>
    )
  }

  return (
    <>
      <Row gutter={[16, 16]} style={{ marginBottom: 16 }}>
        <Col xs={24} sm={12} md={6}>
          <Card><Statistic title="总用例数" value={report.summary.total_cases} /></Card>
        </Col>
        <Col xs={24} sm={12} md={6}>
          <Card>
            <Statistic title="通过用例" value={report.summary.passed_cases}
              valueStyle={{ color: '#3f8600' }} prefix={<CheckCircleOutlined />} />
          </Card>
        </Col>
        <Col xs={24} sm={12} md={6}>
          <Card>
            <Statistic title="失败用例" value={report.summary.failed_cases}
              valueStyle={{ color: '#cf1322' }} prefix={<CloseCircleOutlined />} />
          </Card>
        </Col>
        <Col xs={24} sm={12} md={6}>
          <Card>
            <Statistic title="通过率" value={report.summary.pass_rate * 100} precision={1} suffix="%"
              valueStyle={{ color: report.summary.pass_rate >= 0.8 ? '#3f8600' : '#cf1322' }} />
          </Card>
        </Col>
      </Row>

      {report.summary.connectivity_cases > 0 && (
        <Alert type="info" showIcon style={{ marginBottom: 16 }}
          message={`本次运行含 ${report.summary.connectivity_cases} 个连通用例（未配置判定标准，收到回复即通过）` +
            (report.summary.judged_pass_rate != null
              ? `，判定型通过率 ${(report.summary.judged_pass_rate * 100).toFixed(1)}%`
              : '，无判定型用例')} />
      )}

      <Card style={{ marginBottom: 16 }}>
        <Descriptions size="small" column={2}>
          <Descriptions.Item label="评测对象">{report.target_name}</Descriptions.Item>
          <Descriptions.Item label="评测场景">
            <Space size={6}>
              {report.scenario_name}
              {report.scenario_version != null && <Tag color="geekblue">v{report.scenario_version}</Tag>}
            </Space>
          </Descriptions.Item>
          <Descriptions.Item label="触发方式">
            <Tag color={triggerColors[report.triggered_by as keyof typeof triggerColors] ?? 'default'}>
              {triggerLabels[report.triggered_by as keyof typeof triggerLabels] ?? report.triggered_by ?? '手动'}
            </Tag>
          </Descriptions.Item>
          <Descriptions.Item label="开始时间">{formatDateTime(report.started_at)}</Descriptions.Item>
          <Descriptions.Item label="完成时间">{report.completed_at ? formatDateTime(report.completed_at) : '-'}</Descriptions.Item>
        </Descriptions>
      </Card>

      <Card title="用例明细">
        <Collapse items={report.cases.map((c) => ({
          key: c.case_id,
          label: (
            <Space>
              <span style={{ fontWeight: 500 }}>{c.case_id}</span>
              {c.connectivity
                ? <Tag color="blue">连通用例</Tag>
                : c.results.every((r) => r.passed)
                  ? <Tag color="success">全部通过</Tag>
                  : <Tag color="error">存在失败</Tag>}
              <Tag>{c.turns.length} 轮对话</Tag>
            </Space>
          ),
          children: <CaseDetail c={c} />,
        }))} />
      </Card>
    </>
  )
}

function CaseDetail({ c }: { c: CaseReport }) {
  return (
    <div>
      <div style={{ marginBottom: 16 }}>
        {c.turns.map((turn, idx) => (
          <div key={idx} style={{ marginBottom: 12 }}>
            <div style={{ display: 'flex', justifyContent: 'flex-start', marginBottom: 6 }}>
              <div style={{
                background: colors.chatUser, padding: '8px 14px',
                borderRadius: '12px 12px 12px 2px', maxWidth: '70%',
                fontSize: 13, lineHeight: 1.6,
              }}>
                <UserOutlined style={{ marginRight: 6, color: '#1677ff' }} />
                {turn.sent_text}
              </div>
            </div>
            <div style={{ display: 'flex', justifyContent: 'flex-end' }}>
              <div style={{
                background: colors.chatAgent, padding: '8px 14px',
                borderRadius: '12px 12px 2px 12px', maxWidth: '70%',
                fontSize: 13, lineHeight: 1.6,
              }}>
                <RobotOutlined style={{ marginRight: 6, color: '#52c41a' }} />
                {turn.reply_text || '（无回复）'}
                {turn.latency_ms != null && (
                  <span style={{ color: '#999', fontSize: 11, marginLeft: 8 }}>{turn.latency_ms}ms</span>
                )}
              </div>
            </div>
          </div>
        ))}
      </div>
      <Table size="small" pagination={false} dataSource={c.results} rowKey={(_, idx) => String(idx)}
        columns={[
          { title: '规则', dataIndex: 'rule_type', width: 160 },
          { title: '结果', dataIndex: 'passed', width: 80,
            render: (p: boolean) => p ? <Tag color="success">通过</Tag> : <Tag color="error">失败</Tag> },
          { title: '评分', dataIndex: 'score', width: 80,
            render: (s: number | null) => s != null ? s.toFixed(2) : '-' },
          { title: '说明', dataIndex: 'reason' },
        ]}
      />
    </div>
  )
}

// ── Compare View ─────────────────────────────────────────────────────────

function CompareView({ result }: { result: CompareResult | null }) {
  if (!result) {
    return (
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', minHeight: 200 }}>
        <Empty description="选择两次评测记录后点击「对比」" />
      </div>
    )
  }

  const { run_a, run_b, delta, cases, changed_cases } = result
  const deltaColor = (v: number) => v > 0 ? '#3f8600' : v < 0 ? '#cf1322' : colors.textMuted
  const deltaSign = (v: number) => v > 0 ? `+${v}` : String(v)

  return (
    <>
      {/* 汇总对比 */}
      <Row gutter={16} style={{ marginBottom: 16 }}>
        <Col span={11}>
          <Card title={<span style={{ color: '#1677ff' }}>报告 A — {run_a.run_id.slice(0, 8)}…</span>} size="small">
            <Descriptions size="small" column={1}>
              <Descriptions.Item label="场景">
                {run_a.scenario_name}
                {run_a.scenario_version != null && <Tag color="geekblue" style={{ marginLeft: 6 }}>v{run_a.scenario_version}</Tag>}
              </Descriptions.Item>
              <Descriptions.Item label="触发方式">
                <Tag color={triggerColors[run_a.triggered_by as keyof typeof triggerColors] ?? 'default'}>
                  {triggerLabels[run_a.triggered_by as keyof typeof triggerLabels] ?? run_a.triggered_by ?? '手动'}
                </Tag>
              </Descriptions.Item>
              <Descriptions.Item label="时间">{formatDateTime(run_a.started_at)}</Descriptions.Item>
              <Descriptions.Item label="通过率">{(run_a.summary.pass_rate * 100).toFixed(1)}%</Descriptions.Item>
              <Descriptions.Item label="用例">{run_a.summary.passed_cases}/{run_a.summary.total_cases}</Descriptions.Item>
            </Descriptions>
          </Card>
        </Col>
        <Col span={2} style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', flexDirection: 'column', gap: 8 }}>
          <div style={{ fontSize: 11, color: colors.textMuted }}>变化</div>
          <div style={{ fontWeight: 700, color: deltaColor(delta.pass_rate), fontSize: 16 }}>
            {deltaSign(Math.round(delta.pass_rate * 1000) / 10)}%
          </div>
          <Badge count={changed_cases} color={changed_cases > 0 ? 'orange' : 'green'}
            title={`${changed_cases} 个用例结果变化`} />
        </Col>
        <Col span={11}>
          <Card title={<span style={{ color: '#52c41a' }}>报告 B — {run_b.run_id.slice(0, 8)}…</span>} size="small">
            <Descriptions size="small" column={1}>
              <Descriptions.Item label="场景">
                {run_b.scenario_name}
                {run_b.scenario_version != null && <Tag color="geekblue" style={{ marginLeft: 6 }}>v{run_b.scenario_version}</Tag>}
              </Descriptions.Item>
              <Descriptions.Item label="触发方式">
                <Tag color={triggerColors[run_b.triggered_by as keyof typeof triggerColors] ?? 'default'}>
                  {triggerLabels[run_b.triggered_by as keyof typeof triggerLabels] ?? run_b.triggered_by ?? '手动'}
                </Tag>
              </Descriptions.Item>
              <Descriptions.Item label="时间">{formatDateTime(run_b.started_at)}</Descriptions.Item>
              <Descriptions.Item label="通过率">{(run_b.summary.pass_rate * 100).toFixed(1)}%</Descriptions.Item>
              <Descriptions.Item label="用例">{run_b.summary.passed_cases}/{run_b.summary.total_cases}</Descriptions.Item>
            </Descriptions>
          </Card>
        </Col>
      </Row>

      {/* 用例对比表 */}
      <Card title={`用例对比（${changed_cases} 个结果变化）`}>
        <Table
          size="small"
          pagination={cases.length > 20 ? { pageSize: 20, showTotal: (t) => `共 ${t} 个用例` } : false}
          dataSource={cases}
          rowKey="case_id"
          rowClassName={(r) => r.changed ? 'run-row' : ''}
          columns={[
            { title: '用例', dataIndex: 'case_id', width: 180,
              render: (id: string, r) => (
                <Space>
                  {r.changed && <Badge dot color="orange" />}
                  <span style={{ fontWeight: r.changed ? 600 : 400 }}>{id}</span>
                  {r.connectivity && <Tag color="blue">连通</Tag>}
                </Space>
              ),
            },
            { title: '报告 A', dataIndex: 'run_a_passed', width: 100,
              render: (p: boolean | null) =>
                p === null ? <Tag>无</Tag>
                  : p ? <Tag color="success">通过</Tag>
                  : <Tag color="error">失败</Tag>,
            },
            { title: '报告 B', dataIndex: 'run_b_passed', width: 100,
              render: (p: boolean | null) =>
                p === null ? <Tag>无</Tag>
                  : p ? <Tag color="success">通过</Tag>
                  : <Tag color="error">失败</Tag>,
            },
            { title: '变化', width: 80,
              render: (_: any, r) => {
                if (!r.changed) return <span style={{ color: colors.textMuted }}>—</span>
                if (r.run_b_passed && !r.run_a_passed) return <Tag color="success">改善 ↑</Tag>
                if (!r.run_b_passed && r.run_a_passed) return <Tag color="error">退步 ↓</Tag>
                return <Tag color="orange">变化</Tag>
              },
            },
          ]}
          expandable={{
            expandedRowRender: (r) => (
              <Row gutter={16}>
                <Col span={12}>
                  <div style={{ fontSize: 12, color: colors.textMuted, marginBottom: 4 }}>报告 A 规则</div>
                  {r.run_a_results.map((res, i) => (
                    <div key={i} style={{ fontSize: 12, marginBottom: 2 }}>
                      {res.passed ? '✅' : '❌'} {res.rule_type}: {res.reason}
                    </div>
                  ))}
                </Col>
                <Col span={12}>
                  <div style={{ fontSize: 12, color: colors.textMuted, marginBottom: 4 }}>报告 B 规则</div>
                  {r.run_b_results.map((res, i) => (
                    <div key={i} style={{ fontSize: 12, marginBottom: 2 }}>
                      {res.passed ? '✅' : '❌'} {res.rule_type}: {res.reason}
                    </div>
                  ))}
                </Col>
              </Row>
            ),
            rowExpandable: (r) => r.run_a_results.length > 0 || r.run_b_results.length > 0,
          }}
        />
      </Card>
    </>
  )
}
