import { User, AuthChangeEvent, Session } from '@supabase/supabase-js';
import { TLUserPreferences } from '@tldraw/tldraw';
import { supabase } from '../../supabaseClient';
import { storageService, StorageKeys } from './localStorageService';
import { logger } from '../../debugConfig';

export interface CCUser {
  id: string;
  email?: string;
  user_type: string;
  username: string;
  display_name: string;
  school_id?: string | null;
  created_at?: string;
  updated_at?: string;
}

export interface CCUserMetadata {
  username?: string;
  user_type?: string;
  display_name?: string;
  email?: string;
  name?: string;
  preferred_username?: string;
  [key: string]: string | undefined;
}

export function convertToCCUser(user: User, metadata: CCUserMetadata): CCUser {
  // Extract username from various possible sources
  const username = metadata.username || 
                  metadata.preferred_username || 
                  metadata.email?.split('@')[0] || 
                  user.email?.split('@')[0] || 
                  'user';

  // Extract display name from various possible sources
  const displayName = metadata.display_name || 
                     metadata.name || 
                     metadata.preferred_username || 
                     username;

  // Default to student if no user type specified
  const userType = metadata.user_type || 'student';

  return {
    id: user.id,
    email: user.email,
    user_type: userType,
    username,
    display_name: displayName,
    school_id: null,
    created_at: user.created_at,
    updated_at: user.updated_at,
  };
}

export type UserRole =
  | 'email_teacher'
  | 'email_student'
  | 'cc_admin'
  | 'cc_developer'
  | 'super_admin';

// Login response
export interface LoginResponse {
  user: CCUser | null;
  accessToken: string | null;
  userRole: string;
  message: string | null;
}

// Session response
export interface SessionResponse {
  user: CCUser | null;
  accessToken: string | null;
  message: string | null;
}

// Registration response
export interface RegistrationResponse extends LoginResponse {
  user: CCUser;
  accessToken: string | null;
  userRole: UserRole;
  message: string | null;
}

export interface EmailCredentials {
  email: string;
  password: string;
  role: 'email_teacher' | 'email_student';
}

export type AuthCredentials = EmailCredentials;

export const getTldrawPreferences = (user: CCUser): TLUserPreferences => {
  return {
    id: user.id,
    colorScheme: 'system',
  };
};

class AuthService {
  private static instance: AuthService;

  private constructor() {}

  onAuthStateChange(
    callback: (event: AuthChangeEvent, session: Session | null) => void
  ) {
    return supabase.auth.onAuthStateChange((event, session) => {
      logger.info('auth-service', '🔄 Auth state changed', {
        event,
        hasSession: !!session,
        userId: session?.user?.id,
        eventType: event,
      });

      // Ensure we clear storage on signout
      if (event === 'SIGNED_OUT') {
        storageService.clearAll();
      }

      callback(event, session);
    });
  }

  static getInstance(): AuthService {
    if (!AuthService.instance) {
      AuthService.instance = new AuthService();
    }
    return AuthService.instance;
  }

  async getCurrentSession(): Promise<SessionResponse> {
    try {
      const {
        data: { session },
        error,
      } = await supabase.auth.getSession();
      if (error) {
        throw error;
      }

      if (!session) {
        return { user: null, accessToken: null, message: 'No active session' };
      }

      return {
        user: convertToCCUser(
          session.user,
          session.user.user_metadata as CCUserMetadata
        ),
        accessToken: session.access_token,
        message: 'Session retrieved',
      };
    } catch (error) {
      logger.error('auth-service', 'Failed to get current session:', error);
      throw error;
    }
  }

  async getCurrentUser(): Promise<CCUser | null> {
    try {
      const {
        data: { user },
        error,
      } = await supabase.auth.getUser();
      if (error || !user) {
        return null;
      }
      return convertToCCUser(user, user.user_metadata as CCUserMetadata);
    } catch (error) {
      logger.error('auth-service', 'Failed to get current user:', error);
      return null;
    }
  }

  async login({
    email,
    password,
    role,
  }: EmailCredentials): Promise<LoginResponse> {
    try {
      logger.info('auth-service', '🔄 Attempting login', {
        email,
        role,
      });

      const { data, error } = await supabase.auth.signInWithPassword({
        email,
        password,
      });

      if (error) {
        logger.error('auth-service', '❌ Supabase auth error', {
          error: error.message,
          status: error.status,
        });
        throw error;
      }

      if (!data.session) {
        logger.error('auth-service', '❌ No session after login');
        throw new Error('No session after login');
      }

      const ccUser = convertToCCUser(
        data.user,
        data.user.user_metadata as CCUserMetadata
      );

      // Store auth session in storage
      storageService.set(StorageKeys.USER_ROLE, ccUser.user_type);
      storageService.set(StorageKeys.USER, ccUser);
      storageService.set(StorageKeys.SUPABASE_TOKEN, data.session.access_token);
      storageService.set(StorageKeys.SUPABASE_SESSION, data.session);

      logger.info('auth-service', '✅ Login successful', {
        userId: ccUser.id,
        role: ccUser.user_type,
        username: ccUser.username,
      });

      return {
        user: ccUser,
        accessToken: data.session.access_token,
        userRole: ccUser.user_type,
        message: 'Login successful',
      };
    } catch (error) {
      logger.error('auth-service', '❌ Login failed:', error);
      throw error;
    }
  }

  async logout(): Promise<void> {
    try {
      logger.debug('auth-service', '🔄 Attempting logout');
      const { error } = await supabase.auth.signOut({ scope: 'local' });
      if (error) {
        logger.error('auth-service', '❌ Logout failed:', error);
        throw error;
      }
      // Clear all stored data
      storageService.clearAll();
      // Force a refresh of the auth state
      await supabase.auth.refreshSession();
      logger.debug('auth-service', '✅ Logout successful');
    } catch (error) {
      logger.error('auth-service', '❌ Logout failed:', error);
      throw error;
    }
  }
}

export const authService = AuthService.getInstance();
