import { getSupabaseServiceClient } from '../config/supabase';
import { User, CreateUserInput } from './types';
import logger from '../utils/logger';

export class UserModel {
  /**
   * Create a new user
   */
  static async create(userData: CreateUserInput): Promise<User> {
    const { email, name, password, role = 'user' } = userData;
    
    const supabase = getSupabaseServiceClient();
    
    try {
      const { data, error } = await supabase
        .from('users')
        .insert({
          email,
          name,
          password_hash: password, // Note: In production, this should be hashed
          role
        })
        .select()
        .single();
      
      if (error) {
        logger.error('Error creating user:', error);
        throw error;
      }
      
      logger.info(`Created user: ${email}`);
      return data;
    } catch (error) {
      logger.error('Error creating user:', error);
      throw error;
    }
  }

  /**
   * Find user by ID
   */
  static async findById(id: string): Promise<User | null> {
    const supabase = getSupabaseServiceClient();
    
    try {
      const { data, error } = await supabase
        .from('users')
        .select('*')
        .eq('id', id)
        .eq('is_active', true)
        .single();
      
      if (error) {
        if (error.code === 'PGRST116') {
          return null; // No rows returned
        }
        logger.error('Error finding user by ID:', error);
        throw error;
      }
      
      return data;
    } catch (error) {
      logger.error('Error finding user by ID:', error);
      throw error;
    }
  }

  /**
   * Find user by email
   */
  static async findByEmail(email: string): Promise<User | null> {
    const supabase = getSupabaseServiceClient();
    
    try {
      const { data, error } = await supabase
        .from('users')
        .select('*')
        .eq('email', email)
        .eq('is_active', true)
        .single();
      
      if (error) {
        if (error.code === 'PGRST116') {
          return null; // No rows returned
        }
        logger.error('Error finding user by email:', error);
        throw error;
      }
      
      return data;
    } catch (error) {
      logger.error('Error finding user by email:', error);
      throw error;
    }
  }

  /**
   * Get all users (for admin)
   */
  static async findAll(limit = 100, offset = 0): Promise<User[]> {
    const supabase = getSupabaseServiceClient();
    
    try {
      const { data, error } = await supabase
        .from('users')
        .select('*')
        .eq('is_active', true)
        .order('created_at', { ascending: false })
        .range(offset, offset + limit - 1);
      
      if (error) {
        logger.error('Error finding all users:', error);
        throw error;
      }
      
      return data || [];
    } catch (error) {
      logger.error('Error finding all users:', error);
      throw error;
    }
  }

  /**
   * Update user
   */
  static async update(id: string, updates: Partial<User>): Promise<User | null> {
    const supabase = getSupabaseServiceClient();
    
    try {
      const { data, error } = await supabase
        .from('users')
        .update({
          ...updates,
          updated_at: new Date().toISOString()
        })
        .eq('id', id)
        .select()
        .single();
      
      if (error) {
        if (error.code === 'PGRST116') {
          return null; // No rows returned
        }
        logger.error('Error updating user:', error);
        throw error;
      }
      
      return data;
    } catch (error) {
      logger.error('Error updating user:', error);
      throw error;
    }
  }

  /**
   * Update last login
   */
  static async updateLastLogin(id: string): Promise<void> {
    const supabase = getSupabaseServiceClient();
    
    try {
      const { error } = await supabase
        .from('users')
        .update({
          last_login: new Date().toISOString(),
          updated_at: new Date().toISOString()
        })
        .eq('id', id);
      
      if (error) {
        logger.error('Error updating last login:', error);
        throw error;
      }
    } catch (error) {
      logger.error('Error updating last login:', error);
      throw error;
    }
  }

  /**
   * Delete user (soft delete)
   */
  static async delete(id: string): Promise<boolean> {
    const supabase = getSupabaseServiceClient();
    
    try {
      const { error } = await supabase
        .from('users')
        .update({
          is_active: false,
          updated_at: new Date().toISOString()
        })
        .eq('id', id);
      
      if (error) {
        logger.error('Error deleting user:', error);
        throw error;
      }
      
      return true;
    } catch (error) {
      logger.error('Error deleting user:', error);
      throw error;
    }
  }

  /**
   * Count users
   */
  static async count(): Promise<number> {
    const supabase = getSupabaseServiceClient();
    
    try {
      const { count, error } = await supabase
        .from('users')
        .select('*', { count: 'exact', head: true })
        .eq('is_active', true);
      
      if (error) {
        logger.error('Error counting users:', error);
        throw error;
      }
      
      return count || 0;
    } catch (error) {
      logger.error('Error counting users:', error);
      throw error;
    }
  }

  /**
   * Check if email exists
   */
  static async emailExists(email: string): Promise<boolean> {
    const supabase = getSupabaseServiceClient();
    
    try {
      const { data, error } = await supabase
        .from('users')
        .select('id')
        .eq('email', email)
        .eq('is_active', true)
        .limit(1);
      
      if (error) {
        logger.error('Error checking if email exists:', error);
        throw error;
      }
      
      return (data && data.length > 0);
    } catch (error) {
      logger.error('Error checking if email exists:', error);
      throw error;
    }
  }
} 