"use client";

import { useMemo, useState } from "react";
import {
  addOriginToTrustedOrigins,
  buildTrustedOriginsEnvLine,
  parseTrustedOrigins,
} from "athena-auth-js";
import { getAuthApiOrigin, getAuthBasePath } from "../lib/auth-env";
import { Badge } from "./ui/badge";
import { Button } from "./ui/button";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "./ui/card";
import { Input } from "./ui/input";
import { Label } from "./ui/label";

type SocialProviderRuntime = {
  provider: string;
  label: string;
  enabledByList: boolean;
  clientIdSet: boolean;
  clientSecretSet: boolean;
  ready: boolean;
};

type RuntimeConfig = {
  defaultApiOrigin?: string | null;
  authBasePath?: string;
  upstreamAuthOrigin?: string | null;
  proxyUpstream?: {
    ok: boolean;
    source?: string;
    raw?: string;
    resolved?: string;
    code?: string;
    message?: string;
    details?: Record<string, unknown>;
  };
  trustedOrigins?: string[];
  trustedOriginsRaw?: string;
  smtpConfigured?: boolean;
  smtpConfigurationError?: string | null;
  smtpFromAddressConfigured?: boolean;
  emailDeliveryEvidence?: string;
  social?: {
    configuredProvidersRaw?: string;
    configuredProviders?: string[];
    unknownProviders?: string[];
    callbackPath?: string;
    providers?: SocialProviderRuntime[];
    readyProviders?: string[];
  };
};

function isRecord(value: unknown): value is Record<string, unknown> {
  return typeof value === "object" && value !== null;
}

function parseRuntimeConfig(payload: unknown): RuntimeConfig {
  if (!isRecord(payload)) return {};

  const trustedOrigins = Array.isArray(payload.trustedOrigins)
    ? payload.trustedOrigins.filter((value): value is string => typeof value === "string")
    : [];

  const socialRaw = isRecord(payload.social) ? payload.social : null;
  const socialProvidersRaw = Array.isArray(socialRaw?.providers)
    ? socialRaw.providers.filter((value): value is Record<string, unknown> => isRecord(value))
    : [];

  const providers: SocialProviderRuntime[] = socialProvidersRaw
    .map((entry) => {
      const provider = typeof entry.provider === "string" ? entry.provider : "";
      const label = typeof entry.label === "string" ? entry.label : provider;
      const enabledByList = Boolean(entry.enabledByList);
      const clientIdSet = Boolean(entry.clientIdSet);
      const clientSecretSet = Boolean(entry.clientSecretSet);
      const ready = Boolean(entry.ready);

      if (!provider) return null;
      return {
        provider,
        label,
        enabledByList,
        clientIdSet,
        clientSecretSet,
        ready,
      };
    })
    .filter((value): value is SocialProviderRuntime => value !== null);

  return {
    defaultApiOrigin:
      typeof payload.defaultApiOrigin === "string" ? payload.defaultApiOrigin : null,
    authBasePath: typeof payload.authBasePath === "string" ? payload.authBasePath : undefined,
    upstreamAuthOrigin:
      typeof payload.upstreamAuthOrigin === "string" ? payload.upstreamAuthOrigin : null,
    proxyUpstream: isRecord(payload.proxyUpstream)
      ? {
          ok: Boolean(payload.proxyUpstream.ok),
          source:
            typeof payload.proxyUpstream.source === "string"
              ? payload.proxyUpstream.source
              : undefined,
          raw:
            typeof payload.proxyUpstream.raw === "string"
              ? payload.proxyUpstream.raw
              : undefined,
          resolved:
            typeof payload.proxyUpstream.resolved === "string"
              ? payload.proxyUpstream.resolved
              : undefined,
          code:
            typeof payload.proxyUpstream.code === "string"
              ? payload.proxyUpstream.code
              : undefined,
          message:
            typeof payload.proxyUpstream.message === "string"
              ? payload.proxyUpstream.message
              : undefined,
          details: isRecord(payload.proxyUpstream.details)
            ? payload.proxyUpstream.details
            : undefined,
        }
      : undefined,
    trustedOrigins,
    trustedOriginsRaw:
      typeof payload.trustedOriginsRaw === "string" ? payload.trustedOriginsRaw : "",
    smtpConfigured: Boolean(payload.smtpConfigured),
    smtpConfigurationError:
      typeof payload.smtpConfigurationError === "string"
        ? payload.smtpConfigurationError
        : null,
    smtpFromAddressConfigured: Boolean(payload.smtpFromAddressConfigured),
    emailDeliveryEvidence:
      typeof payload.emailDeliveryEvidence === "string"
        ? payload.emailDeliveryEvidence
        : undefined,
    social: socialRaw
      ? {
          configuredProvidersRaw:
            typeof socialRaw.configuredProvidersRaw === "string"
              ? socialRaw.configuredProvidersRaw
              : "",
          configuredProviders: Array.isArray(socialRaw.configuredProviders)
            ? socialRaw.configuredProviders.filter(
                (value): value is string => typeof value === "string",
              )
            : [],
          unknownProviders: Array.isArray(socialRaw.unknownProviders)
            ? socialRaw.unknownProviders.filter(
                (value): value is string => typeof value === "string",
              )
            : [],
          callbackPath:
            typeof socialRaw.callbackPath === "string"
              ? socialRaw.callbackPath
              : undefined,
          providers,
          readyProviders: Array.isArray(socialRaw.readyProviders)
            ? socialRaw.readyProviders.filter(
                (value): value is string => typeof value === "string",
              )
            : [],
        }
      : undefined,
  };
}

export function AuthDiagnostics({
  lastForgotEmail,
  forgotRequestAccepted,
}: {
  lastForgotEmail: string;
  forgotRequestAccepted: boolean | null;
}) {
  const [runtime, setRuntime] = useState<RuntimeConfig | null>(null);
  const [runtimeError, setRuntimeError] = useState<string | null>(null);
  const [trustedOriginsDraft, setTrustedOriginsDraft] = useState("");
  const [copyMessage, setCopyMessage] = useState<string | null>(null);
  const [loading, setLoading] = useState(false);

  const apiOrigin = getAuthApiOrigin();
  const basePath = getAuthBasePath();

  const loadRuntimeConfig = async () => {
    setLoading(true);
    setRuntimeError(null);

    try {
      const response = await fetch("/api/auth/diagnostics", {
        method: "GET",
        cache: "no-store",
      });

      const payload = (await response.json().catch(() => ({}))) as unknown;
      if (!response.ok) {
        const errorMessage =
          isRecord(payload) && typeof payload.message === "string"
            ? payload.message
            : `Diagnostics request failed (${response.status}).`;
        setRuntime(null);
        setRuntimeError(errorMessage);
        return;
      }

      const parsed = parseRuntimeConfig(payload);
      setRuntime(parsed);
      setTrustedOriginsDraft(parsed.trustedOriginsRaw ?? "");
    } catch (error) {
      const message = error instanceof Error ? error.message : "Diagnostics request failed.";
      setRuntime(null);
      setRuntimeError(message);
    } finally {
      setLoading(false);
    }
  };

  const trustedOrigins = useMemo(() => runtime?.trustedOrigins ?? [], [runtime]);
  const visibleTrustedOrigins = useMemo(
    () =>
      trustedOrigins.length ? trustedOrigins : parseTrustedOrigins(trustedOriginsDraft),
    [trustedOrigins, trustedOriginsDraft],
  );

  const addCurrentOrigin = () => {
    if (typeof window === "undefined") return;
    const current = window.location.origin;
    setTrustedOriginsDraft(addOriginToTrustedOrigins(trustedOriginsDraft, current));
  };

  const copyTrustedOriginsEnv = async () => {
    const line = buildTrustedOriginsEnvLine(trustedOriginsDraft);
    try {
      await navigator.clipboard.writeText(line);
      setCopyMessage("Copied TRUSTED_ORIGINS line.");
    } catch {
      setCopyMessage("Copy failed. Copy manually from the field.");
    }
  };

  const socialProviders = runtime?.social?.providers ?? [];

  return (
    <Card className="mt-5 border border-divider/70">
      <CardHeader>
        <CardTitle>Diagnostics</CardTitle>
        <CardDescription>Live runtime + reset-email observability</CardDescription>
      </CardHeader>
      <CardContent>
        <div className="grid gap-2 text-sm">
          <div className="flex items-center gap-2">
            <Button type="button" variant="secondary" onClick={loadRuntimeConfig} disabled={loading}>
              {loading ? "Loading config..." : "Load runtime config"}
            </Button>
          </div>
          <div className="grid gap-2 rounded-md border border-divider p-3">
            <div><strong>TRUSTED_ORIGINS config</strong></div>
            <Label htmlFor="trusted-origins-diagnostics">Origins</Label>
            <Input
              id="trusted-origins-diagnostics"
              value={trustedOriginsDraft}
              onChange={(e) => {
                setTrustedOriginsDraft(e.target.value);
                setCopyMessage(null);
              }}
              placeholder="http://localhost:3001,http://localhost:3000"
            />
            <div className="flex flex-wrap gap-2">
              <Button type="button" variant="secondary" onClick={addCurrentOrigin}>Add current origin</Button>
              <Button type="button" variant="secondary" onClick={copyTrustedOriginsEnv}>Copy .env line</Button>
            </div>
            {copyMessage ? <div>{copyMessage}</div> : null}
            <div>Apply this in Rust server `.env` and restart server.</div>
          </div>
          <div><strong>Configured auth base:</strong> {apiOrigin}{basePath}</div>
          <div><strong>Demo NEXT_PUBLIC auth origin:</strong> {runtime?.defaultApiOrigin ?? "(not set)"}</div>
          <div><strong>Demo NEXT_PUBLIC auth base path:</strong> {runtime?.authBasePath ?? "(not set)"}</div>
          <div><strong>Proxy upstream origin (ATHENA_AUTH_ORIGIN):</strong> {runtime?.upstreamAuthOrigin ?? "(not set)"}</div>
          <div>
            <strong>Proxy upstream resolution:</strong>{" "}
            {runtime?.proxyUpstream?.ok
              ? `${runtime.proxyUpstream.resolved ?? "(resolved)"}` +
                (runtime.proxyUpstream.source
                  ? ` (source: ${runtime.proxyUpstream.source})`
                  : "")
              : runtime?.proxyUpstream?.message
                ? `${runtime.proxyUpstream.message}${runtime.proxyUpstream.code ? ` [${runtime.proxyUpstream.code}]` : ""}`
                : "(not evaluated)"}
          </div>
          <div><strong>Trusted origins:</strong> {visibleTrustedOrigins.length ? visibleTrustedOrigins.join(", ") : "(none exposed)"}</div>
          <div className="rounded-md border border-divider p-3">
            <div className="mb-2"><strong>Social Auth Configuration</strong></div>
            <div><strong>Configured provider list:</strong> {runtime?.social?.configuredProvidersRaw || "(empty)"}</div>
            <div><strong>Callback path:</strong> {runtime?.social?.callbackPath ?? "(default /session)"}</div>
            <div><strong>Ready providers:</strong> {runtime?.social?.readyProviders?.length ? runtime.social.readyProviders.join(", ") : "(none)"}</div>
            {runtime?.social?.unknownProviders?.length ? (
              <div className="text-warning">
                <strong>Unknown configured providers:</strong> {runtime.social.unknownProviders.join(", ")}
              </div>
            ) : null}
            <div className="mt-2 grid gap-2">
              {socialProviders.length ? socialProviders.map((provider) => (
                <div
                  key={provider.provider}
                  className="grid gap-2 rounded border border-divider p-2 md:grid-cols-[minmax(120px,1fr)_1fr_1fr_1fr]"
                >
                  <div className="font-medium">{provider.label}</div>
                  <div className="flex items-center gap-2">
                    <span className="text-xs uppercase text-slate-500">Enabled</span>
                    <Badge variant={provider.enabledByList ? "success" : "secondary"}>
                      {provider.enabledByList ? "yes" : "no"}
                    </Badge>
                  </div>
                  <div className="flex items-center gap-2">
                    <span className="text-xs uppercase text-slate-500">Client Id</span>
                    <Badge variant={provider.clientIdSet ? "success" : "warning"}>
                      {provider.clientIdSet ? "set" : "missing"}
                    </Badge>
                  </div>
                  <div className="flex items-center gap-2">
                    <span className="text-xs uppercase text-slate-500">Client Secret</span>
                    <Badge variant={provider.clientSecretSet ? "success" : "warning"}>
                      {provider.clientSecretSet ? "set" : "missing"}
                    </Badge>
                    <Badge variant={provider.ready ? "success" : "secondary"}>
                      {provider.ready ? "ready" : "not ready"}
                    </Badge>
                  </div>
                </div>
              )) : (
                <div className="text-slate-500">No supported social providers found in diagnostics payload.</div>
              )}
            </div>
          </div>
          <div className="flex items-center gap-2">
            <strong>SMTP configured:</strong>
            <Badge variant={runtime?.smtpConfigured ? "success" : "warning"}>
              {runtime?.smtpConfigured ? "configured" : "not configured / unknown"}
            </Badge>
          </div>
          {runtime?.smtpConfigurationError ? (
            <div className="text-warning">
              <strong>SMTP config error:</strong> {runtime.smtpConfigurationError}
            </div>
          ) : null}
          <div className="flex items-center gap-2">
            <strong>SMTP from address set:</strong>
            <Badge variant={runtime?.smtpFromAddressConfigured ? "success" : "warning"}>
              {runtime?.smtpFromAddressConfigured ? "set" : "missing / unknown"}
            </Badge>
          </div>
          <div className="flex items-center gap-2">
            <strong>Forgot-password request accepted:</strong>
            <Badge
              variant={
                forgotRequestAccepted === null
                  ? "secondary"
                  : forgotRequestAccepted
                    ? "success"
                    : "destructive"
              }
            >
              {forgotRequestAccepted === null ? "unknown (not requested yet)" : forgotRequestAccepted ? "yes" : "no"}
            </Badge>
          </div>
          <div><strong>Last forgot-password email:</strong> {lastForgotEmail || "(none)"}</div>
          <div><strong>Delivery evidence:</strong> {runtime?.emailDeliveryEvidence ?? "Reset endpoint acceptance does not always prove inbox delivery."}</div>
          {runtimeError ? (
            <div className="text-danger">
              <strong>Config fetch error:</strong> {runtimeError}
              <div>Tip: ensure the demo app can serve `/api/auth/diagnostics` and that your proxy auth env values are set.</div>
            </div>
          ) : null}
        </div>
      </CardContent>
    </Card>
  );
}

