/**
 * Auto-syncs the logged-in subscriber's Xtream credentials into the local
 * "profile" store the rest of the app already uses (so LiveTV / Movies /
 * Series pages find an active profile without the user having to add one
 * manually). Resolved creds come from `/api/subscription/status` and may
 * be either the shared (global) credentials configured by admin, or the
 * subscriber's own per-user credentials.
 */
import { useEffect, useRef } from "react";

import { useProfiles } from "@/hooks/useProfiles";
import { usePrefetchProfile } from "@/hooks/useXtreamData";
import { apiSubscriptionStatus, getToken } from "@/lib/nadiAuth";
import { nadiDb } from "@/lib/nadiDb";
import type { XtreamProfile } from "@/types/xtream";
import { toast } from "sonner";

const MANAGED_ID_KEY = "nadiplay_managed_profile_id";
const MANAGED_LIVE_ID_KEY = "nadiplay_managed_live_profile_id";
const MANAGED_VOD_ID_KEY = "nadiplay_managed_vod_profile_id";
const MANAGED_COUNTS_KEY = "nadiplay_managed_counts";

export type ManagedCounts = {
  channels: number;
  movies: number;
  series: number;
  updatedAt: number;
};

export const getManagedProfileId = () => {
  try {
    return localStorage.getItem(MANAGED_ID_KEY);
  } catch (e) {
    console.warn("[useSubscriberProfileSync] read managed id failed", e);
    return null;
  }
};

export const getManagedCounts = (): ManagedCounts | null => {
  try {
    const raw = localStorage.getItem(MANAGED_COUNTS_KEY);
    return raw ? (JSON.parse(raw) as ManagedCounts) : null;
  } catch (e) {
    console.warn("[useSubscriberProfileSync] read managed counts failed", e);
    return null;
  }
};

export const setManagedCounts = (counts: Omit<ManagedCounts, "updatedAt">) => {
  try {
    localStorage.setItem(
      MANAGED_COUNTS_KEY,
      JSON.stringify({ ...counts, updatedAt: Date.now() }),
    );
    window.dispatchEvent(new Event("nadiplay-managed-counts-changed"));
  } catch (e) {
    console.warn("[useSubscriberProfileSync] write managed counts failed", e);
  }
};

export const clearManagedProfile = () => {
  try {
    // Clear all managed profile keys (legacy + dual-source)
    for (const key of [MANAGED_ID_KEY, MANAGED_LIVE_ID_KEY, MANAGED_VOD_ID_KEY]) {
      const id = localStorage.getItem(key);
      if (id) {
        const saved = JSON.parse(localStorage.getItem("nadiplay_profiles") || "[]") as XtreamProfile[];
        const next = saved.filter((p) => p.id !== id);
        localStorage.setItem("nadiplay_profiles", JSON.stringify(next));
        const active = localStorage.getItem("nadiplay_active_profile");
        if (active === id) localStorage.removeItem("nadiplay_active_profile");
        localStorage.removeItem(key);
      }
    }
    localStorage.removeItem(MANAGED_COUNTS_KEY);
    window.dispatchEvent(new Event("nadiplay-profiles-changed"));
  } catch (e) {
    console.warn("[useSubscriberProfileSync] clear managed profile failed", e);
  }
};

/**
 * Safely extract a string from an unknown value. Returns "" if null/undefined.
 */
const safeStr = (v: unknown): string =>
  (v != null && typeof v === "string") ? v : "";

/**
 * Check if a dual-source object is usable (has non-empty type AND url).
 */
const isValidSource = (src: unknown): src is { type: string; url: string } => {
  if (src == null || typeof src !== "object") return false;
  const s = src as Record<string, unknown>;
  return typeof s.type === "string" && s.type !== "" &&
         typeof s.url === "string" && s.url !== "";
};

export const useSubscriberProfileSync = (user: { id: string; role: string; xtream_mode?: "shared" | "own" } | null) => {
  const { profiles, addProfile, updateProfile, setActiveProfileId } = useProfiles();
  const prefetch = usePrefetchProfile();
  // BUG-2 FIX (2026-05): the previous guard `lastSyncedUserId === user.id`
  // short-circuited any re-sync after the FIRST sync for a given user.
  // That meant a mode change (Admin flips "Shared" → "Own server") was
  // silently ignored until the user logged out and back in, leaving the
  // old (shared) profile active. We now also key the guard on a
  // mode-sensitive signature so the hook re-syncs whenever the resolved
  // mode / creds change.
  const lastSyncedSig = useRef<string | null>(null);

  useEffect(() => {
    if (!user || user.role !== "user" || !getToken()) return;

    let cancelled = false;

    (async () => {
      try {
        const status = await apiSubscriptionStatus();
        if (cancelled) return;

        // Build a signature that captures: who + which mode + creds shape.
        const sig = [
          user.id,
          user.xtream_mode || (status as any)?.xtream_mode || "",
          status?.xtream?.server || "",
          status?.xtream?.username || "",
          (status as any)?.xtream_configured ? "1" : "0",
          (status as any)?.live_source?.url || "",
          (status as any)?.vod_source?.url || "",
        ].join("|");
        if (lastSyncedSig.current === sig) return;

        // ── Persist proxy_enabled (non-critical) ──
        try {
          const pe = (status as any)?.proxy_enabled;
          if (pe !== undefined && pe !== null) {
            localStorage.setItem("nadiplay_proxy_enabled", String(pe));
          }
        } catch { /* noop */ }

        // ── Guard: expired user → wipe managed profiles ──
        if (!status?.user || status.user.is_expired) {
          clearManagedProfile();
          lastSyncedSig.current = sig;
          return;
        }

        // ── BUG-7 HARD BLOCK (2026-05): strict Own-mode isolation ──
        //
        // Check BOTH client-side user.xtream_mode (from login response —
        // always available) AND server-side xtream_mode (from subscription
        // status — may be absent on old backends). If EITHER says "own",
        // the user is on own-mode and must NOT receive any shared content.
        const resolvedMode = (status as any)?.xtream_mode || user.xtream_mode;
        const xtreamConfigured = (status as any)?.xtream_configured;
        const isOwnMode = resolvedMode === "own";

        // Check if own-mode user has credentials (from any source)
        const xtCheck = status.xtream || { server: "", username: "", password: "" };
        const hasXtreamCreds = !!(safeStr(xtCheck.server) && safeStr(xtCheck.username) && safeStr(xtCheck.password));
        const hasLiveSource = !!(status as any)?.live_source?.url;
        const hasVodSource = !!(status as any)?.vod_source?.url;
        const hasAnyCreds = hasXtreamCreds || hasLiveSource || hasVodSource;

        if (isOwnMode && !hasAnyCreds) {
          clearManagedProfile();
          // Purge ALL shared:* and managed profiles from IndexedDB so
          // "own server" users with no credentials see a completely
          // empty dashboard — no leaked admin content.
          try {
            const allProfiles = await nadiDb.profiles.toArray();
            for (const p of allProfiles) {
              if (
                p?.id?.startsWith("shared:") ||
                p?.managed === true ||
                p?.ownerUserId === "shared" ||
                p?.ownerUserId === "managed"
              ) {
                await nadiDb.profiles.delete(p.id);
              }
            }
            // Clear active profile if it was a shared/managed one
            try {
              const currentActive = localStorage.getItem("nadiplay_active_profile");
              if (currentActive) {
                const stillExists = await nadiDb.profiles.get(currentActive);
                if (!stillExists) {
                  localStorage.removeItem("nadiplay_active_profile");
                  setActiveProfileId(null);
                }
              }
            } catch { /* noop */ }
            window.dispatchEvent(new Event("nadiplay-profiles-changed"));
          } catch (purgeErr) {
            console.warn("[useSubscriberProfileSync] purge shared profiles failed", purgeErr);
          }
          toast.success(
            "Add your Xtream server as you wish and enjoy a premium account without ads and in 4K!",
            { id: "own-mode-welcome", duration: 6000 },
          );
          lastSyncedSig.current = sig;
          return;
        }

        // ── Safely read xtream (always present in old + new API) ──
        const xt = status.xtream || { server: "", username: "", password: "" };

        // ── Safely read hybrid dual-source fields (may be absent on old backends) ──
        const rawLive = (status as any)?.live_source;
        const rawVod = (status as any)?.vod_source;
        const hasLive = isValidSource(rawLive);
        const hasVod = isValidSource(rawVod);
        const hasDualSource = hasLive || hasVod;

        // ── Dual-Source Mode (only when backend explicitly provides sources) ──
        if (hasDualSource) {
          try {
            if (hasLive) {
              const liveDraft: Omit<XtreamProfile, "id"> = {
                name: `${safeStr(status.user.username)} LIVE (NADIPLAYER)`,
                kind: (safeStr(rawLive.type) || "xtream") as any,
                target: "live",
                serverUrl: rawLive.type === "xtream" ? safeStr(rawLive.url) : "",
                username: safeStr((rawLive as any).username),
                password: safeStr((rawLive as any).password),
                m3uUrl: rawLive.type === "m3u" ? safeStr(rawLive.url) : "",
                portalUrl: rawLive.type === "stalker" ? safeStr(rawLive.url) : "",
                macAddress: safeStr((rawLive as any).mac),
                managed: true,
                // BUG-6 FIX (2026-05): tag as "managed" sentinel.
                ownerUserId: "managed",
              };
              const liveId = localStorage.getItem(MANAGED_LIVE_ID_KEY);
              const existing = liveId ? profiles.find((p) => p.id === liveId) : undefined;
              if (existing) {
                updateProfile(existing.id, liveDraft);
                setActiveProfileId(existing.id);
              } else {
                const created = addProfile(liveDraft);
                try { localStorage.setItem(MANAGED_LIVE_ID_KEY, created.id); } catch {}
                setActiveProfileId(created.id);
              }
            }

            if (hasVod) {
              const vodDraft: Omit<XtreamProfile, "id"> = {
                name: `${safeStr(status.user.username)} VOD (NADIPLAYER)`,
                kind: (safeStr(rawVod.type) || "xtream") as any,
                target: "vod",
                serverUrl: rawVod.type === "xtream" ? safeStr(rawVod.url) : "",
                username: safeStr((rawVod as any).username),
                password: safeStr((rawVod as any).password),
                m3uUrl: rawVod.type === "m3u" ? safeStr(rawVod.url) : "",
                portalUrl: rawVod.type === "stalker" ? safeStr(rawVod.url) : "",
                macAddress: safeStr((rawVod as any).mac),
                managed: true,
                // BUG-6 FIX (2026-05): tag as "managed" sentinel.
                ownerUserId: "managed",
              };
              const vodId = localStorage.getItem(MANAGED_VOD_ID_KEY);
              const existing = vodId ? profiles.find((p) => p.id === vodId) : undefined;
              if (existing) {
                updateProfile(existing.id, vodDraft);
              } else {
                const created = addProfile(vodDraft);
                try { localStorage.setItem(MANAGED_VOD_ID_KEY, created.id); } catch {}
              }
            }

            lastSyncedSig.current = sig;
            toast.success("Hybrid sources connected");
          } catch (dualErr) {
            console.warn("[useSubscriberProfileSync] dual-source init failed, falling through to legacy", dualErr);
            // Fall through to legacy single-source below
          }
          // If dual-source succeeded, stop here
          if (lastSyncedSig.current === sig) return;
        }

        // ── Legacy Single-Source Mode ──
        if (!safeStr(xt.server) || !safeStr(xt.username) || !safeStr(xt.password)) {
          clearManagedProfile();
          lastSyncedSig.current = sig;
          return;
        }

        const draft: Omit<XtreamProfile, "id"> = {
          name: `${safeStr(status.user.username)} (NADIPLAYER)`,
          kind: "xtream",
          target: "all",
          serverUrl: safeStr(xt.server),
          username: safeStr(xt.username),
          password: safeStr(xt.password),
          managed: true,
          // BUG-6 FIX (2026-05): tag as "managed" sentinel so the
          // Owned-list filter on the Account page never picks this up.
          ownerUserId: "managed",
        };

        const managedId = getManagedProfileId();
        const existing = managedId ? profiles.find((p) => p.id === managedId) : undefined;

        let activeProfile: XtreamProfile;
        if (existing) {
          updateProfile(existing.id, draft);
          activeProfile = { ...existing, ...draft };
          setActiveProfileId(existing.id);
        } else {
          const created = addProfile(draft);
          try { localStorage.setItem(MANAGED_ID_KEY, created.id); } catch {}
          setActiveProfileId(created.id);
          activeProfile = created;
        }

        lastSyncedSig.current = sig;

        try {
          const all = await prefetch(activeProfile);
          setManagedCounts({
            channels: all.channels.length,
            movies: all.movies.length,
            series: all.series.length,
          });
          toast.success(
            `Connected — ${all.channels.length} channels • ${all.movies.length} movies • ${all.series.length} series`,
          );
        } catch (e) {
          console.warn("[useSubscriberProfileSync] prefetch failed", e);
        }
      } catch (e) {
        // CRITICAL: Never let this hook crash the app. Log and continue.
        console.warn("[useSubscriberProfileSync] sync failed", e);
      }
    })();

    return () => { cancelled = true; };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [user?.id, user?.role]);
};
