import { useCallback, useEffect, useRef, useState } from "react";
import { client } from "@/lib/api";

export interface WhmcsProfile {
  client_id: number;
  firstname: string;
  lastname: string;
  fullname: string;
  email: string;
  company?: string | null;
  address1?: string | null;
  address2?: string | null;
  city?: string | null;
  state?: string | null;
  postcode?: string | null;
  country?: string | null;
  phonenumber?: string | null;
  status?: string | null;
  credit?: string | null;
  currency_code?: string | null;
  num_invoices?: number | null;
  num_due_invoices?: number | null;
  num_products?: number | null;
  num_domains?: number | null;
  num_tickets?: number | null;
}

interface UseWhmcsProfileResult {
  loading: boolean;
  profile: WhmcsProfile | null;
  error: string | null;
  notLinked: boolean;
  /** True while the backend is temporarily unavailable and we're auto-retrying. */
  retrying: boolean;
  refetch: () => Promise<void>;
}

/**
 * Fetches the current signed-in user's WHMCS profile via backend proxy.
 *
 * Behavior notes:
 * - Returns `notLinked=true` when the Atoms user has no matching WHMCS client
 *   so the UI can surface a "complete registration" call-to-action.
 * - Transparently retries on transient 502/503/504 responses (or HTML error pages
 *   from platform gateways) up to a few times with backoff, and surfaces a
 *   friendly "temporarily unavailable" message instead of a raw HTML dump.
 */
export function useWhmcsProfile(): UseWhmcsProfileResult {
  const [loading, setLoading] = useState(true);
  const [profile, setProfile] = useState<WhmcsProfile | null>(null);
  const [error, setError] = useState<string | null>(null);
  const [notLinked, setNotLinked] = useState(false);
  const [retrying, setRetrying] = useState(false);
  const cancelledRef = useRef(false);

  const load = useCallback(async () => {
    cancelledRef.current = false;
    setLoading(true);
    setError(null);
    setNotLinked(false);
    setRetrying(false);

    const MAX_ATTEMPTS = 4;
    const BACKOFF_MS = [1500, 2500, 4000]; // between attempts 1->2, 2->3, 3->4

    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    const isTransient = (anyErr: any): boolean => {
      const status: number | undefined = anyErr?.response?.status || anyErr?.status;
      if (status === 502 || status === 503 || status === 504) return true;
      const raw: unknown = anyErr?.response?.data ?? anyErr?.data;
      if (typeof raw === "string" && raw.trim().toLowerCase().startsWith("<!doctype")) {
        return true;
      }
      return false;
    };

    for (let attempt = 1; attempt <= MAX_ATTEMPTS; attempt++) {
      if (cancelledRef.current) return;
      try {
        const res = await client.apiCall.invoke({
          url: "/api/v1/whmcs/me",
          method: "GET",
          data: {},
        });
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        const data: WhmcsProfile = (res as any)?.data;
        if (!data) throw new Error("Empty WHMCS profile response.");
        if (cancelledRef.current) return;
        setProfile(data);
        setError(null);
        setNotLinked(false);
        setRetrying(false);
        setLoading(false);
        return;
      } catch (err: unknown) {
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        const anyErr = err as any;
        const status: number | undefined = anyErr?.response?.status || anyErr?.status;

        if (status === 404) {
          if (cancelledRef.current) return;
          setNotLinked(true);
          setProfile(null);
          setRetrying(false);
          setLoading(false);
          return;
        }

        if (isTransient(anyErr) && attempt < MAX_ATTEMPTS) {
          if (cancelledRef.current) return;
          setRetrying(true);
          const delay = BACKOFF_MS[attempt - 1] ?? 4000;
          await new Promise((resolve) => setTimeout(resolve, delay));
          continue;
        }

        // Final failure — surface a clean message.
        if (cancelledRef.current) return;
        let detail: string | undefined =
          anyErr?.response?.data?.detail || anyErr?.data?.detail || anyErr?.message;
        if (typeof detail === "string" && detail.trim().toLowerCase().startsWith("<!doctype")) {
          detail = undefined;
        }
        if (isTransient(anyErr)) {
          setError(
            "The backend service is temporarily unavailable. Please try again in a few seconds."
          );
        } else {
          setError(detail || "Failed to load WHMCS profile.");
        }
        setProfile(null);
        setRetrying(false);
        setLoading(false);
        return;
      }
    }
  }, []);

  useEffect(() => {
    load();
    return () => {
      cancelledRef.current = true;
    };
  }, [load]);

  return { loading, profile, error, notLinked, retrying, refetch: load };
}