/*
 * 인증 컨텍스트 — JWT를 secure-store에 영속, 앱 부팅 시 복원.
 * 활성 워크스페이스(행사) 선택 상태 보관. 비밀번호는 저장하지 않는다.
 */
import React, {
  createContext,
  useCallback,
  useContext,
  useEffect,
  useMemo,
  useState,
} from 'react';
import { setAccessToken } from '../lib/api';
import { landingPathFor } from '../lib/roleTrack';
import { secureDelete, secureGet, secureSet } from '../lib/secureStore';
import type { AuthUser, LoginResponse, WorkspaceDto } from '../lib/types';

const TOKEN_KEY = 'kintex.accessToken';
const USER_KEY = 'kintex.user';
const LANDING_KEY = 'kintex.landing';

interface AuthState {
  ready: boolean;
  token: string | null;
  user: AuthUser | null;
  workspaces: WorkspaceDto[];
  activeEventId: string | null;
  /** 로그인 시 역할로 계산한 랜딩 라우트(콜드 부팅 시 workspaces 미복원 문제 회피용으로 지속). */
  landingPath: string | null;
}

interface AuthContextValue extends AuthState {
  activeWorkspace: WorkspaceDto | null;
  signIn: (res: LoginResponse) => Promise<void>;
  signOut: () => Promise<void>;
  selectWorkspace: (eventId: string) => void;
}

const AuthContext = createContext<AuthContextValue | undefined>(undefined);

export function AuthProvider({ children }: { children: React.ReactNode }) {
  const [state, setState] = useState<AuthState>({
    ready: false,
    token: null,
    user: null,
    workspaces: [],
    activeEventId: null,
    landingPath: null,
  });

  // 부팅 시 토큰 복원
  useEffect(() => {
    let cancelled = false;
    (async () => {
      const token = await secureGet(TOKEN_KEY);
      const userRaw = await secureGet(USER_KEY);
      const landingPath = await secureGet(LANDING_KEY);
      if (cancelled) return;
      const user = userRaw ? (JSON.parse(userRaw) as AuthUser) : null;
      if (token) setAccessToken(token);
      setState((s) => ({ ...s, ready: true, token, user, landingPath }));
    })();
    return () => {
      cancelled = true;
    };
  }, []);

  const signIn = useCallback(async (res: LoginResponse) => {
    setAccessToken(res.accessToken);
    // 역할 우선순위로 랜딩 경로를 계산·지속(콜드 부팅 시 재사용 — workspaces 미복원 misroute 방지).
    const landingPath = landingPathFor({ user: res.user, workspaces: res.workspaces });
    await secureSet(TOKEN_KEY, res.accessToken);
    await secureSet(USER_KEY, JSON.stringify(res.user));
    await secureSet(LANDING_KEY, landingPath);
    setState((s) => ({
      ...s,
      token: res.accessToken,
      user: res.user,
      workspaces: res.workspaces ?? [],
      activeEventId: res.workspaces?.[0]?.eventId ?? null,
      landingPath,
    }));
  }, []);

  const signOut = useCallback(async () => {
    setAccessToken(null);
    await secureDelete(TOKEN_KEY);
    await secureDelete(USER_KEY);
    await secureDelete(LANDING_KEY);
    setState((s) => ({
      ...s,
      token: null,
      user: null,
      workspaces: [],
      activeEventId: null,
      landingPath: null,
    }));
  }, []);

  const selectWorkspace = useCallback((eventId: string) => {
    setState((s) => ({ ...s, activeEventId: eventId }));
  }, []);

  const value = useMemo<AuthContextValue>(() => {
    const activeWorkspace =
      state.workspaces.find((w) => w.eventId === state.activeEventId) ?? null;
    return { ...state, activeWorkspace, signIn, signOut, selectWorkspace };
  }, [state, signIn, signOut, selectWorkspace]);

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

export function useAuth(): AuthContextValue {
  const ctx = useContext(AuthContext);
  if (!ctx) throw new Error('useAuth must be used within AuthProvider');
  return ctx;
}
