/**
 * Auto-mirrors admin-configured **shared profiles** into the user's local
 * profile store right after the auth token is verified.
 *
 * STABILITY: Every operation is wrapped in try/catch. If the hybrid fields
 * (source_a_*, source_b_*) are null, undefined, or absent, they are silently
 * ignored. The app never crashes from malformed shared-profile data.
 */
import { useEffect, useRef } from "react";

import { useProfiles } from "@/hooks/useProfiles";
import { nadiDb } from "@/lib/nadiDb";
import {
  apiListSharedProfiles,
  getToken,
  type SharedProfile,
} from "@/lib/nadiAuth";
import type { XtreamProfile } from "@/types/xtream";

const SHARED_ID_PREFIX = "shared:";
const LAST_SYNC_KEY = "nadiplay_shared_profiles_sync";
const ACTIVE_KEY = "nadiplay_active_profile";
const EVENT = "nadiplay-profiles-changed";

export type SharedSyncInfo = {
  userId: string;
  count: number;
  at: number; // epoch ms
};

/** Read the last successful sync summary (for UI "Synced N profiles" badges). */
export const getLastSharedSync = (): SharedSyncInfo | null => {
  try {
    const raw = localStorage.getItem(LAST_SYNC_KEY);
    return raw ? (JSON.parse(raw) as SharedSyncInfo) : null;
  } catch {
    return null;
  }
};

/** Safely coerce to string — never returns null/undefined. */
const s = (v: unknown): string =>
  (v != null && typeof v === "string") ? v : "";

const sharedLocalId = (sp: SharedProfile): string =>
  `${SHARED_ID_PREFIX}${s(sp.id) || s(sp.name) || "unknown"}`;

const toLocalProfile = (sp: SharedProfile): XtreamProfile => {
  const base: XtreamProfile = {
    id: sharedLocalId(sp),
    name: s(sp.name) || "Shared Profile",
    kind: (sp.kind === "m3u" || sp.kind === "stalker") ? sp.kind : "xtream",
    serverUrl: "",
    username: "",
    password: "",
    managed: true,
    // BUG-6 FIX (2026-05): "shared" sentinel keeps this entry OUT of
    // the per-user "Owned" filter on the Account page.
    ownerUserId: "shared",
  };
  if (sp.kind === "m3u") {
    return { ...base, m3uUrl: s(sp.m3u_url) || undefined, m3uContent: s(sp.m3u_content) || undefined };
  }
  if (sp.kind === "stalker") {
    return { ...base, portalUrl: s(sp.portal_url), macAddress: s(sp.mac_address).toUpperCase() };
  }
  return { ...base, serverUrl: s(sp.server), username: s(sp.username), password: s(sp.password) };
};

/**
 * Convert a hybrid shared profile into TWO local profiles (Source A = live,
 * Source B = vod). Returns an array of 0..2 extra profiles.
 * Returns EMPTY if source_a/b fields are null, undefined, or empty.
 */
const toHybridProfiles = (sp: SharedProfile): XtreamProfile[] => {
  const result: XtreamProfile[] = [];
  try {
    const saServer = s(sp.source_a_server);
    if (saServer) {
      result.push({
        id: `${SHARED_ID_PREFIX}${s(sp.id) || s(sp.name)}:live`,
        name: `${s(sp.name) || "Shared"} LIVE`,
        kind: (s(sp.source_a_kind) || "xtream") as any,
        target: "live",
        serverUrl: saServer,
        username: s(sp.source_a_username),
        password: s(sp.source_a_password),
        managed: true,
        // BUG-6 FIX (2026-05): tag as "shared".
        ownerUserId: "shared",
      });
    }
    const sbServer = s(sp.source_b_server);
    if (sbServer) {
      result.push({
        id: `${SHARED_ID_PREFIX}${s(sp.id) || s(sp.name)}:vod`,
        name: `${s(sp.name) || "Shared"} VOD`,
        kind: (s(sp.source_b_kind) || "xtream") as any,
        target: "vod",
        serverUrl: sbServer,
        username: s(sp.source_b_username),
        password: s(sp.source_b_password),
        managed: true,
        // BUG-6 FIX (2026-05): tag as "shared".
        ownerUserId: "shared",
      });
    }
  } catch (e) {
    console.warn("[useSharedProfilesSync] toHybridProfiles error", e);
  }
  return result;
};

export const useSharedProfilesSync = (
  user: { id: string; role: string; xtream_mode?: "shared" | "own" } | null,
) => {
  const { setActiveProfileId } = useProfiles();
  const lastSyncedUserId = useRef<string | null>(null);

  useEffect(() => {
    if (!user || !getToken()) return;
    if (lastSyncedUserId.current === user.id) return;

    let cancelled = false;

    (async () => {
      try {
        // ── BUG-7 HARD BLOCK (2026-05): if the user object from
        // login already says xtream_mode === "own", we MUST NOT
        // fetch or inject ANY shared profiles. This is the
        // CLIENT-SIDE gate — works even if the backend hasn't been
        // updated to return empty profiles for own-mode users.
        if (user.xtream_mode === "own") {
          // Purge any existing shared profiles from IndexedDB
          try {
            const existing = await nadiDb.profiles.toArray();
            let purged = 0;
            for (const p of existing) {
              if (p?.id?.startsWith(SHARED_ID_PREFIX)) {
                try {
                  const currentActive = localStorage.getItem(ACTIVE_KEY);
                  if (currentActive === p.id) {
                    localStorage.removeItem(ACTIVE_KEY);
                    setActiveProfileId(null);
                  }
                } catch { /* noop */ }
                await nadiDb.profiles.delete(p.id);
                purged += 1;
              }
            }
            if (purged > 0) {
              console.info(`[useSharedProfilesSync] OWN-MODE: purged ${purged} shared profiles`);
            }
          } catch (e) {
            console.warn("[useSharedProfilesSync] own-mode purge error", e);
          }
          try {
            localStorage.setItem(LAST_SYNC_KEY, JSON.stringify({
              userId: user.id, count: 0, at: Date.now(),
            }));
          } catch { /* noop */ }
          window.dispatchEvent(new Event(EVENT));
          lastSyncedUserId.current = user.id;
          return; // ← STOP. Do NOT fetch shared profiles at all.
        }

        const res = await apiListSharedProfiles();
        if (cancelled) return;

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

        const shared = Array.isArray(res?.profiles) ? res.profiles : [];

        // ── BUG-7 FIX (2026-05): "Own server" users get empty list ──
        // The backend now returns empty profiles for "own" mode users.
        // When profiles list is empty, we MUST purge ALL existing
        // shared:* entries from IndexedDB so the user never sees or
        // loads content from admin shared profiles.
        if (shared.length === 0) {
          try {
            const existing = await nadiDb.profiles.toArray();
            let purged = 0;
            for (const p of existing) {
              if (p?.id?.startsWith(SHARED_ID_PREFIX)) {
                // If the active profile was a shared one, clear it
                try {
                  const currentActive = localStorage.getItem(ACTIVE_KEY);
                  if (currentActive === p.id) {
                    localStorage.removeItem(ACTIVE_KEY);
                    setActiveProfileId(null);
                  }
                } catch { /* noop */ }
                await nadiDb.profiles.delete(p.id);
                purged += 1;
              }
            }
            if (purged > 0) {
              console.info(`[useSharedProfilesSync] purged ${purged} shared profiles (user has own-mode or no shared profiles)`);
            }
          } catch (purgeErr) {
            console.warn("[useSharedProfilesSync] purge error", purgeErr);
          }

          // Persist sync metadata (0 profiles)
          try {
            localStorage.setItem(LAST_SYNC_KEY, JSON.stringify({
              userId: user.id,
              count: 0,
              at: Date.now(),
            }));
          } catch { /* storage quota — non-fatal */ }

          window.dispatchEvent(new Event(EVENT));
          lastSyncedUserId.current = user.id;
          return; // ← STOP. Do NOT upsert anything.
        }

        // Build valid ID set (safe — every field checked for null)
        const validIds = new Set<string>();
        for (const sp of shared) {
          if (!sp) continue;
          validIds.add(sharedLocalId(sp));
          if (s(sp.source_a_server)) validIds.add(`${SHARED_ID_PREFIX}${s(sp.id) || s(sp.name)}:live`);
          if (s(sp.source_b_server)) validIds.add(`${SHARED_ID_PREFIX}${s(sp.id) || s(sp.name)}:vod`);
        }

        // Read + prune stale shared:* entries
        try {
          const existing = await nadiDb.profiles.toArray();
          for (const p of existing) {
            if (p?.id?.startsWith(SHARED_ID_PREFIX) && !validIds.has(p.id)) {
              await nadiDb.profiles.delete(p.id);
            }
          }
        } catch (pruneErr) {
          console.warn("[useSharedProfilesSync] prune error", pruneErr);
        }

        // Upsert current shared entries + hybrid sub-profiles
        for (const sp of shared) {
          if (!sp) continue;
          try {
            await nadiDb.profiles.put(toLocalProfile(sp));
            const hybrids = toHybridProfiles(sp);
            for (const hp of hybrids) {
              await nadiDb.profiles.put(hp);
            }
          } catch (upsertErr) {
            console.warn("[useSharedProfilesSync] upsert error for", sp?.name, upsertErr);
          }
        }

        // Pick an active profile if none yet
        let currentActive: string | null = null;
        try { currentActive = localStorage.getItem(ACTIVE_KEY); } catch { /* no-op */ }
        if (!currentActive && shared.length > 0) {
          try { setActiveProfileId(sharedLocalId(shared[0])); } catch { /* no-op */ }
        }

        // Persist sync metadata
        try {
          localStorage.setItem(LAST_SYNC_KEY, JSON.stringify({
            userId: user.id,
            count: shared.length,
            at: Date.now(),
          }));
        } catch { /* storage quota — non-fatal */ }

        window.dispatchEvent(new Event(EVENT));
        lastSyncedUserId.current = user.id;
      } catch (e) {
        // CRITICAL: Never let this hook crash the app.
        console.warn("[useSharedProfilesSync] sync failed", e);
      }
    })();

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