"use client";

import {
  createContext,
  useCallback,
  useContext,
  useEffect,
  useMemo,
  useState,
  type ReactNode,
} from "react";
import type { Account, Profile } from "@/lib/profile/types";
import {
  ensureDefaultProfile,
  getAccount,
  getActiveAccountId,
  getActiveProfileId,
  listProfiles,
  setActiveAccountId,
  setActiveProfileId,
} from "@/lib/profile/db";
import { setCachedPreferredUi } from "@/lib/uiSkins";
import { isSupabaseConfigured } from "@/lib/supabase/config";
import {
  ensureLocalMirrorFromCloud,
  wasCloudMigrated,
  migrateLocalProfileToCloud,
} from "@/lib/oauth/cloudAccount";

type ProfileContextValue = {
  ready: boolean;
  profile: Profile | null;
  profiles: Profile[];
  account: Account | null;
  refresh: () => Promise<void>;
  switchProfile: (id: string) => Promise<void>;
  switchAccount: (id: string | null) => Promise<void>;
};

const ProfileContext = createContext<ProfileContextValue | null>(null);

export function ProfileProvider({ children }: { children: ReactNode }) {
  const [ready, setReady] = useState(false);
  const [profile, setProfile] = useState<Profile | null>(null);
  const [profiles, setProfiles] = useState<Profile[]>([]);
  const [account, setAccount] = useState<Account | null>(null);

  const refresh = useCallback(async () => {
    const current = await ensureDefaultProfile();
    const all = await listProfiles();
    setProfiles(all);
    const activeId = getActiveProfileId() ?? current.id;
    const activeProfile = all.find((p) => p.id === activeId) ?? current;
    setProfile(activeProfile);

    let acc: Account | null = null;

    if (isSupabaseConfigured()) {
      try {
        const { createClient } = await import("@/lib/supabase/client");
        const supabase = createClient();
        const {
          data: { session },
        } = await supabase.auth.getSession();
        if (session?.user) {
          acc = await ensureLocalMirrorFromCloud(session.user);
            if (acc) {
            setActiveAccountId(acc.id);
            if (!wasCloudMigrated(acc.id) && activeProfile.id) {
              await migrateLocalProfileToCloud(acc.id, activeProfile.id);
            }
          }
        }
      } catch (e) {
        console.warn("[oauth] session refresh", e);
      }
    }

    if (!acc) {
      const accId = getActiveAccountId();
      if (accId) {
        const local = await getAccount(accId);
        if (local?.authProvider && local.authProvider !== "local") {
          // Stale OAuth mirror without session — clear
          setActiveAccountId(null);
          acc = null;
        } else {
          acc = local ?? null;
          if (!local) setActiveAccountId(null);
        }
      }
    }

    setAccount(acc);
    if (acc?.preferredUi) setCachedPreferredUi(acc.preferredUi);
    else if (activeProfile.settings?.preferredUi) {
      setCachedPreferredUi(activeProfile.settings.preferredUi);
    }
    setReady(true);
  }, []);

  useEffect(() => {
    void refresh();
  }, [refresh]);

  useEffect(() => {
    if (!isSupabaseConfigured()) return;
    let unsub: (() => void) | undefined;
    void (async () => {
      try {
        const { createClient } = await import("@/lib/supabase/client");
        const supabase = createClient();
        const {
          data: { subscription },
        } = supabase.auth.onAuthStateChange(() => {
          void refresh();
        });
        unsub = () => subscription.unsubscribe();
      } catch {
        /* ignore */
      }
    })();
    return () => unsub?.();
  }, [refresh]);

  const switchProfile = useCallback(
    async (id: string) => {
      setActiveProfileId(id);
      await refresh();
    },
    [refresh],
  );

  const switchAccount = useCallback(
    async (id: string | null) => {
      setActiveAccountId(id);
      await refresh();
    },
    [refresh],
  );

  const value = useMemo(
    () => ({
      ready,
      profile,
      profiles,
      account,
      refresh,
      switchProfile,
      switchAccount,
    }),
    [ready, profile, profiles, account, refresh, switchProfile, switchAccount],
  );

  return (
    <ProfileContext.Provider value={value}>{children}</ProfileContext.Provider>
  );
}

export function useProfile() {
  const ctx = useContext(ProfileContext);
  if (!ctx) {
    throw new Error("useProfile must be used within ProfileProvider");
  }
  return ctx;
}
