import { useCallback, useEffect, useState, type ReactNode } from 'react';
import {
  buildPageDataExportUrl,
  closePageDataDataset,
  getPageDataOpsOverview,
  resetPageDataPassword,
  restorePageDataRow,
  revokePageDataTokens,
  savePageDataPolicy,
} from '../api/client';
import type { MindSpacePublishCheck, PageDataOpsOverview } from '../types';

type RowPolicyScope = 'all_rows' | 'own_rows' | 'owner_only';

function formatVisitorsText(visitors: Record<string, 'viewer' | 'editor'> | undefined) {
  return Object.entries(visitors ?? {})
    .map(([userId, role]) => `${userId} ${role}`)
    .join('\n');
}

function parseVisitorsText(text: string) {
  const visitors: Record<string, 'viewer' | 'editor'> = {};
  for (const line of text.split('\n')) {
    const trimmed = line.trim();
    if (!trimmed) continue;
    const match = trimmed.match(/^(\S+)[\s:]+(viewer|editor)$/i);
    if (!match) continue;
    visitors[match[1]] = match[2].toLowerCase() as 'viewer' | 'editor';
  }
  return visitors;
}

type Props = {
  pageId: string;
  pageTitle: string;
  accessMode: MindSpacePublishCheck['accessMode'];
  onClose: () => void;
};

function formatLogTime(value: string) {
  const date = new Date(value);
  if (Number.isNaN(date.getTime())) return value;
  return date.toLocaleString();
}

export function MindSpacePageDataOpsPanel({ pageId, pageTitle, accessMode, onClose }: Props) {
  const [overview, setOverview] = useState<PageDataOpsOverview | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [busyAction, setBusyAction] = useState<string | null>(null);
  const [newPassword, setNewPassword] = useState('');
  const [message, setMessage] = useState<string | null>(null);
  const [defaultVisitorRole, setDefaultVisitorRole] = useState<'deny' | 'viewer' | 'editor'>('deny');
  const [visitorsText, setVisitorsText] = useState('');
  const [rowPolicies, setRowPolicies] = useState<
    Record<string, { scope: RowPolicyScope; ownerColumn: string }>
  >({});

  const syncRoleForm = useCallback((policy: PageDataOpsOverview['policy']) => {
    setDefaultVisitorRole(policy.defaultVisitorRole ?? 'deny');
    setVisitorsText(formatVisitorsText(policy.visitors));
    const next: Record<string, { scope: RowPolicyScope; ownerColumn: string }> = {};
    for (const [name, dataset] of Object.entries(policy.datasets ?? {})) {
      next[name] = {
        scope: dataset.rowPolicy?.scope ?? 'all_rows',
        ownerColumn: dataset.rowPolicy?.ownerColumn ?? 'created_by_user_id',
      };
    }
    setRowPolicies(next);
  }, []);

  const loadOverview = useCallback(async () => {
    setLoading(true);
    setError(null);
    try {
      const next = await getPageDataOpsOverview(pageId);
      setOverview(next);
      syncRoleForm(next.policy);
    } catch (err) {
      const text = err instanceof Error ? err.message : '加载页面数据运维信息失败';
      if (text.includes('policy_not_found') || text.includes('策略未配置')) {
        setOverview(null);
        setError('当前页面尚未配置 Page Data 策略。请让 Agent 注册 dataset 并调用 private_data_set_page_policy。');
      } else {
        setError(text);
      }
    } finally {
      setLoading(false);
    }
  }, [pageId, syncRoleForm]);

  useEffect(() => {
    void loadOverview();
  }, [loadOverview]);

  const runAction = async (key: string, fn: () => Promise<void>) => {
    setBusyAction(key);
    setMessage(null);
    try {
      await fn();
      await loadOverview();
    } catch (err) {
      setMessage(err instanceof Error ? err.message : '操作失败');
    } finally {
      setBusyAction(null);
    }
  };

  const recentDeletions =
    overview?.recentLogs.filter(
      (entry) => entry.action === 'soft_delete' && entry.dataset && entry.rowId != null,
    ) ?? [];

  return (
    <section className="mindspace-page-data-ops-panel">
      <div className="mindspace-page-data-ops-header">
        <div>
          <p className="mindspace-eyebrow">PAGE DATA</p>
          <h3>页面数据运维</h3>
          <small>
            {pageTitle} · 页面 ID {pageId}
          </small>
        </div>
        <button type="button" onClick={onClose}>
          关闭
        </button>
      </div>

      {loading ? <p className="mindspace-page-data-ops-muted">加载中…</p> : null}
      {error ? <p className="mindspace-page-data-ops-error">{error}</p> : null}
      {message ? <p className="mindspace-page-data-ops-message">{message}</p> : null}

      {overview ? (
        <>
          <div className="mindspace-page-data-ops-summary">
            <div>
              <span>访问模式</span>
              <strong>{overview.publication.accessMode}</strong>
            </div>
            <div>
              <span>策略索引</span>
              <strong>{overview.index?.scopeHash ?? '—'}</strong>
            </div>
            <div>
              <span>活跃会话</span>
              <strong>{overview.activeSessionCount}</strong>
            </div>
            <div>
              <span>Dataset 数</span>
              <strong>{overview.datasets.length}</strong>
            </div>
            <div>
              <span>最近提交</span>
              <strong>{overview.recentSubmissions.length}</strong>
            </div>
          </div>

          {overview.unconfiguredDatasets && overview.unconfiguredDatasets.length > 0 ? (
            <div className="mindspace-page-data-ops-section">
              <h4>已注册但未纳入策略的 Dataset</h4>
              <p className="mindspace-page-data-ops-muted">
                {overview.unconfiguredDatasets.map((name) => (
                  <code key={name}>{name}</code>
                )).reduce<ReactNode[]>((acc, node, index) => (
                  index === 0 ? [node] : [...acc, '、', node]
                ), [])}
                {' '}— 需通过 Agent 更新 Page Data 策略后才能公开访问。
              </p>
            </div>
          ) : null}

          {overview.publication.accessMode === 'login_required' ? (
            <div className="mindspace-page-data-ops-section mindspace-page-data-ops-role-editor">
              <h4>登录访问 · 角色与行级策略</h4>
              <label>
                未列名访问者默认角色
                <select
                  value={defaultVisitorRole}
                  disabled={busyAction != null}
                  onChange={(event) =>
                    setDefaultVisitorRole(event.target.value as 'deny' | 'viewer' | 'editor')
                  }
                >
                  <option value="deny">拒绝</option>
                  <option value="viewer">只读 (viewer)</option>
                  <option value="editor">编辑 (editor)</option>
                </select>
              </label>
              <label>
                指定访问者（每行：用户 ID + 空格 + viewer/editor）
                <textarea
                  value={visitorsText}
                  disabled={busyAction != null}
                  rows={4}
                  placeholder={'user-a editor\nuser-b viewer'}
                  onChange={(event) => setVisitorsText(event.target.value)}
                />
              </label>
              {overview.datasets.length > 0 ? (
                <div className="mindspace-page-data-ops-role-datasets">
                  <span>Dataset 行级范围</span>
                  {overview.datasets.map((dataset) => (
                    <div key={dataset.name} className="mindspace-page-data-ops-role-dataset-row">
                      <code>{dataset.name}</code>
                      <select
                        value={rowPolicies[dataset.name]?.scope ?? 'all_rows'}
                        disabled={busyAction != null}
                        onChange={(event) =>
                          setRowPolicies((current) => ({
                            ...current,
                            [dataset.name]: {
                              scope: event.target.value as RowPolicyScope,
                              ownerColumn: current[dataset.name]?.ownerColumn ?? 'created_by_user_id',
                            },
                          }))
                        }
                      >
                        <option value="all_rows">全部行</option>
                        <option value="own_rows">仅自己的行</option>
                        <option value="owner_only">仅 owner</option>
                      </select>
                      {(rowPolicies[dataset.name]?.scope ?? 'all_rows') === 'own_rows' ? (
                        <input
                          value={rowPolicies[dataset.name]?.ownerColumn ?? 'created_by_user_id'}
                          disabled={busyAction != null}
                          placeholder="owner 列名"
                          onChange={(event) =>
                            setRowPolicies((current) => ({
                              ...current,
                              [dataset.name]: {
                                scope: current[dataset.name]?.scope ?? 'own_rows',
                                ownerColumn: event.target.value,
                              },
                            }))
                          }
                        />
                      ) : null}
                    </div>
                  ))}
                </div>
              ) : null}
              <button
                type="button"
                disabled={busyAction != null}
                onClick={() =>
                  void runAction('save-role-policy', async () => {
                    if (!overview?.policy) return;
                    const datasets = { ...overview.policy.datasets };
                    for (const [name, rowPolicy] of Object.entries(rowPolicies)) {
                      if (!datasets[name]) continue;
                      datasets[name] = {
                        ...datasets[name],
                        rowPolicy:
                          rowPolicy.scope === 'all_rows'
                            ? undefined
                            : {
                                scope: rowPolicy.scope,
                                ownerColumn:
                                  rowPolicy.scope === 'own_rows'
                                    ? rowPolicy.ownerColumn.trim() || 'created_by_user_id'
                                    : undefined,
                              },
                      };
                    }
                    await savePageDataPolicy(pageId, {
                      defaultVisitorRole,
                      visitors: parseVisitorsText(visitorsText),
                      datasets,
                    });
                    setMessage('角色与行级策略已保存');
                  })
                }
              >
                {busyAction === 'save-role-policy' ? '保存中…' : '保存角色策略'}
              </button>
            </div>
          ) : null}

          <div className="mindspace-page-data-ops-section">
            <h4>Dataset 状态</h4>
            {overview.datasets.length === 0 ? (
              <p className="mindspace-page-data-ops-muted">策略中尚未声明 dataset。</p>
            ) : (
              <div className="mindspace-page-data-ops-table-wrap">
                <table className="mindspace-page-data-ops-table">
                  <thead>
                    <tr>
                      <th>名称</th>
                      <th>读</th>
                      <th>写</th>
                      <th>更新</th>
                      <th>删除</th>
                      <th>行数</th>
                      <th />
                    </tr>
                  </thead>
                  <tbody>
                    {overview.datasets.map((dataset) => (
                      <tr key={dataset.name}>
                        <td>
                          <code>{dataset.name}</code>
                          {dataset.closed ? <span className="mindspace-page-data-ops-badge">已关闭</span> : null}
                        </td>
                        <td>{dataset.read ? '是' : '否'}</td>
                        <td>{dataset.insert ? '是' : '否'}</td>
                        <td>{dataset.update ? '是' : '否'}</td>
                        <td>{dataset.softDelete ? '是' : '否'}</td>
                        <td>{dataset.stats?.total ?? '—'}</td>
                        <td>
                          <div className="mindspace-page-data-ops-row-actions">
                            {!dataset.closed ? (
                              <button
                                type="button"
                                disabled={busyAction != null}
                                onClick={() =>
                                  void runAction(`close-${dataset.name}`, async () => {
                                    await closePageDataDataset(pageId, dataset.name);
                                    setMessage(`已关闭 dataset：${dataset.name}`);
                                  })
                                }
                              >
                                {busyAction === `close-${dataset.name}` ? '处理中…' : '关闭'}
                              </button>
                            ) : null}
                            <a
                              href={buildPageDataExportUrl(dataset.name, 'json')}
                              target="_blank"
                              rel="noreferrer"
                            >
                              导出 JSON
                            </a>
                            <a
                              href={buildPageDataExportUrl(dataset.name, 'csv')}
                              target="_blank"
                              rel="noreferrer"
                            >
                              导出 CSV
                            </a>
                          </div>
                        </td>
                      </tr>
                    ))}
                  </tbody>
                </table>
              </div>
            )}
          </div>

          <div className="mindspace-page-data-ops-section">
            <h4>最近提交</h4>
            {overview.recentSubmissions.length === 0 ? (
              <p className="mindspace-page-data-ops-muted">暂无公开写入记录。</p>
            ) : (
              <ul className="mindspace-page-data-ops-log-list">
                {overview.recentSubmissions.map((entry, index) => (
                  <li key={`${entry.at}-${entry.rowId ?? index}`}>
                    <span>{formatLogTime(entry.at)}</span>
                    <span>{entry.dataset}</span>
                    <span>#{entry.rowId ?? '—'}</span>
                  </li>
                ))}
              </ul>
            )}
          </div>

          <div className="mindspace-page-data-ops-section">
            <h4>最近操作日志</h4>
            {overview.recentLogs.length === 0 ? (
              <p className="mindspace-page-data-ops-muted">暂无操作日志。</p>
            ) : (
              <ul className="mindspace-page-data-ops-log-list">
                {overview.recentLogs.map((entry, index) => (
                  <li key={`${entry.at}-${entry.action}-${index}`}>
                    <span>{formatLogTime(entry.at)}</span>
                    <span>{entry.action}</span>
                    <span>{entry.dataset ?? '—'}</span>
                    <span>{entry.actor?.role ?? entry.actor?.type ?? '—'}</span>
                  </li>
                ))}
              </ul>
            )}
          </div>

          <div className="mindspace-page-data-ops-actions">
            <button
              type="button"
              disabled={busyAction != null || overview.activeSessionCount === 0}
              onClick={() =>
                void runAction('revoke-all', async () => {
                  const result = await revokePageDataTokens(pageId, { revokeAll: true });
                  setMessage(`已撤销 ${result.revokedCount} 个活跃会话令牌。`);
                })
              }
            >
              {busyAction === 'revoke-all' ? '撤销中…' : '撤销全部数据令牌'}
            </button>

            {accessMode === 'password' ? (
              <div className="mindspace-page-data-ops-password">
                <input
                  type="password"
                  value={newPassword}
                  onChange={(event) => setNewPassword(event.target.value)}
                  placeholder="新页面口令（至少 8 位）"
                  autoComplete="new-password"
                />
                <button
                  type="button"
                  disabled={busyAction != null || newPassword.trim().length < 8}
                  onClick={() =>
                    void runAction('reset-password', async () => {
                      const result = await resetPageDataPassword(pageId, newPassword.trim());
                      setNewPassword('');
                      setMessage(
                        `口令已重置，并撤销 ${result.revokedSessions} 个旧会话。`,
                      );
                    })
                  }
                >
                  {busyAction === 'reset-password' ? '重置中…' : '重置页面口令'}
                </button>
              </div>
            ) : null}
          </div>

          <div className="mindspace-page-data-ops-section">
            <h4>可恢复的软删除记录</h4>
            {recentDeletions.length === 0 ? (
              <p className="mindspace-page-data-ops-muted">最近日志中暂无可恢复记录。</p>
            ) : (
              <ul className="mindspace-page-data-ops-log-list">
                {recentDeletions.map((entry, index) => (
                  <li key={`${entry.at}-restore-${index}`}>
                    <span>{formatLogTime(entry.at)}</span>
                    <span>{entry.dataset}</span>
                    <span>#{entry.rowId}</span>
                    <button
                      type="button"
                      disabled={busyAction != null}
                      onClick={() =>
                        void runAction(`restore-${entry.dataset}-${entry.rowId}`, async () => {
                          if (!entry.dataset || entry.rowId == null) return;
                          await restorePageDataRow(entry.dataset, entry.rowId);
                          setMessage(`已恢复 ${entry.dataset} #${entry.rowId}`);
                        })
                      }
                    >
                      {busyAction === `restore-${entry.dataset}-${entry.rowId}` ? '恢复中…' : '恢复'}
                    </button>
                  </li>
                ))}
              </ul>
            )}
          </div>

          <p className="mindspace-page-data-ops-hint">
            HTML 页面可引入 <code>/assets/page-data-client.js</code>，通过{' '}
            <code>MindSpacePageData.createClient({'{'} pageId {'}'})</code> 调用公开数据 API。
            公开表单提交可配合 Cloudflare Turnstile，调用{' '}
            <code>insertRow(dataset, row, {'{'} turnstileToken {'}'})</code> 传入验证码。
          </p>
        </>
      ) : null}
    </section>
  );
}
