"use client";

export const dynamic = "force-dynamic";

import { useCallback, useEffect, useState } from "react";
import { Bot, KeyRound, Loader2, Plus, RefreshCw, Server, Trash2, X } from "lucide-react";

import { useAuth } from "@/auth/clerk";
import { DashboardPageLayout } from "@/components/templates/DashboardPageLayout";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { ConfirmActionDialog } from "@/components/ui/confirm-action-dialog";
import { useOrganizationMembership } from "@/lib/use-organization-membership";
import type { ProviderCredentialRead, ProviderUsageLiveRead } from "@/api/generated/model";
import {
  listProviderCredentialsApiV1ProviderCredentialsGet,
  createProviderCredentialApiV1ProviderCredentialsPost,
  updateProviderCredentialApiV1ProviderCredentialsCredentialIdPatch,
  deleteProviderCredentialApiV1ProviderCredentialsCredentialIdDelete,
  getProviderUsageLiveApiV1ProviderCredentialsCredentialIdUsageGet,
} from "@/api/generated/provider-credentials/provider-credentials";

// ---------------------------------------------------------------------------
// Provider metadata
// ---------------------------------------------------------------------------

const PROVIDERS = [
  {
    id: "anthropic",
    label: "Claude (Anthropic)",
    icon: Bot,
    description: "Anthropic Claude API key. Add multiple accounts to track separate keys or billing profiles.",
    keyLabel: "API Key",
    keyPlaceholder: "sk-ant-…",
    showBaseUrl: false,
    allowMultiple: true,
    accountKeyDefault: "default",
  },
  {
    id: "openai",
    label: "Codex / OpenAI",
    icon: Bot,
    description: "OpenAI API key. Add multiple accounts to track usage separately.",
    keyLabel: "API Key",
    keyPlaceholder: "sk-…",
    showBaseUrl: false,
    allowMultiple: true,
    accountKeyDefault: "",
  },
  {
    id: "ollama",
    label: "Ollama",
    icon: Server,
    description: "Ollama instance — local, on-prem, or cloud. Add the base URL; API key only needed for authenticated deployments.",
    keyLabel: "API Key (optional)",
    keyPlaceholder: "Leave blank for unauthenticated",
    showBaseUrl: true,
    allowMultiple: true,
    accountKeyDefault: "default",
  },
] as const;

type ProviderId = (typeof PROVIDERS)[number]["id"];

// ---------------------------------------------------------------------------
// Add/Edit form
// ---------------------------------------------------------------------------

interface CredentialFormProps {
  providerId: ProviderId;
  allowMultiple: boolean;
  showBaseUrl: boolean;
  keyLabel: string;
  keyPlaceholder: string;
  accountKeyDefault: string;
  onSave: (data: {
    account_key: string;
    display_name: string;
    api_key: string;
    base_url: string;
  }) => Promise<void>;
  onCancel: () => void;
  isSaving: boolean;
  error: string | null;
}

function CredentialForm({
  allowMultiple,
  showBaseUrl,
  keyLabel,
  keyPlaceholder,
  accountKeyDefault,
  onSave,
  onCancel,
  isSaving,
  error,
}: CredentialFormProps) {
  const [accountKey, setAccountKey] = useState(accountKeyDefault);
  const [displayName, setDisplayName] = useState("");
  const [apiKey, setApiKey] = useState("");
  const [baseUrl, setBaseUrl] = useState("");

  return (
    <div className="mt-3 rounded-xl border border-[color:var(--border)] bg-[color:var(--surface-muted)] p-4">
      <div className="space-y-3">
        {allowMultiple && (
          <div>
            <label className="mb-1 block text-xs font-medium text-muted">
              Account name <span className="text-[color:var(--danger)]">*</span>
            </label>
            <Input
              value={accountKey}
              onChange={(e) => setAccountKey(e.target.value)}
              placeholder="e.g. work, personal, gpu-box"
              disabled={isSaving}
            />
            <p className="mt-1 text-[11px] text-muted">
              Used to tell accounts apart in cost reports.
            </p>
          </div>
        )}
        <div>
          <label className="mb-1 block text-xs font-medium text-muted">
            Display name (optional)
          </label>
          <Input
            value={displayName}
            onChange={(e) => setDisplayName(e.target.value)}
            placeholder={accountKey || "My account"}
            disabled={isSaving}
          />
        </div>
        {showBaseUrl && (
          <div>
            <label className="mb-1 block text-xs font-medium text-muted">
              Base URL <span className="text-[color:var(--danger)]">*</span>
            </label>
            <Input
              value={baseUrl}
              onChange={(e) => setBaseUrl(e.target.value)}
              placeholder="http://localhost:11434"
              disabled={isSaving}
            />
          </div>
        )}
        <div>
          <label className="mb-1 block text-xs font-medium text-muted">
            {keyLabel}
          </label>
          <Input
            type="password"
            value={apiKey}
            onChange={(e) => setApiKey(e.target.value)}
            placeholder={keyPlaceholder}
            disabled={isSaving}
            autoComplete="new-password"
          />
        </div>
        {error && (
          <p className="text-sm text-[color:var(--danger)]">{error}</p>
        )}
        <div className="flex gap-2">
          <Button
            size="sm"
            disabled={isSaving || !accountKey.trim() || (showBaseUrl && !baseUrl.trim())}
            onClick={() =>
              onSave({ account_key: accountKey.trim(), display_name: displayName.trim(), api_key: apiKey, base_url: baseUrl.trim() })
            }
          >
            {isSaving ? (
              <Loader2 className="mr-1.5 h-3.5 w-3.5 animate-spin" />
            ) : (
              <KeyRound className="mr-1.5 h-3.5 w-3.5" />
            )}
            {isSaving ? "Saving…" : "Save"}
          </Button>
          <Button variant="outline" size="sm" onClick={onCancel} disabled={isSaving}>
            <X className="mr-1.5 h-3.5 w-3.5" />
            Cancel
          </Button>
        </div>
      </div>
    </div>
  );
}

// ---------------------------------------------------------------------------
// Usage strip — live token data fetched from the provider
// ---------------------------------------------------------------------------

function fmtTokens(n: number | null | undefined): string {
  if (n == null) return "—";
  if (n >= 1_000_000) return `${(n / 1_000_000).toFixed(1)}M`;
  if (n >= 1_000) return `${(n / 1_000).toFixed(0)}k`;
  return n.toString();
}

function fmtResetMs(ms: number | null | undefined): string {
  if (ms == null || ms <= 0) return "now";
  const s = Math.floor(ms / 1000);
  if (s < 60) return `${s}s`;
  const m = Math.floor(s / 60);
  if (m < 60) return `${m}m ${s % 60}s`;
  const h = Math.floor(m / 60);
  return `${h}h ${m % 60}m`;
}

function UsageStrip({ credentialId, provider }: { credentialId: string; provider: string }) {
  const [usage, setUsage] = useState<ProviderUsageLiveRead | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [lastFetched, setLastFetched] = useState<Date | null>(null);

  const fetch = useCallback(async (refresh = false) => {
    setLoading(true);
    setError(null);
    try {
      const res = await getProviderUsageLiveApiV1ProviderCredentialsCredentialIdUsageGet(
        credentialId,
        refresh ? { refresh: true } : undefined,
      );
      if (res.status === 200) {
        setUsage(res.data);
        setLastFetched(new Date());
      }
    } catch (err) {
      setError(err instanceof Error ? err.message : "Failed to fetch usage.");
    } finally {
      setLoading(false);
    }
  }, [credentialId]);

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

  if (loading && !usage) {
    return (
      <div className="mt-2 flex items-center gap-2 text-xs text-muted">
        <Loader2 className="h-3 w-3 animate-spin" />
        Fetching live usage…
      </div>
    );
  }

  if (!usage?.reachable) {
    return (
      <div className="mt-2 flex items-center gap-2 text-xs text-[color:var(--danger)]">
        <span>{usage?.error ?? error ?? "Provider unreachable."}</span>
        <button type="button" onClick={() => fetch(true)} className="ml-1 underline hover:opacity-70">
          Retry
        </button>
      </div>
    );
  }

  const tok = usage.tokens;
  const req = usage.requests;
  const isOllama = provider === "ollama";

  return (
    <div className="mt-2 rounded-lg border border-[color:var(--border)] bg-[color:var(--surface)] p-2.5">
      {isOllama ? (
        <div className="flex items-center gap-3 text-xs text-muted">
          <span className="flex items-center gap-1 text-[color:var(--success)]">
            <span className="inline-block h-1.5 w-1.5 rounded-full bg-[color:var(--success)]" />
            Connected
          </span>
          {(usage.models?.length ?? 0) > 0 && (
            <span>{usage.models!.length} model{usage.models!.length !== 1 ? "s" : ""} available</span>
          )}
          <button type="button" onClick={() => fetch(true)} className="ml-auto text-muted hover:text-strong">
            <RefreshCw className={`h-3 w-3 ${loading ? "animate-spin" : ""}`} />
          </button>
        </div>
      ) : (
        <div className="space-y-1.5">
          {/* Tokens */}
          {tok.limit != null ? (
            <div>
              <div className="mb-1 flex items-center justify-between text-[11px]">
                <span className="font-medium text-muted">Tokens</span>
                <span className="tabular-nums text-strong">
                  {fmtTokens(tok.remaining)} / {fmtTokens(tok.limit)} remaining
                  {tok.reset_in_ms != null && (
                    <span className="ml-2 text-muted">· resets in {fmtResetMs(tok.reset_in_ms)}</span>
                  )}
                </span>
              </div>
              {tok.pct_used != null && (
                <div className="h-1.5 overflow-hidden rounded-full bg-[color:var(--surface-strong)]">
                  <div
                    className={`h-full rounded-full transition-all ${
                      tok.pct_used > 90 ? "bg-[color:var(--danger)]" :
                      tok.pct_used > 75 ? "bg-[color:var(--warning)]" :
                      "bg-[color:var(--success)]"
                    }`}
                    style={{ width: `${Math.min(100, tok.pct_used)}%` }}
                  />
                </div>
              )}
            </div>
          ) : null}

          {/* Requests */}
          {req.limit != null ? (
            <div className="flex items-center justify-between text-[11px] text-muted">
              <span>Requests</span>
              <span className="tabular-nums">
                {req.remaining ?? "—"} / {req.limit} remaining
                {req.reset_in_ms != null && (
                  <span className="ml-2">· resets in {fmtResetMs(req.reset_in_ms)}</span>
                )}
              </span>
            </div>
          ) : null}

          {tok.limit == null && req.limit == null && (
            <p className="text-[11px] text-muted">
              Connected — no rate limit headers returned by this key tier.
            </p>
          )}

          <div className="flex items-center justify-between text-[11px] text-muted">
            {lastFetched && <span>Updated {Math.round((Date.now() - lastFetched.getTime()) / 1000)}s ago</span>}
            <button type="button" onClick={() => fetch(true)} className="ml-auto flex items-center gap-1 hover:text-strong">
              <RefreshCw className={`h-3 w-3 ${loading ? "animate-spin" : ""}`} />
              Refresh
            </button>
          </div>
        </div>
      )}
    </div>
  );
}

// ---------------------------------------------------------------------------
// Credential row
// ---------------------------------------------------------------------------

interface CredentialRowProps {
  cred: ProviderCredentialRead;
  isAdmin: boolean;
  onDelete: (cred: ProviderCredentialRead) => void;
  onToggle: (cred: ProviderCredentialRead) => Promise<void>;
  showUsage?: boolean;
}

function CredentialRow({ cred, isAdmin, onDelete, onToggle, showUsage = true }: CredentialRowProps) {
  const [toggling, setToggling] = useState(false);
  return (
    <div
      className={`rounded-lg border px-3 py-2.5 ${
        cred.active
          ? "border-[color:var(--border)] bg-[color:var(--surface-muted)]"
          : "border-[color:var(--border)] bg-[color:var(--surface)] opacity-60"
      }`}
    >
    <div className="flex min-w-0 items-center gap-3">
      <div className="min-w-0 flex-1">
        <p className="truncate text-sm font-medium text-strong">
          {cred.display_name || cred.account_key}
        </p>
        <div className="mt-0.5 flex flex-wrap gap-x-3 gap-y-0 text-[11px] text-muted">
          <span>key: {cred.account_key}</span>
          {cred.has_api_key && cred.api_key_last_four ? (
            <span className="flex items-center gap-1">
              <KeyRound className="h-3 w-3" />
              ••••{cred.api_key_last_four}
            </span>
          ) : cred.has_api_key ? (
            <span className="flex items-center gap-1">
              <KeyRound className="h-3 w-3" />
              set
            </span>
          ) : (
            <span className="text-[color:var(--warning)]">no key</span>
          )}
          {cred.base_url && <span className="truncate max-w-[200px]">{cred.base_url}</span>}
        </div>
      </div>
      {isAdmin && (
        <div className="flex shrink-0 items-center gap-1.5">
          <button
            type="button"
            onClick={async () => {
              setToggling(true);
              await onToggle(cred);
              setToggling(false);
            }}
            disabled={toggling}
            className={`rounded-full px-2 py-0.5 text-[11px] font-medium transition ${
              cred.active
                ? "bg-[color:rgba(52,211,153,0.15)] text-[color:var(--success)] hover:opacity-80"
                : "bg-[color:var(--surface-strong)] text-muted hover:opacity-80"
            }`}
          >
            {toggling ? "…" : cred.active ? "Active" : "Inactive"}
          </button>
          <Button
            variant="ghost"
            size="sm"
            className="h-7 w-7 p-0 text-[color:var(--danger)] hover:bg-[color:var(--danger-soft)]"
            onClick={() => onDelete(cred)}
          >
            <Trash2 className="h-3.5 w-3.5" />
          </Button>
        </div>
      )}
    </div>
    {showUsage && cred.active && (cred.has_api_key || cred.base_url) && (
      <UsageStrip credentialId={cred.id} provider={cred.provider} />
    )}
    </div>
  );
}

// ---------------------------------------------------------------------------
// Provider section
// ---------------------------------------------------------------------------

interface ProviderSectionProps {
  provider: (typeof PROVIDERS)[number];
  credentials: ProviderCredentialRead[];
  isAdmin: boolean;
  onAdd: (providerId: ProviderId, data: { account_key: string; display_name: string; api_key: string; base_url: string }) => Promise<void>;
  onDelete: (cred: ProviderCredentialRead) => void;
  onToggle: (cred: ProviderCredentialRead) => Promise<void>;
}

function ProviderSection({ provider, credentials, isAdmin, onAdd, onDelete, onToggle }: ProviderSectionProps) {
  const Icon = provider.icon;
  const [showForm, setShowForm] = useState(false);
  const [saving, setSaving] = useState(false);
  const [saveError, setSaveError] = useState<string | null>(null);

  const canAdd = isAdmin && (provider.allowMultiple || credentials.length === 0);

  return (
    <section className="rounded-xl border border-[color:var(--border)] bg-[color:var(--surface)] p-4 shadow-lush md:p-5">
      <div className="flex items-start justify-between gap-3">
        <div className="flex min-w-0 items-start gap-3">
          <div className="rounded-lg border border-[color:var(--border)] bg-[color:var(--surface-muted)] p-2 text-[color:var(--accent)] shrink-0">
            <Icon className="h-4 w-4" />
          </div>
          <div className="min-w-0">
            <h2 className="text-base font-semibold text-strong">{provider.label}</h2>
            <p className="mt-0.5 text-sm text-muted">{provider.description}</p>
          </div>
        </div>
        {canAdd && !showForm && (
          <Button
            size="sm"
            variant="outline"
            onClick={() => { setShowForm(true); setSaveError(null); }}
          >
            <Plus className="h-3.5 w-3.5" />
            Add
          </Button>
        )}
      </div>

      {showForm && (
        <CredentialForm
          providerId={provider.id}
          allowMultiple={provider.allowMultiple}
          showBaseUrl={provider.showBaseUrl}
          keyLabel={provider.keyLabel}
          keyPlaceholder={provider.keyPlaceholder}
          accountKeyDefault={provider.accountKeyDefault}
          onSave={async (data) => {
            setSaving(true);
            setSaveError(null);
            try {
              await onAdd(provider.id, data);
              setShowForm(false);
            } catch (err) {
              setSaveError(err instanceof Error ? err.message : "Save failed.");
            } finally {
              setSaving(false);
            }
          }}
          onCancel={() => setShowForm(false)}
          isSaving={saving}
          error={saveError}
        />
      )}

      {credentials.length > 0 && (
        <div className="mt-3 space-y-2">
          {credentials.map((cred) => (
            <CredentialRow
              key={cred.id}
              cred={cred}
              isAdmin={isAdmin}
              onDelete={onDelete}
              onToggle={onToggle}
            />
          ))}
        </div>
      )}

      {credentials.length === 0 && !showForm && (
        <p className="mt-3 text-sm text-muted">
          No {provider.label} accounts configured.
          {isAdmin ? " Click Add to set one up." : ""}
        </p>
      )}
    </section>
  );
}

// ---------------------------------------------------------------------------
// Page
// ---------------------------------------------------------------------------

export default function AIProvidersSettingsPage() {
  const { isSignedIn } = useAuth();
  const { isAdmin } = useOrganizationMembership(isSignedIn);
  const [credentials, setCredentials] = useState<ProviderCredentialRead[]>([]);
  const [isLoading, setIsLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [deleteTarget, setDeleteTarget] = useState<ProviderCredentialRead | null>(null);
  const [isDeleting, setIsDeleting] = useState(false);
  const [deleteError, setDeleteError] = useState<string | null>(null);

  const load = useCallback(async () => {
    try {
      setIsLoading(true);
      const res = await listProviderCredentialsApiV1ProviderCredentialsGet();
      if (res.status === 200) setCredentials(res.data);
      setError(null);
    } catch (err) {
      setError(err instanceof Error ? err.message : "Could not load provider settings.");
    } finally {
      setIsLoading(false);
    }
  }, []);

  useEffect(() => {
    if (isSignedIn) void load();
  }, [isSignedIn, load]);

  const handleAdd = async (
    providerId: ProviderId,
    data: { account_key: string; display_name: string; api_key: string; base_url: string },
  ) => {
    const res = await createProviderCredentialApiV1ProviderCredentialsPost({
      provider: providerId,
      account_key: data.account_key,
      display_name: data.display_name || data.account_key,
      api_key: data.api_key || undefined,
      base_url: data.base_url || undefined,
    });
    if (res.status === 201) {
      setCredentials((prev) => [...prev, res.data]);
    } else {
      throw new Error("Failed to save credential.");
    }
  };

  const handleToggle = async (cred: ProviderCredentialRead) => {
    const res = await updateProviderCredentialApiV1ProviderCredentialsCredentialIdPatch(
      cred.id,
      { active: !cred.active },
    );
    if (res.status === 200) {
      setCredentials((prev) => prev.map((c) => (c.id === cred.id ? res.data : c)));
    }
  };

  const handleDelete = async () => {
    if (!deleteTarget) return;
    setIsDeleting(true);
    setDeleteError(null);
    try {
      await deleteProviderCredentialApiV1ProviderCredentialsCredentialIdDelete(deleteTarget.id);
      setCredentials((prev) => prev.filter((c) => c.id !== deleteTarget.id));
      setDeleteTarget(null);
    } catch (err) {
      setDeleteError(err instanceof Error ? err.message : "Delete failed.");
    } finally {
      setIsDeleting(false);
    }
  };

  return (
    <>
      <DashboardPageLayout
        signedOut={{
          message: "Sign in to manage AI provider settings.",
          forceRedirectUrl: "/settings/ai-providers",
          signUpForceRedirectUrl: "/settings/ai-providers",
        }}
        title="AI Providers"
        description="Configure API keys and endpoints for the AI providers your gateway uses."
      >
        {isLoading ? (
          <div className="flex items-center gap-2 rounded-xl border border-[color:var(--border)] bg-[color:var(--surface)] p-6 text-sm text-muted">
            <Loader2 className="h-4 w-4 animate-spin" />
            Loading provider settings…
          </div>
        ) : error ? (
          <div className="rounded-xl border border-[color:rgba(248,113,113,0.35)] bg-[color:rgba(248,113,113,0.08)] p-4 text-sm text-[color:var(--danger)]">
            {error}
          </div>
        ) : (
          <div className="space-y-4">
            {!isAdmin && (
              <div className="rounded-xl border border-[color:var(--border)] bg-[color:var(--surface-muted)] p-3 text-sm text-muted">
                You can view provider settings. Only org admins can add or change credentials.
              </div>
            )}
            {PROVIDERS.map((provider) => (
              <ProviderSection
                key={provider.id}
                provider={provider}
                credentials={credentials.filter((c) => c.provider === provider.id)}
                isAdmin={isAdmin}
                onAdd={handleAdd}
                onDelete={setDeleteTarget}
                onToggle={handleToggle}
              />
            ))}
          </div>
        )}
      </DashboardPageLayout>

      <ConfirmActionDialog
        open={Boolean(deleteTarget)}
        onOpenChange={(open) => { if (!open) setDeleteTarget(null); }}
        title="Remove provider account"
        description={
          deleteTarget
            ? `Remove "${deleteTarget.display_name || deleteTarget.account_key}" (${deleteTarget.provider})? The stored key will be deleted and cannot be recovered.`
            : ""
        }
        onConfirm={handleDelete}
        isConfirming={isDeleting}
        errorMessage={deleteError}
        confirmLabel="Remove account"
        confirmingLabel="Removing…"
        confirmClassName="bg-destructive text-destructive-foreground hover:bg-destructive/90"
        cancelLabel="Keep it"
      />
    </>
  );
}
