import { Alert, Button, Card, Drawer, Empty, Input, Space, Table, Typography } from 'antd'
import { useCallback, useEffect, useMemo, useState } from 'react'
import { useSearchParams } from 'react-router-dom'
import type { ApiError } from '../lib/api'
import { isOrchestratorDbUnavailable, listCleanedNotes, type CleanedNoteRecord } from '../lib/content'

export default function CleanedNotesPage() {
  const [searchParams, setSearchParams] = useSearchParams()
  const [loading, setLoading] = useState(false)
  const [error, setError] = useState<ApiError | null>(null)
  const [notes, setNotes] = useState<CleanedNoteRecord[]>([])
  const [total, setTotal] = useState(0)
  const [drawerOpen, setDrawerOpen] = useState(false)
  const [active, setActive] = useState<CleanedNoteRecord | null>(null)

  const page = useMemo(() => {
    const raw = Number(searchParams.get('page') || '1')
    return Number.isFinite(raw) && raw > 0 ? raw : 1
  }, [searchParams])

  const pageSize = useMemo(() => {
    const raw = Number(searchParams.get('page_size') || '20')
    return Number.isFinite(raw) && raw > 0 ? Math.min(raw, 200) : 20
  }, [searchParams])

  const query = useMemo(() => String(searchParams.get('query') || '').trim(), [searchParams])
  const [queryInput, setQueryInput] = useState(query)

  useEffect(() => {
    setQueryInput(query)
  }, [query])

  const setParam = useCallback(
    (patch: Record<string, string | undefined>) => {
      const next = new URLSearchParams(searchParams)
      Object.entries(patch).forEach(([k, v]) => {
        const val = String(v || '').trim()
        if (val) next.set(k, val)
        else next.delete(k)
      })
      setSearchParams(next)
    },
    [searchParams, setSearchParams],
  )

  const loadList = useCallback(async () => {
    setLoading(true)
    setError(null)
    try {
      const res = await listCleanedNotes({
        limit: pageSize,
        offset: (page - 1) * pageSize,
        query: query || undefined,
      })
      setNotes(res.notes || [])
      setTotal(res.total || 0)
    } catch (e) {
      setError(e as ApiError)
    } finally {
      setLoading(false)
    }
  }, [page, pageSize, query])

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

  const columns = useMemo(
    () => [
      { title: 'ID', dataIndex: 'id', width: 90 },
      {
        title: '原始作者',
        dataIndex: 'raw_author',
        width: 160,
        render: (v: unknown) => (v ? String(v) : '—'),
      },
      {
        title: '原始 URL',
        dataIndex: 'raw_url',
        width: 340,
        ellipsis: true,
        render: (v: unknown) => {
          const url = String(v || '').trim()
          if (!url) return '—'
          return (
            <a href={url} target="_blank" rel="noreferrer">
              {url}
            </a>
          )
        },
      },
      {
        title: '清洗内容',
        dataIndex: 'cleaned_content',
        ellipsis: true,
        render: (_: unknown, record: CleanedNoteRecord) => {
          const text = String(record.cleaned_content || '').trim()
          return (
            <Space>
              <Typography.Text ellipsis style={{ maxWidth: 520 }}>
                {text || '—'}
              </Typography.Text>
              <Button
                size="small"
                disabled={!text}
                onClick={() => {
                  setActive(record)
                  setDrawerOpen(true)
                }}
              >
                查看
              </Button>
            </Space>
          )
        },
      },
      {
        title: '创建时间',
        dataIndex: 'created_at',
        width: 200,
        render: (v: unknown) => (v ? String(v) : '—'),
      },
    ],
    [],
  )

  const dbMissing = isOrchestratorDbUnavailable(error)
  const cleanedText = String(active?.cleaned_content || '').trim()

  return (
    <div style={{ display: 'grid', gap: 16 }}>
      <Typography.Title level={3} style={{ margin: 0 }}>
        清洗笔记库
      </Typography.Title>

      <Card
        title="GET /api/v1/content/cleaned-notes"
        extra={
          <Space wrap>
            <Input.Search
              allowClear
              placeholder="搜索 cleaned_content / author / url / content"
              value={queryInput}
              onChange={(e) => setQueryInput(e.target.value)}
              onSearch={(value) => setParam({ query: value.trim() || undefined, page: '1' })}
              style={{ width: 360 }}
            />
            <Button onClick={loadList} disabled={loading}>
              刷新
            </Button>
          </Space>
        }
        loading={loading}
      >
        {dbMissing ? (
          <Empty
            image={Empty.PRESENTED_IMAGE_SIMPLE}
            description={
              <div style={{ maxWidth: 680 }}>
                <Typography.Text strong>内容库数据库不可用</Typography.Text>
                <Typography.Paragraph style={{ marginTop: 8, marginBottom: 0 }}>
                  服务端返回 503，通常表示 ORCHESTRATOR_DB_PATH 未配置、路径不存在或 DB 尚未初始化。
                  <br />
                  处理方式：
                  <br />
                  1）配置 ORCHESTRATOR_DB_PATH 指向可读的 sqlite 文件（默认 orchestrator/data/mvp.db）
                  <br />
                  2）初始化 DB：python Spider_XHS/orchestrator/db_init.py
                </Typography.Paragraph>
              </div>
            }
          />
        ) : error ? (
          <Alert
            type="error"
            showIcon
            message={error.status ? `HTTP ${error.status}` : '请求失败'}
            description={error.message}
            style={{ marginBottom: 16 }}
          />
        ) : null}

        <Table
          size="middle"
          rowKey="id"
          columns={columns}
          dataSource={notes}
          pagination={{
            current: page,
            pageSize,
            total,
            showSizeChanger: true,
            pageSizeOptions: [10, 20, 50, 100, 200],
            onChange: (nextPage, nextSize) => setParam({ page: String(nextPage), page_size: String(nextSize) }),
          }}
        />
      </Card>

      <Drawer
        title={active ? `cleaned_note #${active.id}` : 'cleaned_note'}
        open={drawerOpen}
        onClose={() => setDrawerOpen(false)}
        width={720}
      >
        {active ? (
          <div style={{ display: 'grid', gap: 12 }}>
            <div>
              <Typography.Text type="secondary">raw_note_id：</Typography.Text>
              <Typography.Text>{active.raw_note_id ?? '—'}</Typography.Text>
            </div>
            <div>
              <Typography.Text type="secondary">raw_author：</Typography.Text>
              <Typography.Text>{active.raw_author || '—'}</Typography.Text>
            </div>
            <div>
              <Typography.Text type="secondary">raw_url：</Typography.Text>
              {active.raw_url ? (
                <a href={active.raw_url} target="_blank" rel="noreferrer">
                  {active.raw_url}
                </a>
              ) : (
                <Typography.Text>—</Typography.Text>
              )}
            </div>
            <div>
              <Typography.Text type="secondary">created_at：</Typography.Text>
              <Typography.Text>{active.created_at || '—'}</Typography.Text>
            </div>
            <div>
              <Typography.Text type="secondary">cleaned_content：</Typography.Text>
              <pre
                style={{
                  marginTop: 8,
                  marginBottom: 0,
                  padding: 12,
                  background: '#fafafa',
                  border: '1px solid #f0f0f0',
                  borderRadius: 8,
                  whiteSpace: 'pre-wrap',
                  wordBreak: 'break-word',
                  maxHeight: 520,
                  overflow: 'auto',
                }}
              >
                {cleanedText || '—'}
              </pre>
            </div>
          </div>
        ) : null}
      </Drawer>
    </div>
  )
}
