import { useEffect, useRef, useState, type FormEvent } from 'react';
import { CheckCircle2, Link2, RefreshCw, ShieldCheck, Unplug } from 'lucide-react';
import type {
  IdentityConfigurationRevision,
  IdentityConfigurationView,
  IdentityPairingInput,
} from '@easyai-ai-gateway/contracts';
import {
  activateIdentityRevision,
  cancelIdentityPairing,
  disableIdentityConfiguration,
  GatewayApiError,
  getIdentityConfiguration,
  retireIdentityPairingSecurityEventConflict,
  startIdentityPairing,
  updateIdentityRevisionPolicy,
  validateIdentityRevision,
} from '../../api';
import { Badge, Button, Card, CardContent, CardHeader, CardTitle, ConfirmDialog, Input, Label } from '../../components/ui';

const terminalPairingStatuses = new Set(['completed', 'failed', 'expired', 'cancelled']);

export function UnifiedIdentityPanel(props: { token: string }) {
  const [configuration, setConfiguration] = useState<IdentityConfigurationView | null>(null);
  const [form, setForm] = useState<IdentityPairingInput>(defaultPairingInput);
  const [showPairingForm, setShowPairingForm] = useState(false);
  const [localTenantKey, setLocalTenantKey] = useState('default');
  const [legacyJwtEnabled, setLegacyJwtEnabled] = useState(false);
  const [loading, setLoading] = useState(false);
  const [message, setMessage] = useState('');
  const [error, setError] = useState('');
  const [pollError, setPollError] = useState('');
  const [confirmAction, setConfirmAction] = useState<'disable' | 'cancelPairing' | 'retireSecurityEvent' | null>(null);
  const operationInProgress = useRef(false);

  async function refresh() {
    const next = await getIdentityConfiguration(props.token);
    setConfiguration(next);
    setPollError('');
    if (next.draft) {
      setLocalTenantKey(next.draft.localTenantKey);
      setLegacyJwtEnabled(next.draft.legacyJwtEnabled);
    }
    return next;
  }

  useEffect(() => {
    void refresh().catch((caught) => setError(errorMessage(caught, '统一认证配置加载失败')));
  }, [props.token]);

  useEffect(() => {
    const status = configuration?.pairing?.status;
    const cleanupPending = status === 'cancelled' && configuration?.pairing?.cleanupStatus === 'pending';
    if (!status || (terminalPairingStatuses.has(status) && !cleanupPending)) return undefined;
    const timer = window.setInterval(() => {
      void refresh().catch(() => setPollError('统一认证状态自动刷新失败，请点击“刷新”重试。'));
    }, 2000);
    return () => window.clearInterval(timer);
  }, [configuration?.pairing?.cleanupStatus, configuration?.pairing?.status, props.token]);

  async function run(action: () => Promise<unknown>, success: string, runtimeChanged = false) {
    if (operationInProgress.current) return false;
    operationInProgress.current = true;
    setLoading(true);
    setError('');
    setMessage('');
    try {
      return await executeIdentityOperation({
        action,
        onRuntimeChanged: () => window.dispatchEvent(new Event('identity-runtime-changed')),
        onSuccess: setMessage,
        refresh,
        runtimeChanged,
        success,
      });
    } catch (caught) {
      try {
        await refresh();
      } catch {
        // Preserve the original operation error; the manual refresh remains available.
      }
      setError(errorMessage(caught, '统一认证操作失败'));
      if (isStaleIdentityOperation(caught)) setConfirmAction(null);
      return false;
    } finally {
      operationInProgress.current = false;
      setLoading(false);
    }
  }

  async function submitPairing(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();
    const input = { ...form };
    setForm((current) => ({ ...current, onboardingCode: '' }));
    await run(async () => {
      await startIdentityPairing(props.token, input);
      setShowPairingForm(false);
    }, '接入码已领取，正在由 Gateway 后端准备并保存配置。');
  }

  async function saveDraftPolicy() {
    const draft = configuration?.draft;
    if (!draft) return;
    await run(() => updateIdentityRevisionPolicy(props.token, draft.id, draft.version, {
      localTenantKey: localTenantKey.trim(),
      legacyJwtEnabled,
    }), 'Gateway 本地认证策略已保存。');
  }

  async function retireConflictingSecurityEventConnection() {
    const pairing = configuration?.pairing;
    if (!pairing) return false;
    return run(async () => {
      await retireIdentityPairingSecurityEventConflict(props.token, pairing.id, pairing.version);
    }, '现有安全事件连接已进入安全退役；退役完成后本次配对会自动继续。');
  }

  const active = configuration?.active;
  const draft = configuration?.draft;
  const previous = configuration?.previous;
  const pairing = configuration?.pairing;
  const runtime = configuration?.runtime;
  const cleanupPending = pairing?.status === 'cancelled' && pairing.cleanupStatus === 'pending';
  const cleanupCompleted = pairing?.status === 'cancelled' && pairing.cleanupStatus === 'completed';
  const shouldShowPairing = !active && (showPairingForm || !pairing || cleanupCompleted);

  return (
    <section className="pageStack">
      <div className="fileStorageToolbar">
        <div>
          <strong>统一认证</strong>
          <span>使用认证中心生成的一次性接入码完成标准应用配对；Gateway 自动配置 OIDC、Introspection 与可选 SSF。</span>
        </div>
        <div className="fileStorageToolbar">
          <Badge variant={active ? 'success' : 'outline'}>{active ? '已启用' : '未启用'}</Badge>
          <Button type="button" variant="outline" size="sm" disabled={loading} onClick={() => {
            setError('');
            void refresh().catch((caught) => setError(errorMessage(caught, '统一认证配置刷新失败')));
          }}><RefreshCw size={14} />刷新</Button>
        </div>
      </div>

      {(message || error || pollError) && <div className={`formMessage${error || pollError ? ' error' : ''}`} role={error || pollError ? 'alert' : 'status'} aria-live="polite">{error || pollError || message}</div>}

      {active && runtime && (
        <Card>
          <CardHeader>
            <div>
              <CardTitle>当前生效配置</CardTitle>
              <p className="mutedText">Revision {shortID(active.id)} · {active.issuer}</p>
            </div>
            <Badge variant="success"><CheckCircle2 size={13} />Active</Badge>
          </CardHeader>
          <CardContent className="pageStack">
            <div className="identityHealthGrid">
              <IdentityHealth label="OIDC 登录" value={runtime.login} />
              <IdentityHealth label="JIT 用户" value={runtime.jit} />
              <IdentityHealth label="Token Introspection" value={runtime.tokenIntrospection} />
              <IdentityHealth label="SSF 会话撤销" value={runtime.sessionRevocation} />
            </div>
            <RevisionDetails revision={active} />
            <IdentityRuntimeActions
              loading={loading}
              previous={previous ?? null}
              onDisable={() => setConfirmAction('disable')}
              onValidate={() => void run(() => validateIdentityRevision(props.token, active.id, active.version), '当前配置重新验证成功。', true)}
            />
          </CardContent>
        </Card>
      )}

      {pairing && (!terminalPairingStatuses.has(pairing.status) || cleanupPending) && (
        <PairingProgressCard
          pairing={pairing}
          loading={loading}
          onCancel={() => setConfirmAction('cancelPairing')}
          onResolveConnectionConflict={() => setConfirmAction('retireSecurityEvent')}
        />
      )}

      {draft && pairing?.status === 'completed' && (
        <Card>
          <CardHeader>
            <div><CardTitle>待启用配置</CardTitle><p className="mutedText">机器凭据已写入 SecretStore，页面不会显示或保存明文。</p></div>
            <Badge variant={draft.state === 'failed' ? 'destructive' : 'secondary'}>{draft.state}</Badge>
          </CardHeader>
          <CardContent className="pageStack">
            <RevisionDetails revision={draft} />
            {draft.state === 'draft' && (
              <div className="formGrid two">
                <Label>Gateway 本地租户映射<Input value={localTenantKey} onChange={(event) => setLocalTenantKey(event.target.value)} /></Label>
                <label className="identityCheckbox">
                  <input type="checkbox" checked={legacyJwtEnabled} onChange={(event) => setLegacyJwtEnabled(event.target.checked)} />
                  <span><strong>继续兼容 Legacy JWT</strong><small>仅在迁移期确有旧调用方时开启。</small></span>
                </label>
              </div>
            )}
            <div className="fileStorageToolbar">
              {draft.state === 'draft' && <>
                <Button type="button" variant="outline" disabled={loading || !localTenantKey.trim()} onClick={() => void saveDraftPolicy()}>保存本地策略</Button>
                <Button type="button" disabled={loading || !localTenantKey.trim()}
                  onClick={() => void run(() => validateIdentityRevision(props.token, draft.id, draft.version), '统一认证配置验证成功，可以激活。')}>
                  <ShieldCheck size={14} />验证配置
                </Button>
              </>}
              {draft.state === 'validated' && (
                <Button type="button" disabled={loading}
                  onClick={() => void run(() => activateIdentityRevision(props.token, draft.id, draft.version), '统一认证已热切换启用，无需重启。', true)}>
                  <CheckCircle2 size={14} />激活配置
                </Button>
              )}
              {draft.state === 'failed' && <span className="formMessage">验证失败：{draft.lastErrorCategory || 'validation_failed'}。请检查地址和租户后使用新接入码重新配对。</span>}
              <Button type="button" variant="outline" disabled={loading} onClick={() => setConfirmAction('cancelPairing')}>
                放弃此草稿并重新配置
              </Button>
            </div>
          </CardContent>
        </Card>
      )}

      {pairing && terminalPairingStatuses.has(pairing.status) && pairing.status !== 'completed' && !cleanupPending && (
        <div className="fileStorageToolbar">
          <span className="formMessage" role="status">
            {cleanupCompleted ? '旧配对已放弃，临时凭据与本次创建的 SSF 连接已清理。' : `配对${pairing.status === 'expired' ? '已过期' : '失败'}：${pairingFailureMessage(pairing.lastErrorCategory)}。`}
          </span>
          {cleanupCompleted
            ? <Button type="button" variant="outline" onClick={() => setShowPairingForm(true)}>重新配置</Button>
            : <Button type="button" variant="outline" disabled={loading} onClick={() => setConfirmAction('cancelPairing')}>清理并重新配置</Button>}
        </div>
      )}

      {shouldShowPairing && (
        <Card>
          <CardHeader>
            <div><CardTitle>接入认证中心</CardTitle><p className="mutedText">认证中心保持通用 Application 模型；这里仅消费标准 Manifest 和一次性机器凭据。</p></div>
            <Badge variant="outline">接入码 10 分钟有效</Badge>
          </CardHeader>
          <CardContent>
            <form className="formGrid two" onSubmit={(event) => void submitPairing(event)}>
              <Label>Auth Center 地址<Input required value={form.authCenterUrl} onChange={(event) => setForm({ ...form, authCenterUrl: event.target.value })} placeholder="https://auth.example.com" /></Label>
              <Label>一次性接入码<Input required type="password" autoComplete="one-time-code" value={form.onboardingCode} onChange={(event) => setForm({ ...form, onboardingCode: event.target.value })} placeholder="仅本次提交，不写入日志或数据库" /></Label>
              <Label>Gateway API 公网地址<Input required value={form.publicBaseUrl} onChange={(event) => setForm({ ...form, publicBaseUrl: event.target.value })} placeholder="https://api.gateway.example.com" /></Label>
              <Label>Gateway Web 地址<Input required value={form.webBaseUrl} onChange={(event) => setForm({ ...form, webBaseUrl: event.target.value })} placeholder="https://gateway.example.com" /></Label>
              <Label>Gateway 本地租户映射<Input required value={form.localTenantKey} onChange={(event) => setForm({ ...form, localTenantKey: event.target.value })} placeholder="default" /></Label>
              <label className="identityCheckbox">
                <input type="checkbox" checked={form.legacyJwtEnabled} onChange={(event) => setForm({ ...form, legacyJwtEnabled: event.target.checked })} />
                <span><strong>继续兼容 Legacy JWT</strong><small>默认关闭；本地应急管理员登录始终保留。</small></span>
              </label>
              <div className="fileStorageToolbar spanTwo">
                <Button type="submit" disabled={loading || !form.onboardingCode.trim()}><Link2 size={15} />开始安全配对</Button>
              </div>
            </form>
          </CardContent>
        </Card>
      )}

      <ConfirmDialog
        confirmLabel={confirmAction === 'cancelPairing'
          ? '确认放弃'
          : confirmAction === 'retireSecurityEvent'
            ? '确认安全退役'
            : '确认禁用'}
        description={confirmAction === 'cancelPairing'
          ? '系统会封存当前未激活草稿，并异步销毁本地临时凭据和仅由本次配对创建的 SSF 连接。已经完成的远端 Exchange 不会被伪装为已撤销；使用新接入码时会轮换机器凭据。'
          : confirmAction === 'retireSecurityEvent'
            ? '系统将安全退役当前 SSF Stream。退役期间现有统一认证会自动使用 Introspection 降级保护；退役完成后，本次配对会自动创建新的标准连接。'
            : '统一认证将关闭并清理现有 BFF Session；本地应急管理员登录继续可用。'}
        loading={loading}
        open={confirmAction !== null}
        title={confirmAction === 'cancelPairing'
          ? '放弃当前本地配对？'
          : confirmAction === 'retireSecurityEvent'
            ? '安全退役现有 SSF 连接？'
            : '禁用统一认证？'}
        onCancel={() => setConfirmAction(null)}
        onConfirm={async () => {
          let succeeded = false;
          if (confirmAction === 'disable' && active) {
            succeeded = await run(() => disableIdentityConfiguration(props.token, active.version), '统一认证已禁用，本地管理登录继续可用。', true);
          } else if (confirmAction === 'cancelPairing' && pairing) {
            succeeded = await run(() => cancelIdentityPairing(props.token, pairing.id, pairing.version), '已放弃当前草稿，后台正在安全清理临时资源。');
          } else if (confirmAction === 'retireSecurityEvent') {
            succeeded = await retireConflictingSecurityEventConnection();
          }
          if (succeeded) setConfirmAction(null);
        }}
      />
    </section>
  );
}

export function PairingProgressCard({ pairing, loading, onCancel, onResolveConnectionConflict }: {
  pairing: NonNullable<IdentityConfigurationView['pairing']>;
  loading: boolean;
  onCancel: () => void;
  onResolveConnectionConflict?: () => void;
}) {
  const cleaning = pairing.status === 'cancelled' && pairing.cleanupStatus === 'pending';
  const connectionConflict = pairing.lastErrorCategory === 'security_event_connection_conflict';
  const unsafeCredentialHandoff = pairing.lastErrorCategory === 'security_event_credential_handoff_unsafe';
  return (
    <Card>
      <CardContent className="pageStack" aria-busy="true">
        <div className="fileStorageToolbar" role="status" aria-live="polite">
          <div><strong>{cleaning ? '正在清理已放弃的配对' : '正在配对认证中心'}</strong><span>{pairingStatusLabel(pairing.status, pairing.cleanupStatus)}</span></div>
          <Badge variant="secondary">{cleaning ? 'cleanup_pending' : pairing.status}</Badge>
        </div>
        {pairing.lastErrorCategory && (
          <div className="formMessage error" role="alert">
            {pairingFailureMessage(pairing.lastErrorCategory)}（错误分类：{safePairingCategory(pairing.lastErrorCategory)}）。{cleaning
              ? '后台会继续安全清理。'
              : connectionConflict
                ? '此问题不会通过自动重试恢复；请安全退役现有连接，或放弃本次配对。'
                : unsafeCredentialHandoff
                  ? '此问题不会自动恢复；请先在原配置下断开旧连接，或放弃本次配对。'
                : '后台正在自动重试；也可以放弃本次配对后重新配置。'}
          </div>
        )}
        <div className="fileStorageMeta">
          <span>Exchange: {shortID(pairing.remoteExchangeId)}</span>
          <span>有效期至: {new Date(pairing.expiresAt).toLocaleString()}</span>
          {pairing.lastTraceId && <span>Trace ID: {pairing.lastTraceId}</span>}
          {pairing.authCenterAuditId && <span>Auth Center Audit ID: {pairing.authCenterAuditId}</span>}
        </div>
        {!cleaning && <div className="fileStorageToolbar">
          {connectionConflict && <Button type="button" variant="outline" disabled={loading} onClick={onResolveConnectionConflict}>安全退役现有连接</Button>}
          <Button type="button" variant="outline" disabled={loading} onClick={onCancel}>放弃并清理本次配对</Button>
        </div>}
      </CardContent>
    </Card>
  );
}

export function IdentityRuntimeActions({
  loading,
  onDisable,
  onValidate,
  previous,
}: {
  loading: boolean;
  onDisable: () => void;
  onValidate: () => void;
  previous: IdentityConfigurationRevision | null;
}) {
  return (
    <div className="fileStorageToolbar">
      <Button type="button" variant="outline" size="sm" disabled={loading} onClick={onValidate}>
        <RefreshCw size={14} />重新验证
      </Button>
      <span className="mutedText" role="note">
        当前 Active 关联认证中心的 OAuth/SSF 资源；请先禁用统一认证，再使用新接入码重新配置。
      </span>
      {previous && (
        <span className="mutedText" role="note">
          旧版本的远端 OAuth/SSF 资源可能已经变化，不能直接回滚；请使用新的接入码恢复。
        </span>
      )}
      <Button type="button" variant="destructive" size="sm" disabled={loading} onClick={onDisable}>
        <Unplug size={14} />禁用统一认证
      </Button>
    </div>
  );
}

function RevisionDetails({ revision }: { revision: IdentityConfigurationRevision }) {
  return (
    <div className="fileStorageMeta">
      <span>Issuer: {revision.issuer || '等待 Manifest'}</span>
      <span>Audience: {revision.audience || '等待 Manifest'}</span>
      <span>Tenant: {revision.tenantId || '等待 Manifest'}</span>
      <span>本地租户: {revision.localTenantKey}</span>
      <span>登录 Client: {revision.browserClientId || '未启用'}</span>
      <span>服务 Client: {revision.machineClientId || '未启用'}</span>
      <span>能力: {revision.capabilities.map(capabilityLabel).join('、') || '等待 Manifest'}</span>
      <span>Scope: {revision.scopes.join(', ') || '无'}</span>
      {revision.lastTraceId && <span>Trace ID: {revision.lastTraceId}</span>}
      {revision.lastAuditId && <span>Audit ID: {revision.lastAuditId}</span>}
    </div>
  );
}

function IdentityHealth({ label, value }: { label: string; value: string }) {
  const healthy = value === 'healthy' || value === 'push_healthy';
  return <div className="identityHealthItem"><span>{label}</span><Badge variant={healthy ? 'success' : value === 'disabled' ? 'outline' : 'secondary'}>{healthLabel(value)}</Badge></div>;
}

function defaultPairingInput(): IdentityPairingInput {
  const webBaseUrl = typeof window === 'undefined' ? '' : window.location.origin;
  const configuredApiBaseUrl = (import.meta.env.VITE_GATEWAY_API_BASE_URL ?? '').replace(/\/$/, '');
  return {
    authCenterUrl: 'https://auth.51easyai.com',
    onboardingCode: '',
    publicBaseUrl: /^https?:\/\//i.test(configuredApiBaseUrl) ? configuredApiBaseUrl : '',
    webBaseUrl,
    localTenantKey: 'default',
    legacyJwtEnabled: false,
  };
}

function pairingStatusLabel(status: string, cleanupStatus?: string) {
  if (status === 'cancelled' && cleanupStatus === 'pending') return '正在销毁临时凭据并清理由本次 Revision 创建的安全事件连接';
  return ({ metadata_pending: '正在提交回调与 Receiver 地址', preparing: '认证中心正在创建或复用标准资源', ready: '正在领取并保存一次性机器凭据', credentials_saved: '正在建立安全事件能力并确认完成' } as Record<string, string>)[status] ?? status;
}

const pairingFailureMessages: Readonly<Record<string, string>> = {
  security_event_configuration_invalid: '安全事件配置不完整或无效',
  security_event_discovery_failed: '无法获取或校验 SSF Discovery（网络、HTTP、JSON、Issuer 或端点异常）',
  security_event_connection_conflict: '已有安全事件连接与本次接入配置冲突',
  security_event_credential_handoff_unsafe: '旧安全事件连接与本次认证中心或服务 Client 不匹配；系统不会发送旧凭据，请先在原配置下断开旧连接',
  security_event_connection_binding_missing: '安全事件连接尚未建立',
  security_event_connection_binding_unavailable: '安全事件连接状态暂时不可用',
  security_event_connection_binding_invalid: '安全事件连接缺少 Revision 绑定信息',
  security_event_connection_binding_mismatch: '认证中心返回的安全事件 Audience 或连接归属与本次配置不一致',
  security_event_retirement_pending: '现有安全事件连接正在安全退役，完成后本次配对会自动继续',
  security_event_management_token_failed: '服务客户端暂时无法取得安全事件管理 Token',
  security_event_stream_create_failed: '安全事件 Stream 创建失败',
  security_event_stream_response_invalid: '安全事件 Stream 返回内容不符合预期',
  security_event_receiver_activation_failed: 'Gateway 安全事件 Receiver 启动失败',
  security_event_preparation_failed: '安全事件能力准备失败',
  metadata_submission_failed: '业务地址提交失败',
  exchange_status_unavailable: '认证中心资源准备状态暂时不可用',
  credential_delivery_failed: '一次性机器凭据领取或保存失败',
  exchange_expired: '一次性接入 Exchange 已过期',
  remote_exchange_failed: '认证中心未能完成应用资源准备，请结合 Audit ID 排查',
  remote_state_invalid: '认证中心返回了不符合当前流程的 Exchange 状态',
  exchange_completion_failed: 'Gateway 暂时无法确认认证中心 Exchange 已完成',
  cleanup_revision_unavailable: '待清理的统一认证草稿暂时不可用',
  cleanup_security_event_unavailable: '安全事件清理服务暂时不可用',
  cleanup_security_event_retirement_pending: '安全事件 Stream 已断开，正在等待安全退役窗口结束',
  cleanup_security_event_connection_cleanup_failed: '安全事件连接清理暂时失败',
  cleanup_security_event_secret_cleanup_failed: '安全事件临时凭据清理暂时失败',
  cleanup_security_event_failed: '安全事件连接清理暂时失败',
  cleanup_secret_store_failed: '统一认证临时凭据清理暂时失败',
  cleanup_finalize_failed: '清理结果暂时无法确认',
};

export function pairingFailureMessage(category?: string) {
  return pairingFailureMessages[category ?? ''] ?? '统一认证配对步骤暂时失败';
}

function safePairingCategory(category: string) {
  return Object.hasOwn(pairingFailureMessages, category) ? category : 'pairing_step_failed';
}

export function isStaleIdentityOperation(caught: unknown) {
  return caught instanceof GatewayApiError && (caught.details.status === 409 || caught.details.status === 412);
}

export async function executeIdentityOperation(options: {
  action: () => Promise<unknown>;
  onRuntimeChanged: () => void;
  onSuccess: (message: string) => void;
  refresh: () => Promise<unknown>;
  runtimeChanged: boolean;
  success: string;
}) {
  await options.action();
  try {
    await options.refresh();
  } catch (caught) {
    if (!options.runtimeChanged) throw caught;
    const followUp = isIdentityRefreshAuthenticationLoss(caught)
      ? '当前统一认证会话已失效，请重新登录。'
      : '最新状态刷新失败，请稍后点击“刷新”确认。';
    options.onSuccess(`${options.success} 操作已提交；${followUp}`);
    options.onRuntimeChanged();
    return true;
  }
  options.onSuccess(options.success);
  if (options.runtimeChanged) options.onRuntimeChanged();
  return true;
}

function isIdentityRefreshAuthenticationLoss(caught: unknown) {
  return caught instanceof GatewayApiError && caught.details.status === 401;
}

function capabilityLabel(value: string) {
  return ({ oidc_login: 'OIDC 登录', api_access: 'API 验证', token_introspection: 'Token Introspection', machine_to_machine: '机器调用', session_revocation: 'SSF 会话撤销' } as Record<string, string>)[value] ?? value;
}

function healthLabel(value: string) {
  return ({ healthy: '健康', disabled: '未启用', push_healthy: 'Push 健康', introspection_fallback: 'Introspection 降级', bootstrap: '启动保护' } as Record<string, string>)[value] ?? value;
}

function shortID(value: string) { return value ? `${value.slice(0, 8)}…` : '-'; }

function errorMessage(caught: unknown, fallback: string) { return caught instanceof Error ? caught.message : fallback; }
