import { ChangeEvent, ReactNode, useEffect, useMemo, useState } from "react";
import { Button } from "../../ui";
import { ConnectionAdapter } from "./mockAdapter";
import { blankConnection, ConnectionConfig, ConnectionRecord, connectionStates, createConnectionId, DiagnosticCategory, DiagnosticResult, maskedSecret, parseImportPreview, toSafeExport, validateConnection } from "./model";

const field = (config: ConnectionConfig, onChange: (next: ConnectionConfig) => void) =>
  <K extends keyof ConnectionConfig>(key: K, value: ConnectionConfig[K]) => onChange({ ...config, [key]: value });

function Section({ title, children }: { title: string; children: ReactNode }) {
  return <fieldset className="connection-section"><legend>{title}</legend>{children}</fieldset>;
}

export function TlsSettings({ config, onChange, developmentMode }: { config: ConnectionConfig; onChange: (next: ConnectionConfig) => void; developmentMode: boolean }) {
  const set = (value: Partial<ConnectionConfig["tls"]>) => onChange({ ...config, tls: { ...config.tls, ...value } });
  return <Section title="TLS / mTLS">
    <label className="check"><input type="checkbox" checked={config.tls.enabled} onChange={(e) => set({ enabled: e.target.checked })} />启用 TLS</label>
    <label>自定义 CA<textarea value={config.tls.customCa} onChange={(e) => set({ customCa: e.target.value })} placeholder="PEM 内容（仅保存在内存）" /></label>
    <label>客户端证书<textarea value={config.tls.clientCertificate} onChange={(e) => set({ clientCertificate: e.target.value })} /></label>
    <label>客户端私钥<input type="password" autoComplete="off" value={config.tls.clientKey} onChange={(e) => set({ clientKey: e.target.value })} /></label>
    <label>证书指纹<input value={config.tls.fingerprint} onChange={(e) => set({ fingerprint: e.target.value })} placeholder="sha256:…" /></label>
    <label>SNI<input value={config.tls.sni} onChange={(e) => set({ sni: e.target.value })} /></label>
    {developmentMode && <label className="check danger"><input type="checkbox" checked={config.tls.skipVerification} onChange={(e) => set({ skipVerification: e.target.checked })} />跳过证书校验（仅开发模式，不安全）</label>}
  </Section>;
}

export function AuthSettings({ config, onChange }: { config: ConnectionConfig; onChange: (next: ConnectionConfig) => void }) {
  const set = (value: Partial<ConnectionConfig["auth"]>) => onChange({ ...config, auth: { ...config.auth, ...value } });
  return <Section title="认证">
    <label>方式<select value={config.auth.method} onChange={(e) => set({ method: e.target.value as ConnectionConfig["auth"]["method"] })}><option value="token">Token</option><option value="password">用户名 / 密码</option><option value="mtls">仅 mTLS</option></select></label>
    {config.auth.method === "password" && <label>用户名<input value={config.auth.username} onChange={(e) => set({ username: e.target.value })} /></label>}
    {config.auth.method !== "mtls" && <label>秘密<input aria-label="认证秘密" type="password" autoComplete="new-password" value={config.auth.secret} onChange={(e) => set({ secret: e.target.value })} placeholder={maskedSecret(config.auth.secret)} /></label>}
  </Section>;
}

export function ProxySettings({ config, onChange }: { config: ConnectionConfig; onChange: (next: ConnectionConfig) => void }) {
  const set = (value: Partial<ConnectionConfig["proxy"]>) => onChange({ ...config, proxy: { ...config.proxy, ...value } });
  return <Section title="代理">
    <label className="check"><input type="checkbox" checked={config.proxy.enabled} onChange={(e) => set({ enabled: e.target.checked })} />使用代理</label>
    {config.proxy.enabled && <><label>代理 URL<input value={config.proxy.url} onChange={(e) => set({ url: e.target.value })} placeholder="http://proxy.local:8080" /></label><label>代理用户名<input value={config.proxy.username} onChange={(e) => set({ username: e.target.value })} /></label><label>代理密码<input type="password" autoComplete="new-password" value={config.proxy.password} onChange={(e) => set({ password: e.target.value })} /></label></>}
  </Section>;
}

export function ReconnectPolicy({ config, onChange }: { config: ConnectionConfig; onChange: (next: ConnectionConfig) => void }) {
  const set = (value: Partial<ConnectionConfig["reconnect"]>) => onChange({ ...config, reconnect: { ...config.reconnect, ...value } });
  return <Section title="重连策略">
    <label className="check"><input type="checkbox" checked={config.reconnect.enabled} onChange={(e) => set({ enabled: e.target.checked })} />指数退避重连</label>
    <label>初始退避（秒）<input type="number" value={config.reconnect.initialSeconds} onChange={(e) => set({ initialSeconds: Number(e.target.value) })} /></label>
    <label>最大退避（秒）<input type="number" value={config.reconnect.maxSeconds} onChange={(e) => set({ maxSeconds: Number(e.target.value) })} /></label>
    <label>倍率<input type="number" step="0.1" value={config.reconnect.multiplier} onChange={(e) => set({ multiplier: Number(e.target.value) })} /></label>
    <label>抖动（0–1）<input type="number" step="0.1" value={config.reconnect.jitter} onChange={(e) => set({ jitter: Number(e.target.value) })} /></label>
  </Section>;
}

export function ConnectionEditor({ initial, developmentMode = false, existingAddresses = [], onSave, onCancel }: { initial?: ConnectionConfig; developmentMode?: boolean; existingAddresses?: string[]; onSave: (config: ConnectionConfig) => void | Promise<void>; onCancel: () => void }) {
  const [config, setConfig] = useState(() => structuredClone(initial ?? blankConnection()));
  const [submitted, setSubmitted] = useState(false);
  const [saving, setSaving] = useState(false);
  const [saveError, setSaveError] = useState("");
  const errors = useMemo(() => { const next = validateConnection(config, developmentMode); if (existingAddresses.some((address) => address === config.address.trim() && config.address.trim())) next.address = "该 Teamserver 地址已存在"; return next; }, [config, developmentMode, existingAddresses]);
  const set = field(config, setConfig);
  return <form className="connection-editor" onSubmit={async (e) => { e.preventDefault(); setSubmitted(true); setSaveError(""); if (Object.keys(errors).length) return; setSaving(true); try { await onSave(config); } catch (error) { setSaveError(error instanceof Error ? error.message : "保存失败，请重试"); } finally { setSaving(false); } }}>
    <div className="editor-grid"><Section title="基本设置">
      <label>名称<input value={config.name} onChange={(e) => set("name", e.target.value)} />{submitted && errors.name && <small className="field-error">{errors.name}</small>}</label>
      <label>传输<select value={config.transport} onChange={(e) => set("transport", e.target.value as ConnectionConfig["transport"])}><option value="grpc">gRPC</option><option value="websocket">WebSocket</option></select></label>
      <label>地址<input value={config.address} onChange={(e) => set("address", e.target.value)} placeholder={config.transport === "grpc" ? "https://teamserver.example" : "wss://teamserver.example/events"} />{submitted && errors.address && <small className="field-error">{errors.address}</small>}</label>
      <label>请求超时（秒）<input type="number" value={config.timeoutSeconds} onChange={(e) => set("timeoutSeconds", Number(e.target.value))} /></label>
      <label>心跳（秒）<input type="number" value={config.heartbeatSeconds} onChange={(e) => set("heartbeatSeconds", Number(e.target.value))} /></label>
    </Section><TlsSettings config={config} onChange={setConfig} developmentMode={developmentMode} /><AuthSettings config={config} onChange={setConfig} /><ProxySettings config={config} onChange={setConfig} /><ReconnectPolicy config={config} onChange={setConfig} /></div>
    {submitted && Object.keys(errors).length > 0 && <p role="alert" className="form-error">请修正 {Object.keys(errors).length} 项配置错误</p>}{saveError && <p role="alert" className="form-error">{saveError}</p>}
    <footer><Button type="button" onClick={onCancel} disabled={saving}>取消</Button><Button intent="primary" loading={saving} type="submit">保存到内存</Button></footer>
  </form>;
}

export function ConnectionList({ records, selectedId, onSelect, onCreate, onCopy, onExport, onDelete }: { records: ConnectionRecord[]; selectedId?: string; onSelect: (id: string) => void; onCreate: () => void; onCopy: (record: ConnectionRecord) => void; onExport: (record: ConnectionRecord) => void; onDelete: (record: ConnectionRecord) => void }) {
  return <section className="connection-list" aria-label="连接配置列表"><header><div><h2>连接中心</h2><p>{records.length} 个内存配置 · Mock adapter</p></div><button className="primary" onClick={onCreate}>＋ 新建连接</button></header>
    <div className="state-legend" aria-label="连接状态机">{connectionStates.map((state) => <span key={state}>{state}</span>)}</div>
    {records.length === 0 ? <div className="empty-state">尚无连接配置。配置仅保存在当前进程内存。</div> : records.map((record) => <article key={record.config.id} className={selectedId === record.config.id ? "selected" : ""} onClick={() => onSelect(record.config.id)}>
      <div><strong>{record.config.name}</strong><code>{record.config.address}</code></div><span className={`connection-state ${record.state.toLowerCase()}`}>{record.state}</span>
      <div className="record-actions"><button onClick={(e) => { e.stopPropagation(); onCopy(record); }}>复制</button><button onClick={(e) => { e.stopPropagation(); onExport(record); }}>安全导出</button><button className="danger-button" onClick={(e) => { e.stopPropagation(); onDelete(record); }}>删除</button></div>
    </article>)}</section>;
}

const categories: DiagnosticCategory[] = ["network", "tls", "authentication", "version", "permission", "rate_limit", "timeout", "message_format", "server"];
export function ConnectionDiagnostics({ record, adapter }: { record: ConnectionRecord; adapter: ConnectionAdapter }) {
  const [results, setResults] = useState<DiagnosticResult[]>([]);
  return <section className="diagnostics"><h3>连接诊断</h3><p>仅检查 mock 配置结构，不向地址发送请求。</p><button className="secondary" onClick={async () => setResults(await Promise.all(categories.map((category) => adapter.diagnose(record.config.id, category))))}>运行安全诊断</button><div>{results.map((result) => <output key={result.category}><b>{result.category}</b><span>{result.summary}</span></output>)}</div></section>;
}

export function DeleteConfirmation({ record, onConfirm, onCancel }: { record: ConnectionRecord; onConfirm: () => void; onCancel: () => void }) {
  return <div className="modal-backdrop" role="presentation"><section role="dialog" aria-modal="true" aria-labelledby="delete-title" className="connection-dialog"><h3 id="delete-title">删除“{record.config.name}”？</h3><p>仅移除当前进程中的 mock 配置，不会联系 Teamserver。</p><footer><button className="secondary" onClick={onCancel}>取消</button><button className="danger-button" onClick={onConfirm}>确认删除</button></footer></section></div>;
}

export function ConnectionCenter({ adapter, developmentMode = false }: { adapter: ConnectionAdapter; developmentMode?: boolean }) {
  const [records, setRecords] = useState<ConnectionRecord[]>([]);
  const [editing, setEditing] = useState<ConnectionConfig>();
  const [selected, setSelected] = useState<string>();
  const [deleting, setDeleting] = useState<ConnectionRecord>();
  const [importText, setImportText] = useState("");
  const [notice, setNotice] = useState("");
  useEffect(() => { void adapter.list().then(setRecords); }, [adapter]);
  const refresh = () => adapter.list().then(setRecords);
  const selectedRecord = records.find((item) => item.config.id === selected);
  const importPreview = () => { try { setEditing(parseImportPreview(importText)); setNotice("导入预览已加载；秘密字段已清空，保存前请确认。"); } catch (error) { setNotice(error instanceof Error ? error.message : "导入失败"); } };
  const exportRecord = (record: ConnectionRecord) => { const safe = JSON.stringify(toSafeExport(record.config), null, 2); setNotice(`安全导出预览（不含 Token、密码和客户端私钥）：\n${safe}`); };
  if (editing) return <ConnectionEditor initial={editing} developmentMode={developmentMode} onCancel={() => setEditing(undefined)} onSave={async (config) => { await adapter.save(config); await refresh(); setSelected(config.id); setEditing(undefined); setNotice("配置已保存到内存 mock adapter；尚未建立网络连接。"); }} />;
  return <div className="connection-center"><ConnectionList records={records} selectedId={selected} onSelect={setSelected} onCreate={() => setEditing(blankConnection())} onCopy={(record) => setEditing({ ...structuredClone(record.config), id: createConnectionId(), name: `${record.config.name} 副本`, auth: { ...record.config.auth, secret: "" }, proxy: { ...record.config.proxy, password: "" }, tls: { ...record.config.tls, clientKey: "" } })} onExport={exportRecord} onDelete={setDeleting} />
    <section className="import-panel"><h3>导入预览</h3><textarea aria-label="导入 JSON" value={importText} onChange={(e: ChangeEvent<HTMLTextAreaElement>) => setImportText(e.target.value)} placeholder="粘贴由本客户端安全导出的 JSON" /><button className="secondary" onClick={importPreview}>验证并预览</button></section>
    {selectedRecord && <ConnectionDiagnostics record={selectedRecord} adapter={adapter} />}
    {notice && <pre className="connection-notice" aria-live="polite">{notice}</pre>}
    {deleting && <DeleteConfirmation record={deleting} onCancel={() => setDeleting(undefined)} onConfirm={async () => { await adapter.remove(deleting.config.id); await refresh(); setDeleting(undefined); if (selected === deleting.config.id) setSelected(undefined); }} />}
  </div>;
}
