import { useState } from 'react'
import { useNavigate } from 'react-router-dom'
import {
  Button, Table, Tag, Modal, Form, Select, InputNumber, Input, Space,
  Popconfirm, Drawer, Row, Col, Statistic, Progress, Empty, Spin, message,
} from 'antd'
import {
  PlusOutlined, ReloadOutlined, StopOutlined, BarChartOutlined,
  FileMarkdownOutlined, MinusCircleOutlined,
} from '@ant-design/icons'
import { Line } from '@ant-design/charts'
import PageWrapper from '../components/PageWrapper'
import {
  campaignsApi, targetsApi, scenariosApi, runsApi,
  type CampaignListItem, type CampaignReport, type Target, type Scenario, type Run,
} from '../api'
import { passRateColor } from '../utils/colors'
import { shortDateTime } from '../utils/date'
import { useResource } from '../hooks/useResource'
import { usePolling } from '../hooks/usePolling'
import { useTabStore } from '../stores/tabStore'
import { colors, statusColors, statusLabels, triggerColors, triggerLabels } from '../tokens'

const CAMPAIGN_STATUS: Record<string, { label: string; color: string }> = {
  planned: { label: '计划中', color: 'default' },
  running: { label: '进行中', color: 'processing' },
  completed: { label: '已完成', color: 'success' },
  cancelled: { label: '已取消', color: 'default' },
  failed: { label: '失败', color: 'error' },
}

const WINDOW_OPTIONS = [6, 12, 24, 48, 72].map((h) => ({ label: `${h} 小时`, value: h * 3600 }))

const POLL_INTERVAL_MS = 5000

const isActiveStatus = (status: string) => status === 'planned' || status === 'running'

function fmtWindow(seconds: number): string {
  if (seconds % 3600 === 0) return `${seconds / 3600}h`
  if (seconds % 60 === 0) return `${seconds / 60}m`
  return `${seconds}s`
}

function fmtPct(v: number | null | undefined): string {
  return v == null ? '—' : `${(v * 100).toFixed(1)}%`
}

interface PlanFormEntry {
  scenario_id?: string
  offset_hours?: number
  count?: number
}

interface CampaignsListsData {
  campaigns: CampaignListItem[]
  targets: Target[]
  scenarios: Scenario[]
}

export default function CampaignsPage() {
  const navigate = useNavigate()
  const activeKey = useTabStore((s) => s.activeKey)

  const [createOpen, setCreateOpen] = useState(false)
  const [submitting, setSubmitting] = useState(false)
  const [form] = Form.useForm()

  const [reportOpen, setReportOpen] = useState(false)
  const [reportLoading, setReportLoading] = useState(false)
  const [report, setReport] = useState<CampaignReport | null>(null)
  const [reportRuns, setReportRuns] = useState<Run[]>([])

  const targetName = (id: string) => targets.find((t) => t.id === id)?.name ?? id.slice(0, 8)

  const { data, loading, reload } = useResource<CampaignsListsData>(
    async () => {
      const [c, t, s] = await Promise.all([campaignsApi.list(), targetsApi.list(), scenariosApi.list()])
      return { campaigns: c.data, targets: t.data, scenarios: s.data }
    },
    { tabPath: '/campaigns' },
  )
  const campaigns = data?.campaigns ?? []
  const targets = data?.targets ?? []
  const scenarios = data?.scenarios ?? []

  // Poll the list while this tab is active and a campaign is still working —
  // compressed dev-line campaigns change fast. Stop once all are terminal.
  const hasActiveCampaign = campaigns.some((c) => isActiveStatus(c.status))
  usePolling(
    () => void reload(true),
    POLL_INTERVAL_MS,
    activeKey === '/campaigns' && hasActiveCampaign,
  )

  const openCreate = () => {
    form.setFieldsValue({
      name: '', target_id: undefined, window_seconds: 24 * 3600, time_scale: 1,
      plan: [{ scenario_id: undefined, offset_hours: 0, count: 1 }],
    })
    setCreateOpen(true)
  }

  const submitCreate = async () => {
    const values = await form.validateFields()
    setSubmitting(true)
    try {
      await campaignsApi.create({
        name: values.name,
        target_id: values.target_id,
        window_seconds: values.window_seconds,
        time_scale: values.time_scale,
        plan: (values.plan as PlanFormEntry[]).map((e) => ({
          scenario_id: e.scenario_id as string,
          offset_seconds: Math.round((e.offset_hours ?? 0) * 3600),
          count: e.count ?? 1,
        })),
      })
      message.success('评估活动已创建并开始调度')
      setCreateOpen(false)
      reload()
    } finally {
      setSubmitting(false)
    }
  }

  const cancelCampaign = async (id: string) => {
    await campaignsApi.cancel(id)
    message.success('活动已取消')
    reload()
  }

  const fetchReport = async (campaignId: string, silent = false) => {
    if (!silent) {
      setReportLoading(true)
      setReport(null)
      setReportRuns([])
    }
    try {
      const [rep, runs] = await Promise.all([
        campaignsApi.report(campaignId),
        runsApi.list(),
      ])
      setReport(rep.data)
      setReportRuns(runs.data.filter((r) => r.campaign_id === campaignId))
    } finally {
      if (!silent) setReportLoading(false)
    }
  }

  const openReport = (campaign: CampaignListItem) => {
    setReportOpen(true)
    fetchReport(campaign.id)
  }

  // Keep the open report drawer live while its campaign is still running.
  const reportId = report?.campaign_id ?? null
  const reportCampaignActive = campaigns.some(
    (c) => c.id === reportId && isActiveStatus(c.status),
  )
  usePolling(
    () => { if (reportId) void fetchReport(reportId, true) },
    POLL_INTERVAL_MS,
    activeKey === '/campaigns' && reportOpen && !!reportId && reportCampaignActive,
  )

  const columns = [
    { title: '名称', dataIndex: 'name', key: 'name' },
    { title: '评测对象', key: 'target', render: (_: unknown, c: CampaignListItem) => targetName(c.target_id) },
    { title: '窗口', key: 'window', render: (_: unknown, c: CampaignListItem) => fmtWindow(c.window_seconds) },
    {
      title: '倍速', key: 'scale',
      render: (_: unknown, c: CampaignListItem) => (c.time_scale === 1 ? '实时' : `×${c.time_scale}`),
    },
    {
      title: '状态', key: 'status',
      render: (_: unknown, c: CampaignListItem) => {
        const meta = CAMPAIGN_STATUS[c.status] ?? { label: c.status, color: 'default' }
        return <Tag color={meta.color}>{meta.label}</Tag>
      },
    },
    {
      title: '进度', key: 'progress',
      render: (_: unknown, c: CampaignListItem) => `${c.progress.completed_runs}/${c.progress.planned_total}`,
    },
    {
      title: '整窗通过率', key: 'pass_rate',
      render: (_: unknown, c: CampaignListItem) => {
        const rate = c.progress.overall_pass_rate
        if (rate == null) return '—'
        return (
          <Progress
            percent={Math.round(rate * 100)} size="small" style={{ width: 120 }}
            strokeColor={passRateColor(rate)}
          />
        )
      },
    },
    {
      title: '操作', key: 'actions',
      render: (_: unknown, c: CampaignListItem) => (
        <Space>
          <Button size="small" icon={<BarChartOutlined />} onClick={() => openReport(c)}>报告</Button>
          {isActiveStatus(c.status) && (
            <Popconfirm title="取消该活动？已完成的子运行会保留。" onConfirm={() => cancelCampaign(c.id)}>
              <Button size="small" danger icon={<StopOutlined />}>取消</Button>
            </Popconfirm>
          )}
        </Space>
      ),
    },
  ]

  const trendData = (report?.time_trend ?? [])
    .filter((b) => b.pass_rate != null)
    .map((b) => ({
      slot: `${(b.start_seconds / 3600).toFixed(1)}h`,
      value: Math.round((b.pass_rate as number) * 100),
      runs: b.run_count,
    }))

  const trendConfig = {
    data: trendData,
    xField: 'slot',
    yField: 'value',
    smooth: true,
    height: 220,
    yAxis: { label: { formatter: (v: string) => `${v}%` }, min: 0, max: 100 },
    point: { size: 3 },
    color: colors.primary,
    tooltip: {
      formatter: (d: { value: number; runs: number }) => ({
        name: '通过率', value: `${d.value}%（${d.runs} 次）`,
      }),
    },
  }

  const capabilityColumns = [
    { title: '场景', dataIndex: 'scenario_name', key: 'scenario_name' },
    { title: '运行数', dataIndex: 'run_count', key: 'run_count' },
    {
      title: '通过率', key: 'pass_rate',
      render: (_: unknown, r: { pass_rate: number | null }) =>
        r.pass_rate == null ? '—' : (
          <Progress percent={Math.round(r.pass_rate * 100)} size="small" style={{ width: 100 }}
            strokeColor={passRateColor(r.pass_rate)} />
        ),
    },
    { title: '可用性', key: 'availability', render: (_: unknown, r: { availability: number | null }) => fmtPct(r.availability) },
    {
      title: '时延', key: 'latency',
      render: (_: unknown, r: { avg_latency_ms: number | null }) =>
        r.avg_latency_ms == null ? '—' : `${Math.round(r.avg_latency_ms)}ms`,
    },
  ]

  const runColumns = [
    { title: '子运行', dataIndex: 'id', key: 'id', render: (id: string) => <code>{id.slice(0, 8)}</code> },
    {
      title: '场景', key: 'scenario',
      render: (_: unknown, r: Run) => (
        <Space size={4}>
          <span>{scenarios.find((s) => s.id === r.scenario_id)?.name ?? r.scenario_id.slice(0, 8)}</span>
          {r.scenario_version != null && <Tag>v{r.scenario_version}</Tag>}
        </Space>
      ),
    },
    {
      title: '来源', key: 'trigger',
      render: (_: unknown, r: Run) => {
        const t = r.triggered_by ?? ''
        return <Tag color={triggerColors[t] ?? 'default'}>{triggerLabels[t] ?? t}</Tag>
      },
    },
    {
      title: '状态', key: 'status',
      render: (_: unknown, r: Run) => (
        <span style={{ color: statusColors[r.status] ?? colors.textMuted }}>
          {statusLabels[r.status] ?? r.status}
        </span>
      ),
    },
    {
      title: '通过率', key: 'pass_rate',
      render: (_: unknown, r: Run) => {
        const rate = r.summary?.pass_rate
        return rate == null ? '—' : fmtPct(rate)
      },
    },
    { title: '时间', key: 'time', render: (_: unknown, r: Run) => shortDateTime(r.started_at) },
    {
      title: '', key: 'drill',
      render: (_: unknown, r: Run) => (
        <Button size="small" type="link" onClick={() => navigate(`/reports?run=${r.id}`)}>查看报告</Button>
      ),
    },
  ]

  return (
    <PageWrapper
      title="评估活动"
      description="在一个服务周期窗口内按计划持续评测同一对象，聚合成周期报告"
      inline
      fullHeight
      extra={
        <Space>
          <Button icon={<ReloadOutlined />} onClick={() => reload()} />
          <Button type="primary" icon={<PlusOutlined />} onClick={openCreate}>新建活动</Button>
        </Space>
      }
    >
      <div style={{ height: '100%', overflowY: 'auto', padding: '0 16px 16px' }}>
        <Table
          rowKey="id"
          loading={loading}
          dataSource={campaigns}
          columns={columns}
          pagination={false}
          locale={{ emptyText: <Empty description="还没有评估活动" /> }}
        />
      </div>

      {/* 创建活动 */}
      <Modal
        title="新建评估活动"
        open={createOpen}
        onCancel={() => setCreateOpen(false)}
        onOk={submitCreate}
        confirmLoading={submitting}
        width={640}
        destroyOnClose
      >
        <Form form={form} layout="vertical">
          <Form.Item name="name" label="活动名称" rules={[{ required: true, message: '请输入名称' }]}>
            <Input placeholder="如：数字员工 24h 服务周期" />
          </Form.Item>
          <Form.Item name="target_id" label="评测对象" rules={[{ required: true, message: '请选择对象' }]}>
            <Select
              placeholder="选择评测对象"
              options={targets.map((t) => ({ label: t.name, value: t.id }))}
            />
          </Form.Item>
          <Row gutter={16}>
            <Col span={12}>
              <Form.Item name="window_seconds" label="窗口长度" rules={[{ required: true }]}>
                <Select options={WINDOW_OPTIONS} />
              </Form.Item>
            </Col>
            <Col span={12}>
              <Form.Item
                name="time_scale"
                label="时间倍速"
                tooltip="1=真实墙钟（正式线）；开发线可设大倍速把窗口压缩成几分钟"
                rules={[{ required: true }]}
              >
                <InputNumber min={0.001} step={1} style={{ width: '100%' }} />
              </Form.Item>
            </Col>
          </Row>

          <div style={{ marginBottom: 8, color: colors.textSecondary }}>活动计划（在窗口的哪些时段跑哪个场景、跑几次）</div>
          <Form.List name="plan" rules={[{ validator: async (_, plan) => { if (!plan || plan.length < 1) return Promise.reject(new Error('至少一条计划条目')) } }]}>
            {(fields, { add, remove }, { errors }) => (
              <>
                {fields.map((field) => (
                  <Space key={field.key} align="baseline" style={{ display: 'flex', marginBottom: 8 }}>
                    <Form.Item
                      name={[field.name, 'scenario_id']}
                      rules={[{ required: true, message: '选择场景' }]}
                      style={{ marginBottom: 0 }}
                    >
                      <Select
                        placeholder="场景"
                        style={{ width: 220 }}
                        options={scenarios.map((s) => ({ label: s.name, value: s.id }))}
                      />
                    </Form.Item>
                    <Form.Item name={[field.name, 'offset_hours']} style={{ marginBottom: 0 }}>
                      <InputNumber min={0} step={0.5} addonAfter="h偏移" style={{ width: 130 }} />
                    </Form.Item>
                    <Form.Item name={[field.name, 'count']} style={{ marginBottom: 0 }}>
                      <InputNumber min={1} addonAfter="次" style={{ width: 100 }} />
                    </Form.Item>
                    {fields.length > 1 && (
                      <MinusCircleOutlined onClick={() => remove(field.name)} style={{ color: colors.textMuted }} />
                    )}
                  </Space>
                ))}
                <Button type="dashed" onClick={() => add({ scenario_id: undefined, offset_hours: 0, count: 1 })} block icon={<PlusOutlined />}>
                  添加计划条目
                </Button>
                <Form.ErrorList errors={errors} />
              </>
            )}
          </Form.List>
        </Form>
      </Modal>

      {/* 周期报告 */}
      <Drawer
        title={report ? `活动报告 — ${report.name}` : '活动报告'}
        open={reportOpen}
        onClose={() => setReportOpen(false)}
        width={760}
        extra={
          report && (
            <Button icon={<FileMarkdownOutlined />} onClick={() => campaignsApi.downloadReport(report.campaign_id)}>
              导出 Markdown
            </Button>
          )
        }
      >
        <Spin spinning={reportLoading}>
          {report && (
            <>
              <Row gutter={16}>
                <Col span={8}><Statistic title="子运行" value={`${report.summary.completed_runs}/${report.summary.total_runs}`} /></Col>
                <Col span={8}>
                  <Statistic
                    title="整窗通过率"
                    value={fmtPct(report.summary.overall_pass_rate)}
                    valueStyle={{ color: report.summary.overall_pass_rate == null ? undefined : passRateColor(report.summary.overall_pass_rate) }}
                  />
                </Col>
                <Col span={8}><Statistic title="可用性" value={fmtPct(report.summary.overall_availability)} /></Col>
              </Row>
              <div style={{ marginTop: 8, color: colors.textSecondary }}>
                平均时延：{report.summary.avg_latency_ms == null ? '—' : `${Math.round(report.summary.avg_latency_ms)}ms`}
              </div>

              <h4 style={{ marginTop: 24 }}>时间趋势（通过率随窗口时段）</h4>
              {trendData.length > 0 ? <Line {...trendConfig} /> : <Empty description="暂无已完成子运行" />}

              <h4 style={{ marginTop: 24 }}>能力汇总（按场景）</h4>
              <Table
                rowKey="scenario_id"
                size="small"
                pagination={false}
                dataSource={report.capability_summary}
                columns={capabilityColumns}
              />

              <h4 style={{ marginTop: 24 }}>子运行（点击下钻单次报告）</h4>
              <Table
                rowKey="id"
                size="small"
                pagination={false}
                dataSource={reportRuns}
                columns={runColumns}
                locale={{ emptyText: <Empty description="暂无子运行" /> }}
              />
            </>
          )}
        </Spin>
      </Drawer>
    </PageWrapper>
  )
}
