import { createContext, useContext, useEffect, useState, ReactNode } from "react";

export interface CompanyBranding {
  id: string;
  company_id: string;
  subdomain: string;
  logo_url: string | null;
  primary_color: string | null;
  secondary_color: string | null;
  background_color: string | null;
  font_color: string | null;
  card_color: string | null;
  card_font_color: string | null;
  hero_image_url: string | null;
  hero_video_url: string | null;
  tagline: string | null;
  is_active: boolean;
  contact_email: string | null;
  contact_phone: string | null;
  contact_address: string | null;
  opening_hours: string | null;
}

/** Shape of the `tenant` prop shared by the server (HandleInertiaRequests). */
export interface ServerTenant {
  company_id: string;
  name: string;
  subdomain: string;
  branding: CompanyBranding | null;
}

interface TenantContextType {
  isTenantMode: boolean;
  branding: CompanyBranding | null;
  companyId: string | null;
  companyName: string | null;
  subdomain: string | null;
  isLoading: boolean;
}

const NO_TENANT: TenantContextType = {
  isTenantMode: false,
  branding: null,
  companyId: null,
  companyName: null,
  subdomain: null,
  isLoading: false,
};

const TenantContext = createContext<TenantContextType>({ ...NO_TENANT, isLoading: true });

export const useTenant = () => useContext(TenantContext);

/** Convert hex (#1E40AF) to HSL string "224 72% 40%" */
export function hexToHsl(hex: string): string | null {
  const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
  if (!result) return null;
  const r = parseInt(result[1], 16) / 255;
  const g = parseInt(result[2], 16) / 255;
  const b = parseInt(result[3], 16) / 255;
  const max = Math.max(r, g, b), min = Math.min(r, g, b);
  let h = 0, s = 0;
  const l = (max + min) / 2;
  if (max !== min) {
    const d = max - min;
    s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
    switch (max) {
      case r: h = ((g - b) / d + (g < b ? 6 : 0)) / 6; break;
      case g: h = ((b - r) / d + 2) / 6; break;
      case b: h = ((r - g) / d + 4) / 6; break;
    }
  }
  return `${Math.round(h * 360)} ${Math.round(s * 100)}% ${Math.round(l * 100)}%`;
}

/**
 * Apply the tenant's full colour scheme to the document root. On a tenant
 * subdomain the entire SPA *is* that tenant's site, so we theme globally
 * (accent + surfaces). On the main marketplace `branding` is null and nothing
 * is applied, leaving the default UTC theme intact.
 */
function applyBranding(branding: CompanyBranding | null) {
  if (typeof document === "undefined" || !branding) return;
  const root = document.documentElement;
  const set = (prop: string, hex: string | null) => {
    if (!hex) return;
    const hsl = hexToHsl(hex);
    if (hsl) root.style.setProperty(prop, hsl);
  };
  if (branding.primary_color) {
    const hsl = hexToHsl(branding.primary_color);
    if (hsl) {
      root.style.setProperty("--primary", hsl);
      root.style.setProperty("--accent", hsl);
      root.style.setProperty("--ring", hsl);
    }
  }
  set("--background", branding.background_color);
  set("--foreground", branding.font_color);
  set("--secondary", branding.secondary_color);
  set("--card", branding.card_color);
  set("--card-foreground", branding.card_font_color);
}

function fromServerTenant(t: ServerTenant): TenantContextType {
  return {
    isTenantMode: true,
    branding: t.branding,
    companyId: t.company_id,
    companyName: t.name,
    subdomain: t.subdomain,
    isLoading: false,
  };
}

/**
 * Dev/preview fallback only: derive a subdomain from the URL when the server
 * did not resolve a tenant (e.g. local SPA on "<slug>.localhost" or a
 * "?tenant=<slug>" override). In production the server is authoritative.
 */
function detectSubdomainFromLocation(): string | null {
  const params = new URLSearchParams(window.location.search);
  const override = params.get("tenant");
  if (override) return override;

  const hostname = window.location.hostname.toLowerCase();
  const parts = hostname.split(".");
  if (parts.length >= 3) {
    const first = parts[0];
    if (first && !["www", "localhost"].includes(first)) return first;
  }
  if (parts.length === 2 && parts[1] === "localhost" && parts[0] !== "www") {
    return parts[0];
  }
  return null;
}

export const TenantProvider = ({
  children,
  initialTenant = null,
}: {
  children: ReactNode;
  initialTenant?: ServerTenant | null;
}) => {
  const [state, setState] = useState<TenantContextType>(() =>
    initialTenant ? fromServerTenant(initialTenant) : { ...NO_TENANT, isLoading: true },
  );

  // Re-apply the tenant theme whenever branding changes.
  useEffect(() => {
    applyBranding(state.branding);
  }, [state.branding]);

  // When the server already resolved the tenant (the production path) there is
  // nothing to detect. Only fall back to client detection otherwise.
  useEffect(() => {
    if (initialTenant) return;

    let cancelled = false;
    (async () => {
      const subdomain = detectSubdomainFromLocation();
      if (!subdomain) {
        if (!cancelled) setState(NO_TENANT);
        return;
      }
      try {
        const res = await fetch(`/api/tenant/branding?subdomain=${encodeURIComponent(subdomain)}`);
        const data = res.ok ? await res.json() : null;
        const branding: CompanyBranding | null =
          data && typeof data === "object" && data.is_active ? (data as CompanyBranding) : null;
        if (cancelled) return;
        setState(
          branding
            ? {
                isTenantMode: true,
                branding,
                companyId: branding.company_id,
                companyName: null,
                subdomain,
                isLoading: false,
              }
            : NO_TENANT,
        );
      } catch {
        if (!cancelled) setState(NO_TENANT);
      }
    })();

    return () => {
      cancelled = true;
    };
  }, [initialTenant]);

  return <TenantContext.Provider value={state}>{children}</TenantContext.Provider>;
};
