import { useState } from 'react';
import { useQuery, useQueryClient } from '@tanstack/react-query';
import type { GatewayKey } from '../../api';
import {
  listGatewayKeys,
  createGatewayKey,
  revokeGatewayKey,
  rotateGatewayKey,
  patchGatewayKey,
} from '../../api';
import { GatewayKeyCreateDialog } from './GatewayKeyCreateDialog';
import { GatewayKeyRawKeyDialog } from './GatewayKeyRawKeyDialog';
import { GatewayKeyUsagePanel } from './GatewayKeyUsagePanel';

interface Props {
  showToast?: (msg: string, variant?: 'success' | 'error') => void;
}

/**
 * Settings → LLM → Gateway Server → Virtual Keys section (Step 8).
 *
 * Renders the Gateway Keys list + create/rotate/revoke actions inline
 * within the Gateway Server form. Previously this lived under its own
 * sidebar entry (`gateway-keys`); the entry was removed in Step 8 because
 * key management is a Gateway Server operation, not a separate concern.
 *
 * List table + actions per row (Detail / Rotate / Revoke). Create
 * dialog issues a fresh sk-aao-* key; the raw value is then surfaced
 * in a one-time reveal dialog with copy + acknowledge gate.
 *
 * Filters: ?team= (text input) and ?activeOnly= (checkbox). Both
 * roundtrip through React Query for cache scoping.
 *
 * Note: this section talks to its own admin REST API (not the global
 * config save flow), so edits here are applied immediately and do not
 * participate in the surrounding form's draft/dirty/Save&Apply bar.
 */
export function GatewayKeysSection({ showToast }: Props) {
  const qc = useQueryClient();
  const [teamFilter, setTeamFilter] = useState('');
  const [activeOnly, setActiveOnly] = useState(false);
  const [creating, setCreating] = useState(false);
  const [createError, setCreateError] = useState<string | null>(null);
  const [createSubmitting, setCreateSubmitting] = useState(false);
  const [rawDialog, setRawDialog] = useState<{ rawKey: string; team: string; reason: 'created' | 'rotated' } | null>(null);
  const [usagePanelId, setUsagePanelId] = useState<string | null>(null);
  const [budgetDraft, setBudgetDraft] = useState<{ id: string; value: string } | null>(null);
  const [rpmDraft, setRpmDraft] = useState<{ id: string; value: string } | null>(null);

  const queryKey = ['gateway-keys', { team: teamFilter || undefined, activeOnly }];
  const { data, isLoading, error, refetch } = useQuery({
    queryKey,
    queryFn: () => listGatewayKeys({ team: teamFilter || undefined, activeOnly }),
    staleTime: 10_000,
  });

  function notify(msg: string, variant: 'success' | 'error' = 'success'): void {
    if (showToast) showToast(msg, variant);
  }

  async function handleCreate(input: {
    team: string;
    allowedModels?: string[];
    tokensBudget?: number | null;
    rateLimitRpm?: number | null;
  }): Promise<void> {
    setCreateSubmitting(true);
    setCreateError(null);
    try {
      const created = await createGatewayKey(input);
      setCreating(false);
      if (created.key) {
        setRawDialog({ rawKey: created.key, team: created.team, reason: 'created' });
      }
      await qc.invalidateQueries({ queryKey: ['gateway-keys'] });
      notify('Gateway key を発行しました');
    } catch (e) {
      setCreateError(e instanceof Error ? e.message : String(e));
    } finally {
      setCreateSubmitting(false);
    }
  }

  async function handleRotate(row: GatewayKey): Promise<void> {
    if (!confirm(`team=${row.team} のキーをローテーションしますか？\n旧キーは無効になります。`)) return;
    try {
      const created = await rotateGatewayKey(row.id);
      if (created.key) {
        setRawDialog({ rawKey: created.key, team: created.team, reason: 'rotated' });
      }
      await qc.invalidateQueries({ queryKey: ['gateway-keys'] });
      notify('Rotate しました');
    } catch (e) {
      notify(e instanceof Error ? e.message : String(e), 'error');
    }
  }

  async function handleRevoke(row: GatewayKey): Promise<void> {
    if (!confirm(`team=${row.team} のキー (${row.keyPrefix}…) を Revoke しますか？\nこの操作は取り消せません。`)) return;
    try {
      await revokeGatewayKey(row.id);
      await qc.invalidateQueries({ queryKey: ['gateway-keys'] });
      notify('Revoke しました');
    } catch (e) {
      notify(e instanceof Error ? e.message : String(e), 'error');
    }
  }

  async function handlePatch(id: string, patch: { tokensBudget?: number | null; rateLimitRpm?: number | null }): Promise<void> {
    try {
      await patchGatewayKey(id, patch);
      await qc.invalidateQueries({ queryKey: ['gateway-keys'] });
      notify('更新しました');
    } catch (e) {
      notify(e instanceof Error ? e.message : String(e), 'error');
    }
  }

  function commitBudget(id: string): void {
    if (!budgetDraft || budgetDraft.id !== id) return;
    const v = budgetDraft.value.trim();
    const parsed = v === '' ? null : Number(v);
    if (parsed !== null && (!Number.isFinite(parsed) || parsed <= 0)) {
      notify('tokens budget must be a positive integer or empty', 'error');
      setBudgetDraft(null);
      return;
    }
    handlePatch(id, { tokensBudget: parsed });
    setBudgetDraft(null);
  }

  function commitRpm(id: string): void {
    if (!rpmDraft || rpmDraft.id !== id) return;
    const v = rpmDraft.value.trim();
    const parsed = v === '' ? null : Number(v);
    if (parsed !== null && (!Number.isFinite(parsed) || parsed <= 0)) {
      notify('rate limit must be a positive integer or empty', 'error');
      setRpmDraft(null);
      return;
    }
    handlePatch(id, { rateLimitRpm: parsed });
    setRpmDraft(null);
  }

  return (
    <div className="space-y-4">
      <div className="flex flex-wrap items-center gap-3">
        <div>
          <label className="block text-xs font-medium text-slate-600 mb-1">Team filter</label>
          <input
            type="text"
            value={teamFilter}
            onChange={(e) => setTeamFilter(e.target.value)}
            placeholder="alpha"
            className="px-2 py-1 text-sm border border-slate-300 rounded"
          />
        </div>
        <label className="flex items-center gap-2 text-sm mt-5 cursor-pointer">
          <input
            type="checkbox"
            checked={activeOnly}
            onChange={(e) => setActiveOnly(e.target.checked)}
          />
          Active only
        </label>
        <button
          type="button"
          onClick={() => refetch()}
          className="ml-auto px-2 py-1 text-xs rounded border border-slate-300 hover:bg-slate-50"
        >
          Refresh
        </button>
        <button
          type="button"
          onClick={() => { setCreateError(null); setCreating(true); }}
          className="px-3 py-1.5 text-sm rounded bg-accent text-white hover:bg-accent-strong"
        >
          + 新規発行
        </button>
      </div>

      <div className="border border-hairline rounded overflow-hidden">
        {isLoading && <div className="p-3 text-sm text-slate-500">Loading…</div>}
        {error && (
          <div className="p-3 text-sm text-red-600">
            取得エラー: {String((error as Error).message ?? error)}
          </div>
        )}
        {data && data.length === 0 && (
          <div className="p-6 text-center text-sm text-slate-400">
            キーが登録されていません。「+ 新規発行」から作成できます。
          </div>
        )}
        {data && data.length > 0 && (
          <table className="w-full text-sm">
            <thead className="bg-slate-50 text-xs uppercase tracking-wide text-slate-500">
              <tr>
                <th className="text-left p-2 font-medium">Prefix</th>
                <th className="text-left p-2 font-medium">Team</th>
                <th className="text-left p-2 font-medium">Models</th>
                <th className="text-right p-2 font-medium">Budget</th>
                <th className="text-right p-2 font-medium">Rpm</th>
                <th className="text-left p-2 font-medium">Source</th>
                <th className="text-left p-2 font-medium">Status</th>
                <th className="text-right p-2 font-medium">Actions</th>
              </tr>
            </thead>
            <tbody>
              {data.map((row) => {
                const isRevoked = row.revokedAt !== null;
                const isConfig = row.source === 'config-import';
                return (
                  <tr
                    key={row.id}
                    className={`border-t border-hairline ${isRevoked ? 'bg-slate-50 text-slate-400' : ''}`}
                  >
                    <td className="p-2 font-mono text-xs">{row.keyPrefix}…</td>
                    <td className="p-2">{row.team}</td>
                    <td className="p-2 text-xs text-slate-500">
                      {row.allowedModels === null
                        ? <span className="text-slate-400 italic">all</span>
                        : row.allowedModels.join(', ')}
                    </td>
                    <td className="p-2 text-right font-mono text-xs">
                      {budgetDraft?.id === row.id ? (
                        <input
                          type="number"
                          autoFocus
                          value={budgetDraft.value}
                          onChange={(e) => setBudgetDraft({ id: row.id, value: e.target.value })}
                          onBlur={() => commitBudget(row.id)}
                          onKeyDown={(e) => {
                            if (e.key === 'Enter') commitBudget(row.id);
                            if (e.key === 'Escape') setBudgetDraft(null);
                          }}
                          className="w-20 px-1 py-0.5 text-xs border border-slate-300 rounded text-right"
                        />
                      ) : (
                        <button
                          type="button"
                          disabled={isRevoked || isConfig}
                          onClick={() => setBudgetDraft({ id: row.id, value: row.tokensBudget?.toString() ?? '' })}
                          className="text-left disabled:cursor-not-allowed hover:underline"
                          title={isConfig ? 'config-import keys は config.yaml で管理' : isRevoked ? 'revoked' : 'click to edit'}
                        >
                          {row.tokensBudget !== null ? row.tokensBudget.toLocaleString() : <span className="text-slate-400">∞</span>}
                        </button>
                      )}
                    </td>
                    <td className="p-2 text-right font-mono text-xs">
                      {rpmDraft?.id === row.id ? (
                        <input
                          type="number"
                          autoFocus
                          value={rpmDraft.value}
                          onChange={(e) => setRpmDraft({ id: row.id, value: e.target.value })}
                          onBlur={() => commitRpm(row.id)}
                          onKeyDown={(e) => {
                            if (e.key === 'Enter') commitRpm(row.id);
                            if (e.key === 'Escape') setRpmDraft(null);
                          }}
                          className="w-16 px-1 py-0.5 text-xs border border-slate-300 rounded text-right"
                        />
                      ) : (
                        <button
                          type="button"
                          disabled={isRevoked || isConfig}
                          onClick={() => setRpmDraft({ id: row.id, value: row.rateLimitRpm?.toString() ?? '' })}
                          className="text-left disabled:cursor-not-allowed hover:underline"
                          title={isConfig ? 'config-import keys は config.yaml で管理' : isRevoked ? 'revoked' : 'click to edit'}
                        >
                          {row.rateLimitRpm !== null ? row.rateLimitRpm.toString() : <span className="text-slate-400">∞</span>}
                        </button>
                      )}
                    </td>
                    <td className="p-2 text-xs">
                      {isConfig ? (
                        <span className="px-1.5 py-0.5 bg-slate-100 rounded text-slate-600">config</span>
                      ) : (
                        <span className="px-1.5 py-0.5 bg-accent-soft rounded text-accent">admin</span>
                      )}
                    </td>
                    <td className="p-2 text-xs">
                      {isRevoked ? (
                        <span className="px-1.5 py-0.5 bg-red-50 text-red-700 rounded">revoked</span>
                      ) : (
                        <span className="px-1.5 py-0.5 bg-green-50 text-green-700 rounded">active</span>
                      )}
                    </td>
                    <td className="p-2 text-right">
                      <div className="flex justify-end gap-1">
                        <button
                          type="button"
                          onClick={() => setUsagePanelId(row.id)}
                          className="px-2 py-0.5 text-xs rounded border border-slate-300 hover:bg-slate-50"
                        >
                          詳細
                        </button>
                        <button
                          type="button"
                          disabled={isRevoked}
                          onClick={() => handleRotate(row)}
                          className="px-2 py-0.5 text-xs rounded border border-slate-300 hover:bg-slate-50 disabled:opacity-40 disabled:cursor-not-allowed"
                        >
                          Rotate
                        </button>
                        <button
                          type="button"
                          disabled={isRevoked}
                          onClick={() => handleRevoke(row)}
                          className="px-2 py-0.5 text-xs rounded border border-red-300 text-red-700 hover:bg-red-50 disabled:opacity-40 disabled:cursor-not-allowed"
                        >
                          Revoke
                        </button>
                      </div>
                    </td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        )}
      </div>

      <div className="text-xs text-slate-500">
        Tokens budget は月次 UTC でリセット。Rate limit (rpm) は 60 秒スライディングウィンドウ。
        config-import のキー（config.yaml から取り込まれたもの）は値の編集ができません。
      </div>

      {creating && (
        <GatewayKeyCreateDialog
          onCancel={() => setCreating(false)}
          onSubmit={handleCreate}
          submitting={createSubmitting}
          error={createError}
        />
      )}
      {rawDialog && (
        <GatewayKeyRawKeyDialog
          rawKey={rawDialog.rawKey}
          team={rawDialog.team}
          reason={rawDialog.reason}
          onClose={() => setRawDialog(null)}
        />
      )}
      {usagePanelId && (
        <GatewayKeyUsagePanel
          keyId={usagePanelId}
          onClose={() => setUsagePanelId(null)}
        />
      )}
    </div>
  );
}
