import React, { useState } from 'react'
import {
  Card, Steps, Button, Space, Input, Select, Form, Tag, Timeline,
  Descriptions, message, Row, Col, Typography, Divider, Alert, Table,
} from 'antd'
import {
  PlayCircleOutlined, RedoOutlined, StopOutlined, SafetyCertificateOutlined,
} from '@ant-design/icons'
import { api } from './api.js'

const { Text, Paragraph } = Typography

const roleColor = { cp: 'green', regulator: 'red', reviewer: 'blue', operator: 'orange' }
const roleLabel = { cp: '内容提供商', regulator: '监管主体', reviewer: '审核/媒资', operator: '运营商' }

// 七步流水线定义（审核在前，发码在后——审过才发证发码）
const STEPS = [
  { key: 'register', title: 'CP 送审', role: 'cp', desc: '原片送 CSPS 既有审核渠道 + 哈希包上链（链上不存原片）' },
  { key: 'csps', title: 'CSPS 合规审核', role: 'reviewer', desc: '基于原片审画面/台词/声音；验真送审哈希=上链哈希（审播一致）' },
  { key: 'issue', title: '审核通过·发码签发', role: 'regulator', desc: '审过才发码：按号段生成 MA 码，1:1 强绑定哈希' },
  { key: 'ingest', title: '媒资库入库', role: 'reviewer', desc: '审合格入库，建立媒资编码映射' },
  { key: 'publish', title: '发布给运营商', role: 'reviewer', desc: '携 MA 码+哈希证书发布' },
  { key: 'inject', title: 'CDN 注入校验', role: 'operator', desc: '注入前哈希比对，匹配放行（防偷换）' },
]

export default function FlowDemo() {
  const [form] = Form.useForm()
  const [current, setCurrent] = useState(0)
  const [running, setRunning] = useState(false)
  const [logs, setLogs] = useState([])
  const [ctx, setCtx] = useState({}) // reviewID/ctid/maCode/cert/fileHash/episodeHashes
  const [done, setDone] = useState(false)
  const [episodes, setEpisodes] = useState([]) // 集级哈希列表
  const [epVerify, setEpVerify] = useState({}) // {episode: 'match'|'mismatch'}

  function addLog(role, title, ok, detail) {
    setLogs((prev) => [...prev, { role, title, ok, detail, t: new Date().toLocaleTimeString() }])
  }

  function reset() {
    setCurrent(0); setLogs([]); setCtx({}); setDone(false); setRunning(false)
    setEpisodes([]); setEpVerify({})
  }

  // 执行单步，返回是否成功
  async function runStep(idx, shared) {
    const step = STEPS[idx]
    const v = form.getFieldsValue()
    const fileHash = shared.fileHash
    let res
    switch (step.key) {
      case 'register':
        // 一剧一码 + 集级哈希：按集数生成每集独立哈希
        shared.episodeHashes = []
        const epArr = []
        const epCount = Number(v.episodes) || 1
        for (let i = 1; i <= epCount; i++) {
          const eh = `${fileHash}-E${i}`
          shared.episodeHashes.push({ episode: i, hash: eh })
          epArr.push({ episode: i, file_sha256: eh, merkle_root: `mr-${eh}` })
        }
        res = await api.register({
          title: v.title, episode_count: epCount, category: v.category,
          file_sha256: fileHash, merkle_root: 'mr-' + fileHash, perceptual_hash: 'ph-' + fileHash,
          episodes: epArr,
          cp_media_id: v.cpId, cp_name: v.cpName,
        })
        if (res.ok) { shared.reviewID = res.data.data.review_id; shared.ctid = res.data.data.content_twin_id }
        addLog(step.role, step.title, res.ok, res.ok ? `流水号 ${shared.reviewID}（${epCount}集，每集独立哈希）` : res.data.message)
        break
      case 'issue':
        res = await api.issue({ review_id: shared.reviewID, issuer: '陕西IPTV运营公司' })
        if (res.ok) { shared.maCode = res.data.data.ma_code; shared.cert = res.data.data.certificate }
        addLog(step.role, step.title, res.ok, res.ok ? `MA码 ${shared.maCode}` : res.data.message)
        break
      case 'csps':
        res = await api.csps({ review_id: shared.reviewID, approved: true, reviewer_id: 'sxiptv-审核01' })
        addLog(step.role, step.title, res.ok, res.ok ? '审核通过（发码前置）' : res.data.message)
        break
      case 'ingest':
        res = await api.ingest({
          ma_code: shared.maCode, content_twin_id: shared.ctid,
          media_asset_id: 'SXMEDIA-' + fileHash, lib_name: '陕西IPTV媒体资源库',
        })
        addLog(step.role, step.title, res.ok, res.ok ? '已入媒资库' : res.data.message)
        break
      case 'publish':
        res = await api.publish({ ma_code: shared.maCode, certificate: shared.cert })
        addLog(step.role, step.title, res.ok, res.ok ? '已发布' : res.data.message)
        break
      case 'inject':
        res = await api.inject({
          content_twin_id: shared.ctid, ma_code: shared.maCode, file_sha256: fileHash,
          operator_id: v.opId, cdn_endpoint: v.cdn,
        })
        addLog(step.role, step.title, res.ok,
          res.ok ? `注入成功 ${res.data.data.distribution_id}` : res.data.message)
        break
      default:
        res = { ok: false }
    }
    return res.ok
  }

  // 一键全流程
  async function runAll() {
    setRunning(true); setLogs([]); setDone(false); setCurrent(0)
    const shared = { fileHash: 'fh-' + Date.now().toString(36) }
    for (let i = 0; i < STEPS.length; i++) {
      setCurrent(i)
      const ok = await runStep(i, shared)
      if (!ok) {
        message.error(`第 ${i + 1} 步「${STEPS[i].title}」失败，流程中断`)
        setRunning(false); setCtx(shared)
        return
      }
      await new Promise((r) => setTimeout(r, 500)) // 放慢便于演示观看
    }
    setCurrent(STEPS.length)
    setCtx(shared); setDone(true); setRunning(false)
    message.success('全流程跑通：审过即锁定，锁定即通行')
    await loadEpisodes(shared.maCode)
  }

  async function loadEpisodes(maCode) {
    const res = await api.episodes(maCode)
    if (res.ok) setEpisodes(res.data.data.episodes || [])
  }

  // 按集验真：correct=true 用正确哈希，false 用篡改哈希
  async function verifyEp(ep, correct) {
    const realHash = (ctx.episodeHashes || []).find((e) => e.episode === ep)?.hash
    const submit = correct ? realHash : 'TAMPERED-' + realHash
    const res = await api.verifyEpisode(ctx.maCode, ep, submit)
    const matched = res.ok && res.data.data?.match
    setEpVerify((prev) => ({ ...prev, [ep]: matched ? 'match' : 'mismatch' }))
    if (matched) message.success(`第${ep}集验真通过`)
    else message.warning(`第${ep}集不匹配（疑似该集被替换）`)
  }

  async function doTakedown() {
    const res = await api.takedown(ctx.maCode, '监管演示下架')
    if (res.ok) {
      addLog('regulator', '违规应急下架', true,
        `秒级下架，受影响 CDN: ${(res.data.data.cdn_endpoints || []).join(', ')}`)
      message.success('已全网下架')
    } else message.error(res.data.message)
  }

  async function doTamperTest() {
    const res = await api.inject({
      content_twin_id: ctx.ctid, ma_code: ctx.maCode, file_sha256: 'TAMPERED-' + ctx.fileHash,
      operator_id: 'OP-X', cdn_endpoint: 'cdn://x',
    })
    addLog('operator', '篡改注入测试', !res.ok, res.ok ? '⚠️ 异常：篡改竟通过' : '✅ 已拒绝：' + res.data.message)
    if (!res.ok) message.success('篡改内容被正确拦截')
  }

  return (
    <Row gutter={16}>
      <Col span={9}>
        <Card title="演示参数" size="small" style={{ marginBottom: 16 }}>
          <Form form={form} layout="vertical" size="small" initialValues={{
            title: '长安少年行', category: 'WD', episodes: 6,
            cpId: 'XAQJSL-2026-001', cpName: '西安曲江丝路文化传播有限公司',
            opId: 'CT-SX-IPTV', cdn: 'cdn://ct-sx/iptv/vod/changan001',
          }}>
            <Form.Item label="作品标题" name="title"><Input /></Form.Item>
            <Row gutter={8}>
              <Col span={12}>
                <Form.Item label="类目" name="category">
                  <Select options={[
                    { value: 'WD', label: '微短剧' }, { value: 'WJ', label: '网络剧' },
                    { value: 'DY', label: '网络电影' }, { value: 'DH', label: '网络动画' },
                  ]} />
                </Form.Item>
              </Col>
              <Col span={12}><Form.Item label="集数" name="episodes"><Input type="number" /></Form.Item></Col>
            </Row>
            <Form.Item label="内容提供商 (CP)" name="cpName"><Input /></Form.Item>
            <Form.Item label="CP 媒资编码" name="cpId"><Input /></Form.Item>
            <Form.Item label="运营商编码" name="opId"><Input /></Form.Item>
            <Form.Item label="CDN 端点" name="cdn"><Input /></Form.Item>
          </Form>
          <Space>
            <Button type="primary" icon={<PlayCircleOutlined />} loading={running} onClick={runAll}>
              一键全流程
            </Button>
            <Button icon={<RedoOutlined />} onClick={reset} disabled={running}>重置</Button>
          </Space>
        </Card>
      </Col>

      <Col span={15}>
        <Card title="内容生命周期流水线" style={{ marginBottom: 16 }}>
          <Steps
            direction="vertical" size="small" current={current}
            status={running ? 'process' : done ? 'finish' : 'wait'}
            items={STEPS.map((s) => ({
              title: <Space>{s.title}<Tag color={roleColor[s.role]}>{roleLabel[s.role]}</Tag></Space>,
              description: s.desc,
            }))}
          />
        </Card>

        {done && (
          <Card title={<Space><SafetyCertificateOutlined />赋码结果（双锚定）</Space>} style={{ marginBottom: 16 }}>
            <Descriptions bordered size="small" column={1}>
              <Descriptions.Item label="MA 码（监管锚点）"><Text strong copyable>{ctx.maCode}</Text></Descriptions.Item>
              <Descriptions.Item label="文件哈希（技术锚点）">{ctx.fileHash}</Descriptions.Item>
              <Descriptions.Item label="CTID（机器主键）">{ctx.ctid}</Descriptions.Item>
            </Descriptions>
            <Divider />
            <Space>
              <Button onClick={doTamperTest}>篡改注入测试（应拒绝）</Button>
              <Button danger icon={<StopOutlined />} onClick={doTakedown}>违规应急下架</Button>
            </Space>
          </Card>
        )}

        {done && episodes.length > 0 && (
          <Card
            title={<Space>集级面板<Tag color="purple">一剧一码 · {episodes.length} 集独立哈希</Tag></Space>}
            style={{ marginBottom: 16 }}
            extra={<Text type="secondary">集级子标识：{ctx.maCode}#E01 …</Text>}
          >
            <Table
              size="small" rowKey="episode" pagination={false}
              dataSource={episodes}
              columns={[
                { title: '集号', dataIndex: 'episode', width: 70, render: (e) => <Tag>第 {e} 集</Tag> },
                { title: '集级子标识', render: (_, r) => <Text code>{`${ctx.maCode}#E${String(r.episode).padStart(2, '0')}`}</Text> },
                { title: '该集哈希', dataIndex: 'hash_value', ellipsis: true },
                {
                  title: '验真状态', width: 110, render: (_, r) => {
                    const st = epVerify[r.episode]
                    if (st === 'match') return <Tag color="green">匹配</Tag>
                    if (st === 'mismatch') return <Tag color="red">不匹配</Tag>
                    return <Tag>未验</Tag>
                  },
                },
                {
                  title: '按集验真', width: 200, render: (_, r) => (
                    <Space>
                      <Button size="small" onClick={() => verifyEp(r.episode, true)}>正确</Button>
                      <Button size="small" danger onClick={() => verifyEp(r.episode, false)}>模拟篡改</Button>
                    </Space>
                  ),
                },
              ]}
            />
          </Card>
        )}

        <Card title="执行日志" size="small">
          {logs.length === 0
            ? <Alert type="info" message='点击「一键全流程」开始演示' />
            : <Timeline items={logs.map((l) => ({
                color: l.ok ? 'green' : 'red',
                children: (
                  <Space direction="vertical" size={0}>
                    <Space>
                      <Tag color={roleColor[l.role]}>{roleLabel[l.role]}</Tag>
                      <Text strong>{l.title}</Text>
                      <Text type="secondary" style={{ fontSize: 12 }}>{l.t}</Text>
                    </Space>
                    <Text type={l.ok ? 'success' : 'danger'}>{l.detail}</Text>
                  </Space>
                ),
              }))} />
          }
        </Card>
      </Col>
    </Row>
  )
}
