const { useCallback, useEffect, useMemo, useRef, useState } = React;

const {
  App,
  Alert,
  Button,
  Card,
  Checkbox,
  Col,
  ConfigProvider,
  Drawer,
  Input,
  Pagination,
  Popover,
  Row,
  Select,
  Space,
  Spin,
  Tabs,
  Table,
  Typography,
  message,
} = antd;

const { Title, Text, Paragraph } = Typography;
const apiBase = (window.APP_CONFIG && window.APP_CONFIG.apiBase) || "/drugs";
const authBase = (window.APP_CONFIG && window.APP_CONFIG.authBase) || "/auth";
const AUTH_KEY = "drug_admin_token";
const PAGE_SIZE_OPTIONS = [30, 50, 100, 200];
const ALL_COLUMN_KEYS = ["id", "generic_name_en"];
const DEFAULT_VISIBLE_COLUMNS = {
  id: true,
  generic_name_en: true,
};
const SEARCH_HISTORY_KEY = "drug_site_recent_searches";
const SEARCH_HISTORY_LIMIT = 8;

function readInitialStateFromUrl() {
  const params = new URLSearchParams(window.location.search || "");
  const q = (params.get("q") || "").trim();
  const pageRaw = Number(params.get("page") || "1");
  const pageSizeRaw = Number(params.get("page_size") || "100");
  const colsRaw = (params.get("cols") || "").trim();
  const detailIdRaw = Number(params.get("detail_id") || "");

  let visibleColumns = { ...DEFAULT_VISIBLE_COLUMNS };
  if (colsRaw) {
    const selected = new Set(colsRaw.split(",").map((x) => x.trim()).filter((x) => ALL_COLUMN_KEYS.includes(x)));
    visibleColumns = ALL_COLUMN_KEYS.reduce((acc, key) => {
      acc[key] = selected.has(key);
      return acc;
    }, {});
    if (!Object.values(visibleColumns).some(Boolean)) {
      visibleColumns = { ...DEFAULT_VISIBLE_COLUMNS };
    }
  }

  return {
    q,
    page: Number.isFinite(pageRaw) && pageRaw > 0 ? Math.floor(pageRaw) : 1,
    pageSize: PAGE_SIZE_OPTIONS.includes(pageSizeRaw) ? pageSizeRaw : 100,
    visibleColumns,
    detailId: Number.isFinite(detailIdRaw) && detailIdRaw > 0 ? Math.floor(detailIdRaw) : null,
  };
}

function buildLoginRedirectUrl(detailId) {
  const params = new URLSearchParams(window.location.search || "");
  params.set("detail_id", String(detailId));
  const nextPath = `${window.location.pathname}?${params.toString()}`;
  return `/admin?next=${encodeURIComponent(nextPath)}`;
}

function clearDetailIdInUrl() {
  const params = new URLSearchParams(window.location.search || "");
  const hasDetailId = params.has("detail_id");
  const hasNext = params.has("next");
  if (!hasDetailId && !hasNext) {
    return;
  }
  params.delete("detail_id");
  params.delete("next");
  const query = params.toString();
  const nextUrl = `${window.location.pathname}${query ? `?${query}` : ""}`;
  window.history.replaceState(null, "", nextUrl);
}

function readSearchHistory() {
  try {
    const raw = window.localStorage.getItem(SEARCH_HISTORY_KEY);
    const parsed = raw ? JSON.parse(raw) : [];
    if (!Array.isArray(parsed)) {
      return [];
    }
    return parsed
      .filter((x) => x && typeof x.q === "string")
      .map((x) => ({
        q: x.q.trim(),
        reviewStatus: "",
      }))
      .filter((x) => x.q.length > 0)
      .slice(0, SEARCH_HISTORY_LIMIT);
  } catch {
    return [];
  }
}

function saveSearchHistory(items) {
  try {
    window.localStorage.setItem(SEARCH_HISTORY_KEY, JSON.stringify(items.slice(0, SEARCH_HISTORY_LIMIT)));
  } catch {
    // Ignore localStorage failures in restricted environments.
  }
}

function removeSearchHistoryItem(currentItems, target) {
  return currentItems.filter(
    (item) => !(item.q === target.q && (item.reviewStatus || "") === (target.reviewStatus || ""))
  );
}

function pushSearchHistory(currentItems, q, reviewStatus) {
  const normalized = (q || "").trim();
  if (!normalized) {
    return currentItems;
  }
  const status = reviewStatus || "";
  const next = [{ q: normalized, reviewStatus: status }];
  for (const item of currentItems) {
    if (item.q === normalized && (item.reviewStatus || "") === status) {
      continue;
    }
    next.push(item);
    if (next.length >= SEARCH_HISTORY_LIMIT) {
      break;
    }
  }
  return next;
}

function toText(value, fallback = "-") {
  if (value === null || value === undefined || value === "") {
    return fallback;
  }
  return String(value);
}

function normalizeError(err) {
  if (!err) {
    return "Unknown error";
  }
  return err.message || String(err);
}

async function fetchJSON(url, options = {}) {
  const resp = await fetch(url, options);
  if (!resp.ok) {
    const text = await resp.text();
    const err = new Error(text || `HTTP ${resp.status}`);
    err.status = resp.status;
    throw err;
  }
  return await resp.json();
}

function ReactDrugSite() {
  const init = useMemo(() => readInitialStateFromUrl(), []);

  const [queryInput, setQueryInput] = useState(init.q);
  const [queryValue, setQueryValue] = useState(init.q);
  const [page, setPage] = useState(init.page);
  const [pageSize, setPageSize] = useState(init.pageSize);

  const [loading, setLoading] = useState(false);
  const [errorMsg, setErrorMsg] = useState("");

  const [total, setTotal] = useState(0);
  const [items, setItems] = useState([]);

  const [detailOpen, setDetailOpen] = useState(false);
  const [detailLoading, setDetailLoading] = useState(false);
  const [detailError, setDetailError] = useState("");
  const [detailDrug, setDetailDrug] = useState(null);
  const [detailEvidence, setDetailEvidence] = useState([]);
  const [tableFilters, setTableFilters] = useState({});
  const [tableSorter, setTableSorter] = useState({});
  const [visibleColumns, setVisibleColumns] = useState(init.visibleColumns || DEFAULT_VISIBLE_COLUMNS);
  const [recentSearches, setRecentSearches] = useState(() => readSearchHistory());
  const [shareUrl, setShareUrl] = useState(window.location.href);
  const autoOpenedDetailRef = useRef(false);

  const authHeaders = useCallback(() => {
    const token = window.localStorage.getItem(AUTH_KEY) || "";
    if (!token) return {};
    return { Authorization: `Bearer ${token}` };
  }, []);

  const totalPages = Math.max(1, Math.ceil(total / pageSize));

  const fetchPage = useCallback(async () => {
    const offset = (page - 1) * pageSize;
    const params = new URLSearchParams({
      q: queryValue,
      limit: String(pageSize),
      offset: String(offset),
    });
    setLoading(true);
    setErrorMsg("");
    try {
      const data = await fetchJSON(`${apiBase}/search?${params.toString()}`);
      setTotal(Number(data.total || 0));
      setItems(Array.isArray(data.items) ? data.items : []);
    } catch (err) {
      setErrorMsg(normalizeError(err));
      setItems([]);
      setTotal(0);
    } finally {
      setLoading(false);
    }
  }, [page, pageSize, queryValue]);

  useEffect(() => {
    fetchPage().catch(() => {});
  }, [fetchPage]);

  useEffect(() => {
    const params = new URLSearchParams();
    if (queryValue) {
      params.set("q", queryValue);
    }
    if (page > 1) {
      params.set("page", String(page));
    }
    if (pageSize !== 100) {
      params.set("page_size", String(pageSize));
    }
    const cols = ALL_COLUMN_KEYS.filter((k) => visibleColumns[k]);
    if (cols.length !== ALL_COLUMN_KEYS.length) {
      params.set("cols", cols.join(","));
    }

    const query = params.toString();
    const nextUrl = `${window.location.pathname}${query ? `?${query}` : ""}`;
    window.history.replaceState(null, "", nextUrl);
    setShareUrl(window.location.href);
  }, [queryValue, page, pageSize, visibleColumns]);

  const applySearch = useCallback(
    (nextQuery) => {
      const normalized = (nextQuery || "").trim();
      setQueryInput(normalized);
      setQueryValue(normalized);
      setPage(1);

      const updated = pushSearchHistory(recentSearches, normalized, "");
      setRecentSearches(updated);
      saveSearchHistory(updated);
    },
    [recentSearches]
  );

  const openDetail = useCallback(async (id) => {
    setDetailOpen(true);
    setDetailLoading(true);
    setDetailError("");
    setDetailDrug(null);
    setDetailEvidence([]);

    try {
      const headers = authHeaders();
      const drug = await fetchJSON(`${apiBase}/${id}`, { headers });
      const evidences = await fetchJSON(`${apiBase}/${id}/evidences?limit=50`, { headers });
      setDetailDrug(drug);
      setDetailEvidence(Array.isArray(evidences.items) ? evidences.items : []);
    } catch (err) {
      if (err && err.status === 401) {
        setDetailOpen(false);
        window.localStorage.removeItem(AUTH_KEY);
        message.warning("未登录，正在跳转到登录页");
        window.location.href = buildLoginRedirectUrl(id);
        return;
      }
      setDetailError(normalizeError(err));
    } finally {
      setDetailLoading(false);
    }
  }, [authHeaders]);

  useEffect(() => {
    if (autoOpenedDetailRef.current) {
      return;
    }
    if (!init.detailId) {
      return;
    }
    const token = window.localStorage.getItem(AUTH_KEY) || "";
    if (!token) {
      return;
    }
    autoOpenedDetailRef.current = true;
    clearDetailIdInUrl();
    openDetail(init.detailId).catch(() => {});
  }, [init.detailId, openDetail]);

  const columns = useMemo(
    () => [
      {
        title: "ID",
        dataIndex: "id",
        key: "id",
        width: 96,
        sorter: (a, b) => Number(a.id || 0) - Number(b.id || 0),
        sortOrder: tableSorter.columnKey === "id" ? tableSorter.order : null,
      },
      {
        title: "英文通用名",
        dataIndex: "generic_name_en",
        key: "generic_name_en",
        sorter: (a, b) => toText(a.generic_name_en).localeCompare(toText(b.generic_name_en)),
        sortOrder: tableSorter.columnKey === "generic_name_en" ? tableSorter.order : null,
        render: (value) => <Text strong>{toText(value)}</Text>,
      },
      {
        title: "操作",
        key: "actions",
        width: 120,
        render: (_, row) => (
          <Button type="link" onClick={() => openDetail(row.id)}>
            查看详细
          </Button>
        ),
      },
    ],
    [openDetail, tableFilters, tableSorter]
  );

  const tableColumns = useMemo(() => {
    return columns.filter((col) => {
      if (col.key === "actions") {
        return true;
      }
      return visibleColumns[col.key] !== false;
    });
  }, [columns, visibleColumns]);

  const columnChooserContent = (
    <Space direction="vertical" size={6} style={{ minWidth: 160 }}>
      <Checkbox
        checked={visibleColumns.id}
        onChange={(e) => setVisibleColumns((prev) => ({ ...prev, id: e.target.checked }))}
      >
        ID
      </Checkbox>
      <Checkbox
        checked={visibleColumns.generic_name_en}
        onChange={(e) => setVisibleColumns((prev) => ({ ...prev, generic_name_en: e.target.checked }))}
      >
        英文通用名
      </Checkbox>
      <Button
        size="small"
        onClick={() => {
          setVisibleColumns({ ...DEFAULT_VISIBLE_COLUMNS });
        }}
      >
        恢复默认列
      </Button>
    </Space>
  );

  const detailTabItems = useMemo(() => {
    if (!detailDrug) {
      return [];
    }

    const evidenceRows = (detailEvidence || []).slice(0, 60).map((ev, idx) => ({
      key: `${idx}-${ev.field_name}-${ev.source_url || "-"}`,
      field_name: ev.field_name,
      evidence_text: ev.evidence_text,
      source_title: ev.source_title,
      source_url: ev.source_url,
      confidence: Number(ev.confidence || 0),
    }));

    const oneLineField = (label, value) => (
      <div className="detail-inline-item">
        <span className="detail-inline-label">{label}</span>
        <Text className="detail-inline-value">{toText(value)}</Text>
      </div>
    );

    return [
      {
        key: "base",
        label: "基础信息",
        children: (
          <Space direction="vertical" size="middle" style={{ width: "100%" }}>
            <Card size="small" title="药物核心字段">
              <div className="detail-inline-grid">
                {oneLineField("英文名", detailDrug.generic_name_en)}
                {oneLineField("药理", detailDrug.pharmacology)}
                {oneLineField("机制", detailDrug.mechanism)}
                {oneLineField("不良反应", detailDrug.adverse_reactions)}
                {oneLineField("临床用途", detailDrug.clinical_uses)}
              </div>
            </Card>

            <Card size="small" title="理化性质 JSON">
              <pre className="json-block">{JSON.stringify(detailDrug.physicochemical || {}, null, 2)}</pre>
            </Card>
          </Space>
        ),
      },
      {
        key: "evidence",
        label: `证据 (${detailEvidence.length})`,
        children: (
          <Card size="small" title={`证据片段 (${detailEvidence.length})`}>
            <Table
              size="small"
              rowKey="key"
              dataSource={evidenceRows}
              pagination={false}
              scroll={{ x: 760, y: 360 }}
              locale={{ emptyText: "暂无" }}
              columns={[
                {
                  title: "字段",
                  dataIndex: "field_name",
                  key: "field_name",
                  width: 120,
                  render: (value) => toText(value),
                },
                {
                  title: "证据",
                  dataIndex: "evidence_text",
                  key: "evidence_text",
                  render: (value) => <div className="evidence-full-text">{toText(value)}</div>,
                },
                {
                  title: "来源",
                  dataIndex: "source_title",
                  key: "source_title",
                  width: 180,
                  render: (_, row) => (
                    row.source_url
                      ? <a href={row.source_url} target="_blank" rel="noreferrer">{toText(row.source_title)}</a>
                      : toText(row.source_title)
                  ),
                },
                {
                  title: "置信度",
                  dataIndex: "confidence",
                  key: "confidence",
                  width: 90,
                  render: (value) => Number(value || 0).toFixed(2),
                },
              ]}
            />
          </Card>
        ),
      },
      {
        key: "refs",
        label: `文献 (${(detailDrug.references || []).length})`,
        children: (
          <Card size="small" title={`参考文献 (${(detailDrug.references || []).length})`}>
            <Space direction="vertical" size={8} style={{ width: "100%" }}>
              {(detailDrug.references || []).slice(0, 20).map((ref, idx) => (
                <a key={`${idx}-${ref.url || ref.title}`} href={ref.url} target="_blank" rel="noreferrer">
                  {toText(ref.title)}
                </a>
              ))}
              {(detailDrug.references || []).length === 0 ? <Text type="secondary">暂无</Text> : null}
            </Space>
          </Card>
        ),
      },
    ];
  }, [detailDrug, detailEvidence]);

  const copyCurrentViewLink = useCallback(async () => {
    try {
      await navigator.clipboard.writeText(shareUrl);
      message.success("已复制当前视图链接");
    } catch {
      message.error("复制失败，请手动复制地址栏");
    }
  }, [shareUrl]);

  return (
    <ConfigProvider
      theme={{
        token: {
          colorPrimary: "#1677ff",
          borderRadius: 10,
          fontFamily: "Plus Jakarta Sans, Noto Sans SC, sans-serif",
        },
      }}
    >
      <App>
        <Space direction="vertical" size="large" style={{ width: "100%" }}>
          <Card className="react-hero" bordered={false}>
            <Row justify="center">
              <Col xs={24} md={20} lg={16} className="react-hero-center">
                <Title level={2} style={{ color: "#fff", margin: "0 0 10px", textAlign: "center" }}>
                  药物信息检索中心
                </Title>
                <Paragraph style={{ color: "rgba(255,255,255,0.9)", margin: "0 0 14px", textAlign: "center" }}>
                  支持药物检索、详情查看与证据追踪。
                </Paragraph>

                <Space direction="vertical" size={10} style={{ width: "100%" }} className="react-hero-controls">
                  <Input
                    size="large"
                    placeholder="关键词，例如 aspirin / metformin"
                    value={queryInput}
                    onChange={(e) => setQueryInput(e.target.value)}
                    onPressEnter={() => applySearch(queryInput)}
                  />
                  <Space wrap style={{ width: "100%", justifyContent: "center" }}>
                    <Select
                      style={{ minWidth: 140 }}
                      value={pageSize}
                      onChange={(val) => {
                        setPageSize(val);
                        setPage(1);
                      }}
                      options={[
                        { label: "30 / 页", value: 30 },
                        { label: "50 / 页", value: 50 },
                        { label: "100 / 页", value: 100 },
                        { label: "200 / 页", value: 200 },
                      ]}
                    />
                    <Button
                      type="primary"
                      size="large"
                      onClick={() => applySearch(queryInput)}
                    >
                      检索
                    </Button>
                  </Space>
                  {recentSearches.length > 0 ? (
                    <div className="recent-search-row">
                      <Text type="secondary">最近搜索:</Text>
                      <Space wrap size={[6, 6]}>
                        {recentSearches.map((entry, idx) => (
                          <span key={`${entry.q}-${entry.reviewStatus}-${idx}`} className="recent-item">
                            <Button
                              size="small"
                              onClick={() => applySearch(entry.q)}
                            >
                              {entry.q}
                            </Button>
                            <Button
                              size="small"
                              type="text"
                              danger
                              className="recent-item-remove"
                              onClick={() => {
                                const next = removeSearchHistoryItem(recentSearches, entry);
                                setRecentSearches(next);
                                saveSearchHistory(next);
                              }}
                            >
                              x
                            </Button>
                          </span>
                        ))}
                        <Button
                          size="small"
                          danger
                          onClick={() => {
                            setRecentSearches([]);
                            saveSearchHistory([]);
                          }}
                        >
                          清空
                        </Button>
                      </Space>
                    </div>
                  ) : null}
                </Space>
              </Col>
            </Row>
          </Card>

          <Card
            title="结果列表"
            extra={(
              <Space>
                <Text type="secondary">共 {total} 条，当前展示 {items.length} 条</Text>
                <Popover trigger="click" placement="bottomRight" content={columnChooserContent}>
                  <Button size="small">列设置</Button>
                </Popover>
                <Button size="small" onClick={copyCurrentViewLink}>分享当前视图</Button>
                <Button
                  size="small"
                  onClick={() => {
                    setTableFilters({});
                    setTableSorter({});
                  }}
                >
                  重置排序筛选
                </Button>
              </Space>
            )}
          >
            {errorMsg ? <Alert type="error" showIcon message={`请求失败: ${errorMsg}`} style={{ marginBottom: 12 }} /> : null}

            <Table
              rowKey="id"
              size="middle"
              columns={tableColumns}
              dataSource={items}
              loading={loading}
              pagination={false}
              scroll={{ x: 900 }}
              locale={{ emptyText: loading ? "加载中..." : "没有检索到结果" }}
              onChange={(_, filters, sorter) => {
                setTableFilters(filters || {});
                if (Array.isArray(sorter)) {
                  setTableSorter(sorter[0] || {});
                } else {
                  setTableSorter(sorter || {});
                }
              }}
            />

            <div className="react-pager">
              <Pagination
                current={page}
                pageSize={pageSize}
                total={total}
                showSizeChanger={false}
                showQuickJumper
                onChange={(nextPage) => setPage(nextPage)}
              />
              <Text type="secondary">第 {page} / {totalPages} 页</Text>
            </div>
          </Card>
        </Space>

        <Drawer
          title={detailDrug ? `${detailDrug.generic_name_en}` : "药物详情"}
          placement="right"
          width={820}
          open={detailOpen}
          onClose={() => setDetailOpen(false)}
        >
          {detailLoading ? (
            <div className="detail-spin-wrap">
              <Spin />
            </div>
          ) : null}

          {!detailLoading && detailError ? <Alert type="error" showIcon message={`详情加载失败: ${detailError}`} /> : null}

          {!detailLoading && detailDrug ? <Tabs items={detailTabItems} /> : null}
        </Drawer>
      </App>
    </ConfigProvider>
  );
}

const root = ReactDOM.createRoot(document.getElementById("reactRoot"));
root.render(<ReactDrugSite />);
