import { createContext, createResource, createSignal, useContext, type ParentProps, type Accessor, type Setter } from 'solid-js';
import { useNavigate } from '@solidjs/router';

const API = '/api/gateway';

type AuthUser = {
  id: string;
  email: string;
  full_name: string;
  active_role: string;
  email_verified: boolean;
};

type AuthState = {
  user: Accessor<AuthUser | null>;
  isAuthenticated: Accessor<boolean>;
  isLoading: Accessor<boolean>;
  logout: () => void;
  setUser: Setter<AuthUser | null>;
};

const AuthContext = createContext<AuthState>();

function getToken(): string | null {
  if (typeof window === 'undefined') return null;
  return sessionStorage.getItem('nxtgauge_access_token') || null;
}

function clearAuthStorage() {
  if (typeof window === 'undefined') return;
  sessionStorage.removeItem('nxtgauge_access_token');
  sessionStorage.removeItem('nxtgauge_frontend_access_token');
  localStorage.removeItem('nxtgauge_auth_user');
  localStorage.removeItem('nxtgauge_user');
  localStorage.removeItem('nxtgauge_signup_profile_v1');
}

function normalizeRoleValue(value: unknown): string {
  return String(value || '').trim().toUpperCase().replace(/\s+/g, '_');
}

function getStoredPreferredRole(emailHint?: string): string | null {
  if (typeof window === 'undefined') return null;
  const keys = ['nxtgauge_signup_profile_v1', 'nxtgauge_auth_user', 'nxtgauge_user'];
  for (const key of keys) {
    const raw = window.localStorage.getItem(key);
    if (!raw) continue;
    try {
      const parsed = JSON.parse(raw) as Record<string, any>;
      const storedEmail = String(parsed?.email || '').trim().toLowerCase();
      if (emailHint && storedEmail && storedEmail !== emailHint.trim().toLowerCase()) continue;

      const selectedProfessionalRole = normalizeRoleValue(parsed?.selectedProfessionalRole);
      if (selectedProfessionalRole) return selectedProfessionalRole;

      const activeRole = normalizeRoleValue(parsed?.active_role || parsed?.role);
      if (activeRole) return activeRole;
    } catch {
      // Ignore malformed local storage payloads.
    }
  }
  return null;
}

function resolveActiveRole(rawBackendRole: unknown, emailHint?: string): string {
  const backendRole = normalizeRoleValue(rawBackendRole);
  if (backendRole) return backendRole;
  const preferredRole = getStoredPreferredRole(emailHint);
  if (preferredRole) return preferredRole;
  return preferredRole || 'JOB_SEEKER';
}

async function fetchSession(): Promise<AuthUser | null> {
  const token = getToken();
  if (!token) return null;
  try {
    const res = await fetch(`${API}/api/auth/session`, {
      headers: {
        Accept: 'application/json',
        Authorization: `Bearer ${token}`,
      },
      credentials: 'include',
    });
    if (!res.ok) return null;
    const data = await res.json();
    if (!data?.id && !data?.user_id) return null;
    const resolvedActiveRole = resolveActiveRole(data.active_role || data.role, data.email || '');
    return {
      id: data.id || data.user_id,
      email: data.email || '',
      full_name: data.full_name || data.name || '',
      active_role: resolvedActiveRole,
      email_verified: data.email_verified || false,
    };
  } catch {
    return null;
  }
}

export function AuthProvider(props: ParentProps) {
  const [user, setUser] = createSignal<AuthUser | null>(null);
  const [session] = createResource(fetchSession);

  const isLoading = () => session.loading;
  const isAuthenticated = () => !!user() || !!getToken() || (!!session() && !session.error);

  if (session()) {
    setUser(session() as AuthUser | null);
  }

  const logout = () => {
    clearAuthStorage();
    setUser(null);
    if (typeof window !== 'undefined') {
      window.location.href = '/login';
    }
  };

  return (
    <AuthContext.Provider value={{ user, isAuthenticated, isLoading, logout, setUser }}>
      {props.children}
    </AuthContext.Provider>
  );
}

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

export function RequireAuth(props: ParentProps<{ fallback?: string }>) {
  const navigate = useNavigate();
  const auth = useAuth();

  if (auth.isLoading()) {
    return <div class="flex min-h-screen items-center justify-center text-[#6B7280]">Loading...</div>;
  }

  if (!auth.isAuthenticated()) {
    const fallback = props.fallback || '/login';
    navigate(fallback, { replace: true });
    return null;
  }

  return <>{props.children}</>;
}

export { getToken, clearAuthStorage };
