import { useEffect } from "react";
import { useLocation } from "react-router-dom";
import { useLanguage, type AppLanguage } from "@/context/LanguageContext";
import {
  BRAND_NAME,
  DEFAULT_OG_IMAGE,
  SITE_ORIGIN,
  resolveSeo,
  shouldNoIndex,
} from "@/lib/seoConfig";

/**
 * Dynamically updates `<head>` metadata so search engines can correctly
 * index both the English and Arabic versions of every public page.
 *
 * What this component writes on each route / language change:
 *
 *   - `<html lang="…">` and `<html dir="…">` — RTL-aware.
 *   - `<title>` — localized, with brand suffix on non-home pages.
 *   - `<meta name="description">` — localized summary.
 *   - `<meta http-equiv="content-language">` — current language.
 *   - `<meta name="robots">` — `noindex, nofollow` for admin / auth pages,
 *     `index, follow` for public pages.
 *   - `<link rel="canonical">` — canonical URL for the current page.
 *   - `<link rel="alternate" hreflang="…">` — one per supported language
 *     plus an `x-default` pointing to English. Each alternate uses the
 *     same path on the same origin, which matches our client-side SPA
 *     i18n model (language is stored in localStorage, not in the URL).
 *   - Open Graph: `og:type`, `og:locale`, `og:locale:alternate`,
 *     `og:title`, `og:description`, `og:url`, `og:image`,
 *     `og:site_name`.
 *   - Twitter card: `twitter:card`, `twitter:title`,
 *     `twitter:description`, `twitter:image`.
 *
 * We mutate `document.head` directly (instead of pulling in a helmet
 * library) because this project already has a DOM-level auto translator
 * and the metadata surface is small and well defined.
 *
 * Notes on canonical / hreflang strategy:
 *   - The canonical URL for EVERY language is the same path on the same
 *     origin. Google fully supports `hreflang` variants sharing a single
 *     canonical when the page content is translated client-side and the
 *     URL does not change per-language. Do not point `canonical` to a
 *     language variant — that would deindex the other language.
 *   - For pages that should not be indexed at all (admin, account, auth)
 *     we emit `robots="noindex, nofollow"` and skip hreflang entirely.
 */

const HREFLANG_MAP: Record<AppLanguage, string> = {
  en: "en",
  ar: "ar",
};

const OG_LOCALE_MAP: Record<AppLanguage, string> = {
  en: "en_US",
  ar: "ar_SA",
};

const SUPPORTED_LANGS: AppLanguage[] = ["en", "ar"];

/**
 * Set or create a `<meta>` tag with the given attribute pair.
 */
function upsertMeta(
  attr: "name" | "property" | "http-equiv",
  key: string,
  content: string,
) {
  if (typeof document === "undefined") return;
  let el = document.head.querySelector<HTMLMetaElement>(
    `meta[${attr}="${key}"]`,
  );
  if (!el) {
    el = document.createElement("meta");
    el.setAttribute(attr, key);
    document.head.appendChild(el);
  }
  if (el.getAttribute("content") !== content) {
    el.setAttribute("content", content);
  }
}

/**
 * Remove any meta tag matching the selector. Used when a page flips
 * from "public" to "noindex" so stale attributes don't linger.
 */
function removeMeta(selector: string) {
  if (typeof document === "undefined") return;
  document.head
    .querySelectorAll(selector)
    .forEach((el) => el.parentElement?.removeChild(el));
}

/**
 * Clear all previously-managed `<link rel="alternate">` entries we own
 * before writing a new set. Each managed link carries `data-i18n-seo`.
 */
function clearAlternates() {
  if (typeof document === "undefined") return;
  document.head
    .querySelectorAll("link[data-i18n-seo='hreflang']")
    .forEach((el) => el.parentElement?.removeChild(el));
}

function setCanonical(href: string) {
  if (typeof document === "undefined") return;
  let el = document.head.querySelector<HTMLLinkElement>(
    "link[rel='canonical']",
  );
  if (!el) {
    el = document.createElement("link");
    el.setAttribute("rel", "canonical");
    document.head.appendChild(el);
  }
  if (el.getAttribute("href") !== href) {
    el.setAttribute("href", href);
  }
}

function appendAlternate(hreflang: string, href: string) {
  if (typeof document === "undefined") return;
  const el = document.createElement("link");
  el.setAttribute("rel", "alternate");
  el.setAttribute("hreflang", hreflang);
  el.setAttribute("href", href);
  el.setAttribute("data-i18n-seo", "hreflang");
  document.head.appendChild(el);
}

/**
 * Resolve the origin at runtime (client) or fall back to the configured
 * `SITE_ORIGIN` when rendered outside a browser.
 */
function getOrigin(): string {
  if (typeof window !== "undefined" && window.location?.origin) {
    return window.location.origin.replace(/\/+$/, "");
  }
  return SITE_ORIGIN.replace(/\/+$/, "");
}

/**
 * Component — mount once (e.g. inside SiteLayout). It keeps `<head>`
 * in sync with the current route and active language.
 */
export default function SeoMeta() {
  const { lang } = useLanguage();
  const { pathname, search } = useLocation();

  useEffect(() => {
    if (typeof document === "undefined") return;

    const cleanPath = pathname.replace(/\/+$/, "") || "/";
    const origin = getOrigin();
    const canonicalUrl = `${origin}${cleanPath}`;
    const fullUrl = `${origin}${cleanPath}${search || ""}`;

    const seo = resolveSeo(cleanPath, lang);
    const isHome = cleanPath === "/";
    const title = isHome
      ? seo.title
      : `${seo.title}${seo.title.includes(BRAND_NAME[lang]) ? "" : " | " + BRAND_NAME[lang]}`;

    // 1. <html lang> + dir
    document.documentElement.setAttribute("lang", lang);
    document.documentElement.setAttribute(
      "dir",
      lang === "ar" ? "rtl" : "ltr",
    );

    // 2. <title>
    if (document.title !== title) document.title = title;

    // 3. Core meta
    upsertMeta("name", "description", seo.description);
    upsertMeta("http-equiv", "content-language", lang);

    // 4. Robots
    if (shouldNoIndex(cleanPath)) {
      upsertMeta("name", "robots", "noindex, nofollow");
    } else {
      upsertMeta("name", "robots", "index, follow");
    }

    // 5. Canonical URL — same path for every language variant.
    setCanonical(canonicalUrl);

    // 6. hreflang alternates. Skip on noindex pages.
    clearAlternates();
    if (!shouldNoIndex(cleanPath)) {
      for (const code of SUPPORTED_LANGS) {
        appendAlternate(HREFLANG_MAP[code], canonicalUrl);
      }
      // x-default points to the English variant of the same path.
      appendAlternate("x-default", canonicalUrl);
    }

    // 7. Open Graph
    upsertMeta("property", "og:type", "website");
    upsertMeta("property", "og:site_name", BRAND_NAME[lang]);
    upsertMeta("property", "og:title", title);
    upsertMeta("property", "og:description", seo.description);
    upsertMeta("property", "og:url", fullUrl);
    upsertMeta("property", "og:locale", OG_LOCALE_MAP[lang]);

    // og:locale:alternate — clear + re-add to avoid duplicates.
    removeMeta("meta[property='og:locale:alternate']");
    for (const code of SUPPORTED_LANGS) {
      if (code === lang) continue;
      const m = document.createElement("meta");
      m.setAttribute("property", "og:locale:alternate");
      m.setAttribute("content", OG_LOCALE_MAP[code]);
      document.head.appendChild(m);
    }

    const ogImage = seo.image
      ? seo.image.startsWith("http")
        ? seo.image
        : `${origin}${seo.image}`
      : `${origin}${DEFAULT_OG_IMAGE}`;
    upsertMeta("property", "og:image", ogImage);
    upsertMeta("property", "og:image:alt", BRAND_NAME[lang]);

    // 8. Twitter card
    upsertMeta("name", "twitter:card", "summary_large_image");
    upsertMeta("name", "twitter:title", title);
    upsertMeta("name", "twitter:description", seo.description);
    upsertMeta("name", "twitter:image", ogImage);
  }, [lang, pathname, search]);

  return null;
}