import { useEffect, useMemo, useState } from "react";
import { Link } from "react-router-dom";
import { grades as defaultGrades } from "@/data/portraitData";
import { orionExternalApiUrl } from "@/lib/apiUrl";
import { appendApiQueryFilters } from "@/lib/apiQueryFilters";
import { fetchEncryptedApiData } from "@/lib/encryptedApiClient";

type Content = Record<string, unknown>;

type GradeItem = { id: string; label?: string; shortLabel: string; route: string; available: boolean };

function parseItems(content: Content | undefined): GradeItem[] {
  const raw = content?.items;
  if (!Array.isArray(raw) || raw.length === 0) return defaultGrades;
  return raw.map((x: unknown, index: number) => {
    const o = x as Record<string, unknown>;
    return {
      id: typeof o?.id === "string" ? o.id : `item-${index}`,
      label: typeof o?.label === "string" ? o.label : undefined,
      shortLabel: typeof o?.shortLabel === "string" ? o.shortLabel : "",
      route: typeof o?.route === "string" ? o.route : "#",
      available: o?.available === true,
    };
  });
}

function getArrayFromResponse(data: unknown): unknown[] {
  if (Array.isArray(data)) return data;
  if (!data || typeof data !== "object") return [];
  const record = data as Record<string, unknown>;

  const direct = [record.items, record.grades, record.data, record.results, record.payload];
  for (const candidate of direct) {
    if (Array.isArray(candidate)) return candidate;
  }

  const nested = [record.data, record.payload, record.response, record.result];
  for (const candidate of nested) {
    if (candidate && typeof candidate === "object" && !Array.isArray(candidate)) {
      const nestedRecord = candidate as Record<string, unknown>;
      const nestedDirect = [nestedRecord.items, nestedRecord.grades, nestedRecord.data, nestedRecord.results];
      for (const nestedCandidate of nestedDirect) {
        if (Array.isArray(nestedCandidate)) return nestedCandidate;
      }
    }
  }

  return [];
}

function normalizeApiGradeItems(data: unknown): GradeItem[] {
  const list = getArrayFromResponse(data);
  return list
    .map((item, index) => {
      const row = (item && typeof item === "object" ? item : {}) as Record<string, unknown>;

      // Requested mapping for API payload:
      // Text -> shortLabel/label, Values -> id, route -> "#", available -> true
      if (typeof row.Text === "string" && row.Text.trim()) {
        const text = row.Text.trim();
        const value = row.Values;
        const id =
          typeof value === "number"
            ? String(value)
            : typeof value === "string" && value.trim()
            ? value.trim()
            : `grade-${index}`;
        return {
          id,
          label: text,
          shortLabel: text,
          route: "#",
          available: true,
        };
      }

      const shortLabel =
        typeof row.shortLabel === "string"
          ? row.shortLabel
          : typeof row.short === "string"
          ? row.short
          : typeof row.code === "string"
          ? row.code
          : typeof row.id === "string"
          ? row.id.toUpperCase()
          : "";

      if (!shortLabel) return null;

      const id =
        typeof row.id === "string"
          ? row.id
          : typeof row.gradeId === "string"
          ? row.gradeId
          : `${shortLabel.toLowerCase()}-${index}`;

      const route =
        typeof row.route === "string"
          ? row.route
          : typeof row.href === "string"
          ? row.href
          : typeof row.url === "string"
          ? row.url
          : "#";

      const available =
        typeof row.available === "boolean"
          ? row.available
          : typeof row.enabled === "boolean"
          ? row.enabled
          : typeof row.isActive === "boolean"
          ? row.isActive
          : true;

      const label =
        typeof row.label === "string"
          ? row.label
          : typeof row.name === "string"
          ? row.name
          : undefined;

      return { id, label, shortLabel, route, available };
    })
    .filter((item) => item !== null) as GradeItem[];
}

export function GradeFamilyGuidesApiBlock({ content }: { content?: Content }) {
  const heading = (content?.heading as string) ?? "Family Guides by Grade";
  const footerText = (content?.footerText as string) ?? "Live API driven list";
  const apiPath = ((content?.apiPath as string) ?? (content?.apiUrl as string) ?? "").trim();
  const apiMethod = ((content?.apiMethod as string) ?? "GET").toUpperCase();
  const apiHeadersJson = (content?.apiHeadersJson as string) ?? "";
  const apiBodyJson = (content?.apiBodyJson as string) ?? "";
  const fallbackItems = useMemo(() => parseItems(content), [content]);
  const [apiItems, setApiItems] = useState<GradeItem[] | null>(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState("");

  useEffect(() => {
    if (!apiPath) {
      setApiItems(null);
      setError("");
      setLoading(false);
      return;
    }

    let cancelled = false;
    setLoading(true);
    setError("");

    const requestUrl = appendApiQueryFilters(orionExternalApiUrl(apiPath), content?.filters);

    fetchEncryptedApiData({
      url: requestUrl,
      method: apiMethod,
      headersJson: apiHeadersJson,
      bodyJson: apiBodyJson,
    })
      .then((response) => {
        if (cancelled) return;
        const normalized = normalizeApiGradeItems(response);
        if (normalized.length > 0) {
          setApiItems(normalized);
          return;
        }
        setApiItems(null);
        setError("API response was received, but did not contain mappable grade items.");
      })
      .catch((e) => {
        if (!cancelled) {
          setApiItems(null);
          setError(e instanceof Error ? e.message : "Failed to load API data.");
        }
      })
      .finally(() => {
        if (!cancelled) setLoading(false);
      });

    return () => {
      cancelled = true;
    };
  }, [apiBodyJson, apiHeadersJson, apiMethod, apiPath, content?.filters]);

  const gradeItems = apiItems?.length ? apiItems : fallbackItems;

  return (
    <section className="py-10 bg-card">
      <div className="container mx-auto px-6 max-w-3xl text-center">
        <p className="font-display text-xs tracking-[0.2em] uppercase text-deep-sea mb-4">{heading}</p>
        <div className="flex flex-wrap justify-center gap-2">
          {gradeItems.map((g) =>
            g.available ? (
              <Link
                key={g.id}
                to={g.route}
                title={g.label}
                className="inline-flex items-center justify-center font-display text-sm font-bold rounded-full w-12 h-12 bg-deep-sea text-milk hover:bg-valencia transition-colors shadow-md hover:shadow-lg"
              >
                {g.shortLabel}
              </Link>
            ) : (
              <span
                key={g.id}
                title={g.label || "Coming soon"}
                className="inline-flex items-center justify-center font-display text-sm font-medium rounded-full w-12 h-12 bg-secondary text-muted-foreground cursor-not-allowed"
              >
                {g.shortLabel}
              </span>
            )
          )}
        </div>
        <p className="text-muted-foreground text-xs mt-3 font-display">{footerText}</p>
        {loading && <p className="text-[11px] text-muted-foreground mt-2">Loading live data...</p>}
        {!loading && error && <p className="text-[11px] text-amber-700 mt-2">Using fallback data: {error}</p>}
      </div>
    </section>
  );
}
