"use client";

import { useCallback, useEffect, useMemo, useState } from "react";
import { ChevronDown } from "lucide-react";

import { useAuth } from "@/auth/clerk";
import type {
  ProviderCredentialRead,
  ProviderUsageLiveRead,
  SubscriptionWindowRead,
} from "@/api/generated/model";
import {
  getProviderUsageLiveApiV1ProviderCredentialsCredentialIdUsageGet,
  listProviderCredentialsApiV1ProviderCredentialsGet,
} from "@/api/generated/provider-credentials/provider-credentials";
import {
  Popover,
  PopoverContent,
  PopoverTrigger,
} from "@/components/ui/popover";

type NavbarProviderId = "anthropic" | "openai";

type ProviderNavbarItem = {
  providerId: NavbarProviderId;
  label: string;
  status: "Active" | "Inactive" | "Not configured" | "Syncing";
  sessionRemaining: number | null;
  modelsRemaining: number | null;
  reset: string;
};

const NAVBAR_PROVIDER_IDS: NavbarProviderId[] = ["anthropic", "openai"];

function providerShortLabel(provider: string): string {
  if (provider === "anthropic") return "Claude";
  if (provider === "openai") return "GPT";
  return provider;
}

function clampPct(pct: number): number {
  return Math.max(0, Math.min(100, pct));
}

function fmtResetMs(ms: number | null | undefined): string {
  if (ms == null || ms <= 0) return "< 1m";
  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 remainingPct(window: SubscriptionWindowRead | null): number | null {
  if (!window) return null;
  return clampPct(100 - window.pct_used);
}

function remainingColor(pct: number | null): string {
  if (pct == null) return "bg-[color:var(--text-quiet)]";
  if (pct <= 10) return "bg-[color:var(--danger)]";
  if (pct <= 25) return "bg-[color:var(--warning)]";
  return "bg-[color:var(--success)]";
}

function findSessionWindow(usage: ProviderUsageLiveRead | null | undefined) {
  const windows = usage?.subscription_windows ?? [];
  return (
    windows.find((window) => {
      const key = `${window.key} ${window.label}`.toLowerCase();
      return (
        key.includes("current") ||
        key.includes("session") ||
        key.includes("five") ||
        key.includes("hour")
      );
    }) ??
    windows[0] ??
    null
  );
}

function findModelsWindow(
  usage: ProviderUsageLiveRead | null | undefined,
  sessionWindow: SubscriptionWindowRead | null,
) {
  const windows = usage?.subscription_windows ?? [];
  return (
    windows.find((window) => {
      if (window.key === sessionWindow?.key) return false;
      const key = `${window.key} ${window.label}`.toLowerCase();
      return key.includes("all") || key.includes("model") || key.includes("week");
    }) ??
    windows.find((window) => window.key !== sessionWindow?.key) ??
    null
  );
}

function resetLabel(
  sessionWindow: SubscriptionWindowRead | null,
  modelsWindow: SubscriptionWindowRead | null,
): string {
  const resetInMs = sessionWindow?.reset_in_ms ?? modelsWindow?.reset_in_ms;
  return resetInMs == null ? "-" : fmtResetMs(resetInMs);
}

function formatRemaining(pct: number | null): string {
  return pct == null ? "-" : `${Math.round(pct)}% left`;
}

function providerStatusColor(status: ProviderNavbarItem["status"]): string {
  if (status === "Active") return "bg-[color:var(--success)]";
  if (status === "Syncing") return "bg-[color:var(--accent)]";
  if (status === "Inactive") return "bg-[color:var(--warning)]";
  return "bg-[color:var(--text-quiet)]";
}

function MiniRemainingBar({
  pct,
  className = "w-10",
}: {
  pct: number | null;
  className?: string;
}) {
  if (pct == null) return null;
  const width = clampPct(pct);
  return (
    <span
      className={`h-1 overflow-hidden rounded-full bg-[color:var(--surface-strong)] ${className}`}
      aria-hidden="true"
    >
      <span
        className={`block h-full rounded-full ${remainingColor(pct)}`}
        style={{ width: `${width}%` }}
      />
    </span>
  );
}

function buildProviderNavbarItems({
  credentials,
  usageByCredentialId,
  isLoading,
}: {
  credentials: ProviderCredentialRead[];
  usageByCredentialId: Record<string, ProviderUsageLiveRead | null>;
  isLoading: boolean;
}): ProviderNavbarItem[] {
  return NAVBAR_PROVIDER_IDS.map((providerId) => {
    const providerCredentials = credentials
      .filter((cred) => cred.provider === providerId)
      .sort((a, b) => a.account_key.localeCompare(b.account_key));
    const activeCredential =
      providerCredentials.find(
        (cred) =>
          cred.active &&
          (cred.has_api_key || cred.has_session_key || Boolean(cred.base_url)),
      ) ?? null;
    const credential = activeCredential ?? providerCredentials[0] ?? null;
    const usage = activeCredential
      ? usageByCredentialId[activeCredential.id]
      : null;
    const status: ProviderNavbarItem["status"] = activeCredential
      ? isLoading && usage == null
        ? "Syncing"
        : "Active"
      : credential
        ? "Inactive"
        : "Not configured";
    const sessionWindow = findSessionWindow(usage);
    const modelsWindow = findModelsWindow(usage, sessionWindow);
    const sessionRemaining = remainingPct(sessionWindow);
    const modelsRemaining = remainingPct(modelsWindow);

    return {
      providerId,
      label: providerShortLabel(providerId),
      status,
      sessionRemaining,
      modelsRemaining,
      reset: resetLabel(sessionWindow, modelsWindow),
    };
  });
}

function ProviderInlineStatus({
  item,
  compact = false,
}: {
  item: ProviderNavbarItem;
  compact?: boolean;
}) {
  return (
    <div
      className={`flex min-w-0 items-center ${
        compact ? "flex-wrap gap-x-2 gap-y-1" : "gap-1.5 whitespace-nowrap"
      }`}
    >
      <span
        className={`h-1.5 w-1.5 shrink-0 rounded-full ${providerStatusColor(item.status)}`}
      />
      <span className="font-semibold text-[color:var(--text)]">{item.label}</span>
      <span className="text-[color:var(--text-muted)]">{item.status}</span>
      <span className="text-[color:var(--text-quiet)]">|</span>
      <span className="text-[color:var(--text-muted)]">
        Session{" "}
        <span className="tabular-nums text-[color:var(--text)]">
          {formatRemaining(item.sessionRemaining)}
        </span>
      </span>
      <MiniRemainingBar pct={item.sessionRemaining} className="w-8 opacity-80" />
      <span className="text-[color:var(--text-quiet)]">|</span>
      <span className="text-[color:var(--text-muted)]">
        Models{" "}
        <span className="tabular-nums text-[color:var(--text)]">
          {formatRemaining(item.modelsRemaining)}
        </span>
      </span>
      <MiniRemainingBar pct={item.modelsRemaining} className="w-8 opacity-80" />
      <span className="text-[color:var(--text-quiet)]">|</span>
      <span className="text-[color:var(--text-muted)]">
        Reset <span className="tabular-nums text-[color:var(--text)]">{item.reset}</span>
      </span>
    </div>
  );
}

export function ProviderNavbarStatus() {
  const { isSignedIn } = useAuth();
  const [credentials, setCredentials] = useState<ProviderCredentialRead[]>([]);
  const [usageByCredentialId, setUsageByCredentialId] = useState<
    Record<string, ProviderUsageLiveRead | null>
  >({});
  const [isUsageLoading, setIsUsageLoading] = useState(false);

  const usageCredentials = useMemo(() => {
    return credentials
      .filter(
        (cred) =>
          NAVBAR_PROVIDER_IDS.includes(cred.provider as NavbarProviderId) &&
          cred.active &&
          (cred.has_api_key || cred.has_session_key || Boolean(cred.base_url)),
      )
      .sort((a, b) => {
        const providerDelta =
          NAVBAR_PROVIDER_IDS.indexOf(a.provider as NavbarProviderId) -
          NAVBAR_PROVIDER_IDS.indexOf(b.provider as NavbarProviderId);
        if (providerDelta !== 0) return providerDelta;
        return a.account_key.localeCompare(b.account_key);
      });
  }, [credentials]);

  const loadCredentials = useCallback(async () => {
    try {
      const res = await listProviderCredentialsApiV1ProviderCredentialsGet();
      if (res.status === 200) setCredentials(res.data);
    } catch {
      setCredentials([]);
    }
  }, []);

  useEffect(() => {
    if (!isSignedIn) return;

    const initialLoad = window.setTimeout(() => {
      void loadCredentials();
    }, 0);
    window.addEventListener("provider-credentials-updated", loadCredentials);
    const interval = window.setInterval(() => {
      void loadCredentials();
    }, 60_000);

    return () => {
      window.clearTimeout(initialLoad);
      window.removeEventListener("provider-credentials-updated", loadCredentials);
      window.clearInterval(interval);
    };
  }, [isSignedIn, loadCredentials]);

  useEffect(() => {
    if (!isSignedIn || usageCredentials.length === 0) {
      const resetUsage = window.setTimeout(() => {
        setUsageByCredentialId({});
        setIsUsageLoading(false);
      }, 0);
      return () => window.clearTimeout(resetUsage);
    }

    let cancelled = false;
    const fetchUsage = async (refresh = false) => {
      setIsUsageLoading(true);
      const pairs = await Promise.all(
        usageCredentials.map(async (cred) => {
          try {
            const res = await getProviderUsageLiveApiV1ProviderCredentialsCredentialIdUsageGet(
              cred.id,
              refresh ? { refresh: true } : undefined,
            );
            return [cred.id, res.status === 200 ? res.data : null] as const;
          } catch {
            return [cred.id, null] as const;
          }
        }),
      );
      if (!cancelled) {
        setUsageByCredentialId(Object.fromEntries(pairs));
        setIsUsageLoading(false);
      }
    };

    const initialFetch = window.setTimeout(() => {
      void fetchUsage();
    }, 0);
    const interval = window.setInterval(() => {
      void fetchUsage(true);
    }, 60_000);

    return () => {
      cancelled = true;
      window.clearTimeout(initialFetch);
      window.clearInterval(interval);
    };
  }, [isSignedIn, usageCredentials]);

  const items = buildProviderNavbarItems({
    credentials,
    usageByCredentialId,
    isLoading: isUsageLoading,
  });
  const activeCount = items.filter(
    (item) => item.status === "Active" || item.status === "Syncing",
  ).length;
  const primaryRemaining =
    items
      .flatMap((item) => [item.sessionRemaining, item.modelsRemaining])
      .filter((pct): pct is number => pct != null)
      .sort((a, b) => a - b)[0] ?? null;

  return (
    <div className="flex h-9 min-w-0 items-center text-[11px]">
      <div className="hidden h-9 min-w-0 items-center gap-2 overflow-hidden xl:flex">
        {items.map((item, index) => (
          <div key={item.providerId} className="flex min-w-0 items-center gap-2">
            {index > 0 ? (
              <span className="h-3.5 w-px shrink-0 bg-[color:var(--border)]" />
            ) : null}
            <ProviderInlineStatus item={item} />
          </div>
        ))}
      </div>
      <Popover>
        <PopoverTrigger asChild>
          <button
            type="button"
            className="flex h-8 min-w-0 max-w-[42vw] items-center gap-2 text-[11px] font-medium text-[color:var(--text-muted)] transition hover:text-[color:var(--text)] xl:hidden"
            aria-label="Open provider status summary"
          >
            <span
              className={`h-1.5 w-1.5 shrink-0 rounded-full ${
                activeCount > 0
                  ? "bg-[color:var(--success)]"
                  : "bg-[color:var(--text-quiet)]"
              }`}
            />
            <span className="truncate">Providers {activeCount} active</span>
            <MiniRemainingBar pct={primaryRemaining} className="w-10 shrink-0 opacity-80" />
            <span className="shrink-0 tabular-nums">
              {formatRemaining(primaryRemaining)}
            </span>
            <ChevronDown className="h-3 w-3 shrink-0" />
          </button>
        </PopoverTrigger>
        <PopoverContent
          align="center"
          sideOffset={10}
          className="w-[min(420px,calc(100vw-2rem))] rounded-xl border border-[color:var(--border)] bg-[color:var(--surface)] p-3 shadow-xl"
        >
          <div className="space-y-2 text-[11px]">
            {items.map((item) => (
              <ProviderInlineStatus key={item.providerId} item={item} compact />
            ))}
          </div>
        </PopoverContent>
      </Popover>
    </div>
  );
}
