import { supabase } from './supabase';
import type {
  Territory,
  TerritoryManager,
  TerritoryApplication,
  Lead,
  Commission,
  TrainingProgress,
  Achievement,
  TerritoryManagerAchievement,
  ExpenseReport,
  TMNotification,
  ReferralLink,
  MarketingMaterial,
  ApplicationFormData,
  LeadFormData,
  ExpenseReportFormData,
  TerritoryManagerStats,
  LeaderboardEntry,
  TerritoryManagerAPI
} from './territory-manager-types';

class TerritoryManagerAPIClient implements TerritoryManagerAPI {
  
  // Applications
  async submitApplication(data: ApplicationFormData): Promise<TerritoryApplication> {
    const applicationData = {
      email: data.personalInfo.email,
      full_name: data.personalInfo.fullName,
      phone: data.personalInfo.phone,
      address: data.personalInfo.address,
      desired_territory: data.preferences.desiredTerritory,
      has_transportation: data.preferences.hasTransportation,
      has_event_experience: data.preferences.hasEventExperience,
      motivation: data.preferences.motivation,
      consent: data.consent,
      documents: {
        // File uploads would be handled separately
      }
    };

    const { data: result, error } = await supabase
      .from('territory_applications')
      .insert(applicationData)
      .select()
      .single();

    if (error) throw error;
    return result;
  }

  async getApplications(status?: string): Promise<TerritoryApplication[]> {
    let query = supabase
      .from('territory_applications')
      .select('*')
      .order('created_at', { ascending: false });

    if (status) {
      query = query.eq('status', status);
    }

    const { data, error } = await query;
    if (error) throw error;
    return data || [];
  }

  async reviewApplication(id: string, action: 'approve' | 'reject', notes?: string): Promise<void> {
    const { data: user } = await supabase.auth.getUser();
    if (!user.user) throw new Error('User not authenticated');

    const updateData = {
      status: action === 'approve' ? 'approved' : 'rejected',
      reviewed_by: user.user.id,
      reviewed_at: new Date().toISOString(),
      review_notes: notes
    };

    const { error } = await supabase
      .from('territory_applications')
      .update(updateData)
      .eq('id', id);

    if (error) throw error;

    // If approved, create territory manager record
    if (action === 'approve') {
      const { data: application } = await supabase
        .from('territory_applications')
        .select('*')
        .eq('id', id)
        .single();

      if (application) {
        await this.createTerritoryManagerFromApplication(application);
      }
    }
  }

  private async createTerritoryManagerFromApplication(application: TerritoryApplication): Promise<void> {
    // First, create or get user
    const { data: existingUser } = await supabase
      .from('users')
      .select('id')
      .eq('email', application.email)
      .single();

    let userId = existingUser?.id;

    if (!userId) {
      // Create Supabase Auth user first
      const { data: authUser, error: authError } = await supabase.auth.admin.createUser({
        email: application.email,
        password: Math.random().toString(36).slice(-8) + Math.random().toString(36).slice(-8), // Generate temporary password
        email_confirm: true,
        user_metadata: {
          full_name: application.full_name,
          role: 'territory_manager'
        }
      });

      if (authError) throw authError;
      
      // Create user record in users table
      const { data: newUser, error: userError } = await supabase
        .from('users')
        .insert({
          id: authUser.user.id,
          email: application.email,
          name: application.full_name,
          role: 'territory_manager'
        })
        .select()
        .single();

      if (userError) throw userError;
      userId = newUser.id;
    }

    // Create territory manager record
    const { error } = await supabase
      .from('territory_managers')
      .insert({
        user_id: userId,
        status: 'active',
        approved_date: new Date().toISOString(),
        approved_by: application.reviewed_by,
        profile: {
          full_name: application.full_name,
          phone: application.phone,
          address: application.address,
          has_transportation: application.has_transportation,
          has_event_experience: application.has_event_experience,
          motivation: application.motivation
        },
        documents: application.documents
      });

    if (error) throw error;
  }

  // Territory Managers
  async getTerritoryManager(id: string): Promise<TerritoryManager> {
    const { data, error } = await supabase
      .from('territory_managers')
      .select('*')
      .eq('id', id)
      .single();

    if (error) throw error;
    return data;
  }

  async updateTerritoryManager(id: string, data: Partial<TerritoryManager>): Promise<TerritoryManager> {
    const { data: result, error } = await supabase
      .from('territory_managers')
      .update(data)
      .eq('id', id)
      .select()
      .single();

    if (error) throw error;
    return result;
  }

  async getTerritoryManagerStats(id: string): Promise<TerritoryManagerStats> {
    // Get commission data
    const { data: commissions } = await supabase
      .from('commissions')
      .select('*')
      .eq('territory_manager_id', id);

    const totalCommission = commissions?.reduce((sum, c) => sum + c.total_commission, 0) || 0;
    
    const currentMonth = new Date().toISOString().slice(0, 7); // YYYY-MM format
    const currentMonthCommission = commissions?.filter(c => 
      c.created_at.startsWith(currentMonth)
    ).reduce((sum, c) => sum + c.total_commission, 0) || 0;

    // Get events referred
    const { data: events } = await supabase
      .from('events')
      .select('id')
      .eq('created_by', id); // Assuming events have a created_by field for referrals

    const totalEventsReferred = events?.length || 0;

    // Calculate success rate (events that actually happened vs referred)
    const successRate = totalEventsReferred > 0 ? 
      (commissions?.filter(c => c.status === 'paid').length || 0) / totalEventsReferred : 0;

    // Get achievements
    const { data: achievements } = await supabase
      .from('territory_manager_achievements')
      .select('*')
      .eq('territory_manager_id', id);

    const achievementsEarned = achievements?.length || 0;

    // Get pending payouts
    const pendingPayouts = commissions?.filter(c => c.status === 'unpaid').length || 0;

    return {
      total_commission: totalCommission,
      current_month_commission: currentMonthCommission,
      total_events_referred: totalEventsReferred,
      success_rate: successRate,
      rank: 1, // TODO: Calculate actual rank
      achievements_earned: achievementsEarned,
      pending_payouts: pendingPayouts
    };
  }

  // Leads
  async createLead(data: LeadFormData): Promise<Lead> {
    const { data: user } = await supabase.auth.getUser();
    if (!user.user) throw new Error('User not authenticated');

    // Get territory manager ID for current user
    const { data: tm } = await supabase
      .from('territory_managers')
      .select('id')
      .eq('user_id', user.user.id)
      .single();

    if (!tm) throw new Error('Territory manager not found');

    const leadData = {
      territory_manager_id: tm.id,
      event_name: data.eventName,
      organizer_contact: data.organizerContact,
      event_details: data.eventDetails,
      notes: data.notes ? [data.notes] : [],
      follow_up_date: data.followUpDate
    };

    const { data: result, error } = await supabase
      .from('leads')
      .insert(leadData)
      .select()
      .single();

    if (error) throw error;
    return result;
  }

  async getLeads(territoryManagerId: string): Promise<Lead[]> {
    const { data, error } = await supabase
      .from('leads')
      .select('*')
      .eq('territory_manager_id', territoryManagerId)
      .order('created_at', { ascending: false });

    if (error) throw error;
    return data || [];
  }

  async updateLead(id: string, data: Partial<Lead>): Promise<Lead> {
    const { data: result, error } = await supabase
      .from('leads')
      .update(data)
      .eq('id', id)
      .select()
      .single();

    if (error) throw error;
    return result;
  }

  async deleteLead(id: string): Promise<void> {
    const { error } = await supabase
      .from('leads')
      .delete()
      .eq('id', id);

    if (error) throw error;
  }

  // Commissions
  async getCommissions(territoryManagerId: string): Promise<Commission[]> {
    const { data, error } = await supabase
      .from('commissions')
      .select('*')
      .eq('territory_manager_id', territoryManagerId)
      .order('created_at', { ascending: false });

    if (error) throw error;
    return data || [];
  }

  async calculateCommission(eventId: string): Promise<Commission> {
    // This would be called when an event is converted from a lead
    // Implementation depends on how event sales are tracked
    throw new Error('Not implemented');
  }

  // Training
  async getTrainingProgress(territoryManagerId: string): Promise<TrainingProgress[]> {
    const { data, error } = await supabase
      .from('training_progress')
      .select('*')
      .eq('territory_manager_id', territoryManagerId)
      .order('created_at', { ascending: false });

    if (error) throw error;
    return data || [];
  }

  async updateTrainingProgress(territoryManagerId: string, moduleId: string, score?: number): Promise<void> {
    const { error } = await supabase
      .from('training_progress')
      .upsert({
        territory_manager_id: territoryManagerId,
        module_id: moduleId,
        completed_at: new Date().toISOString(),
        score: score
      });

    if (error) throw error;
  }

  // Achievements
  async getAchievements(): Promise<Achievement[]> {
    const { data, error } = await supabase
      .from('achievements')
      .select('*')
      .eq('is_active', true)
      .order('created_at', { ascending: false });

    if (error) throw error;
    return data || [];
  }

  async getTerritoryManagerAchievements(territoryManagerId: string): Promise<TerritoryManagerAchievement[]> {
    const { data, error } = await supabase
      .from('territory_manager_achievements')
      .select('*')
      .eq('territory_manager_id', territoryManagerId)
      .order('earned_at', { ascending: false });

    if (error) throw error;
    return data || [];
  }

  // Expense Reports
  async submitExpenseReport(data: ExpenseReportFormData): Promise<ExpenseReport> {
    const { data: user } = await supabase.auth.getUser();
    if (!user.user) throw new Error('User not authenticated');

    const { data: tm } = await supabase
      .from('territory_managers')
      .select('id')
      .eq('user_id', user.user.id)
      .single();

    if (!tm) throw new Error('Territory manager not found');

    const expenseData = {
      territory_manager_id: tm.id,
      event_id: data.eventId,
      mileage: data.mileage,
      receipts: [], // File uploads would be handled separately
      total_amount: data.mileage * 0.65 // Standard IRS mileage rate
    };

    const { data: result, error } = await supabase
      .from('expense_reports')
      .insert(expenseData)
      .select()
      .single();

    if (error) throw error;
    return result;
  }

  async getExpenseReports(territoryManagerId: string): Promise<ExpenseReport[]> {
    const { data, error } = await supabase
      .from('expense_reports')
      .select('*')
      .eq('territory_manager_id', territoryManagerId)
      .order('created_at', { ascending: false });

    if (error) throw error;
    return data || [];
  }

  // Notifications
  async getNotifications(territoryManagerId: string): Promise<TMNotification[]> {
    const { data, error } = await supabase
      .from('tm_notifications')
      .select('*')
      .eq('territory_manager_id', territoryManagerId)
      .order('created_at', { ascending: false });

    if (error) throw error;
    return data || [];
  }

  async markNotificationAsRead(id: string): Promise<void> {
    const { error } = await supabase
      .from('tm_notifications')
      .update({ read: true })
      .eq('id', id);

    if (error) throw error;
  }

  // Referrals
  async generateReferralLink(territoryManagerId: string, eventType?: string): Promise<ReferralLink> {
    const { data: tm } = await supabase
      .from('territory_managers')
      .select('referral_code')
      .eq('id', territoryManagerId)
      .single();

    if (!tm) throw new Error('Territory manager not found');

    const baseUrl = `${window.location.origin}/e/`;
    const referralUrl = `${baseUrl}?ref=${tm.referral_code}${eventType ? `&type=${eventType}` : ''}`;
    
    // Generate QR code (would use QR code library)
    const qrCodeUrl = `${window.location.origin}/api/qr-code?data=${encodeURIComponent(referralUrl)}`;

    const linkData = {
      territory_manager_id: territoryManagerId,
      url: referralUrl,
      qr_code_url: qrCodeUrl,
      event_type: eventType,
      campaign_name: `${eventType || 'general'}-${Date.now()}`,
      clicks: 0,
      conversions: 0
    };

    // This would be stored in a referral_links table
    // For now, return the generated link
    return {
      id: crypto.randomUUID(),
      ...linkData,
      created_at: new Date().toISOString()
    };
  }

  async getReferralLinks(territoryManagerId: string): Promise<ReferralLink[]> {
    // Would query referral_links table
    // For now, return empty array
    return [];
  }

  // Leaderboard
  async getLeaderboard(period: 'monthly' | 'quarterly' | 'yearly' = 'monthly'): Promise<LeaderboardEntry[]> {
    // This would be a complex query joining multiple tables
    // For now, return empty array
    return [];
  }

  // Marketing Materials
  async getMarketingMaterials(): Promise<MarketingMaterial[]> {
    // This would query a marketing_materials table
    // For now, return empty array
    return [];
  }

  // Territories
  async getTerritories(): Promise<Territory[]> {
    const { data, error } = await supabase
      .from('territories')
      .select('*')
      .order('name');

    if (error) throw error;
    return data || [];
  }

  async assignTerritory(territoryId: string, territoryManagerId: string): Promise<void> {
    const { error } = await supabase
      .from('territory_managers')
      .update({ territory_id: territoryId })
      .eq('id', territoryManagerId);

    if (error) throw error;

    // Also update the territory
    const { error: territoryError } = await supabase
      .from('territories')
      .update({ assigned_to: territoryManagerId })
      .eq('id', territoryId);

    if (territoryError) throw territoryError;
  }
}

export const territoryManagerAPI = new TerritoryManagerAPIClient();