import "jsr:@supabase/functions-js/edge-runtime.d.ts";
import { createClient } from "https://esm.sh/@supabase/supabase-js@2.57.4";
import { edgeLogger, startRequest, endRequest } from '../_shared/logger.ts';

const corsHeaders = {
  'Access-Control-Allow-Origin': '*',
  'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type',
};

const CLOUDFLARE_ACCOUNT_ID = Deno.env.get('CLOUDFLARE_ACCOUNT_ID');
const CLOUDFLARE_API_TOKEN = Deno.env.get('CLOUDFLARE_IMAGES_API_TOKEN');

// Validate configuration at startup
if (!CLOUDFLARE_ACCOUNT_ID || !CLOUDFLARE_API_TOKEN) {
  edgeLogger.error('Missing Cloudflare configuration', {
    action: 'oauth_profile_init',
    hasAccountId: !!CLOUDFLARE_ACCOUNT_ID,
    hasApiToken: !!CLOUDFLARE_API_TOKEN,
  });
  edgeLogger.error('Please configure CLOUDFLARE_ACCOUNT_ID and CLOUDFLARE_IMAGES_API_TOKEN in Supabase Edge Function secrets', {
    action: 'oauth_profile_init'
  });
}

interface GoogleUserMetadata {
  email?: string;
  name?: string;
  picture?: string;
  email_verified?: boolean;
}

interface DiscordUserMetadata {
  email?: string;
  name?: string;              // "username#0" format
  full_name?: string;         // "username" without discriminator
  custom_claims?: {
    global_name?: string;     // Display name like "PacNPal"
  };
  avatar_url?: string;        // Full CDN URL
  picture?: string;           // Alternative full CDN URL
  provider_id?: string;       // Discord user ID
  sub?: string;               // Alternative Discord user ID
  email_verified?: boolean;
  phone_verified?: boolean;
  iss?: string;
}

async function ensureUniqueUsername(
  supabase: any,
  baseUsername: string,
  userId: string,
  maxAttempts: number = 10
): Promise<string> {
  let username = baseUsername.toLowerCase();
  let attempt = 0;

  while (attempt < maxAttempts) {
    const { data: existing } = await supabase
      .from('profiles')
      .select('user_id')
      .eq('username', username)
      .neq('user_id', userId)
      .maybeSingle();

    if (!existing) {
      return username;
    }

    attempt++;
    username = `${baseUsername.toLowerCase()}_${attempt}`;
  }

  // Fallback to UUID-based username
  return `user_${userId.substring(0, 8)}`;
}

Deno.serve(async (req) => {
  const tracking = startRequest();
  
  if (req.method === 'OPTIONS') {
    return new Response(null, { headers: corsHeaders });
  }

  try {
    const authHeader = req.headers.get('Authorization');
    if (!authHeader) {
      return new Response(JSON.stringify({ error: 'Missing authorization header' }), {
        status: 401,
        headers: { ...corsHeaders, 'Content-Type': 'application/json' },
      });
    }

    const supabaseUrl = Deno.env.get('SUPABASE_URL')!;
    const supabaseKey = Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!;
    const supabase = createClient(supabaseUrl, supabaseKey);

    // Verify JWT and get user
    const token = authHeader.replace('Bearer ', '');
    const { data: { user }, error: authError } = await supabase.auth.getUser(token);
    
    if (authError || !user) {
      edgeLogger.error('Authentication failed', { action: 'oauth_profile', error: authError, requestId: tracking.requestId });
      return new Response(JSON.stringify({ error: 'Unauthorized' }), {
        status: 401,
        headers: { ...corsHeaders, 'Content-Type': 'application/json' },
      });
    }

    edgeLogger.info('Processing profile for user', { action: 'oauth_profile', userId: user.id, requestId: tracking.requestId });

    // CRITICAL: Check ban status immediately
    const { data: banProfile } = await supabase
      .from('profiles')
      .select('banned, ban_reason')
      .eq('user_id', user.id)
      .single();
    
    if (banProfile?.banned) {
      const duration = endRequest(tracking);
      const message = banProfile.ban_reason 
        ? `Your account has been suspended. Reason: ${banProfile.ban_reason}`
        : 'Your account has been suspended. Contact support for assistance.';
      
      edgeLogger.info('User is banned, rejecting authentication', { 
        action: 'oauth_profile_banned',
        requestId: tracking.requestId, 
        duration,
        hasBanReason: !!banProfile.ban_reason 
      });
      
      return new Response(JSON.stringify({ 
        error: 'Account suspended',
        message,
        ban_reason: banProfile.ban_reason,
        requestId: tracking.requestId 
      }), {
        status: 403,
        headers: { ...corsHeaders, 'Content-Type': 'application/json', 'X-Request-ID': tracking.requestId },
      });
    }

    const provider = user.app_metadata?.provider;
    
    // For Discord, data is in identities[0].identity_data, not user_metadata
    let userMetadata = user.user_metadata;
    if (provider === 'discord' && user.identities && user.identities.length > 0) {
      const discordIdentity = user.identities.find(i => i.provider === 'discord');
      if (discordIdentity) {
        userMetadata = discordIdentity.identity_data || {};
        
        edgeLogger.info('Discord identity_data', {
          action: 'oauth_profile_discord',
          requestId: tracking.requestId,
          hasAvatarUrl: !!(userMetadata as DiscordUserMetadata).avatar_url,
          hasFullName: !!(userMetadata as DiscordUserMetadata).full_name,
          hasGlobalName: !!(userMetadata as DiscordUserMetadata).custom_claims?.global_name,
          hasProviderId: !!(userMetadata as DiscordUserMetadata).provider_id,
          hasEmail: !!(userMetadata as DiscordUserMetadata).email
        });
      } else {
        edgeLogger.warn('Discord provider found but no Discord identity in user.identities', { action: 'oauth_profile_discord', requestId: tracking.requestId });
      }
    }

    let avatarUrl: string | null = null;
    let displayName: string | null = null;
    let usernameBase: string | null = null;

    // Extract provider-specific data
    if (provider === 'google') {
      const googleData = userMetadata as GoogleUserMetadata;
      avatarUrl = googleData.picture || null;
      displayName = googleData.name || null;
      usernameBase = googleData.email?.split('@')[0] || null;
      edgeLogger.info('Google user', { action: 'oauth_profile_google', requestId: tracking.requestId, avatarUrl, displayName, usernameBase });
    } else if (provider === 'discord') {
      const discordData = userMetadata as DiscordUserMetadata;
      
      // Extract Discord user ID from provider_id or sub
      const discordId = discordData.provider_id || discordData.sub || null;
      
      // Extract display name: custom_claims.global_name > full_name > name
      displayName = discordData.custom_claims?.global_name || discordData.full_name || discordData.name || null;
      
      // Extract username base: full_name or name without discriminator
      usernameBase = discordData.full_name || discordData.name?.split('#')[0] || null;
      
      // Extract email
      const discordEmail = discordData.email || null;
      
      // Use the avatar URL that Supabase already provides (full CDN URL)
      avatarUrl = discordData.avatar_url || discordData.picture || null;
      
      // Validation logging
      if (!discordId) {
        edgeLogger.error('Discord user ID missing from provider_id/sub - OAuth data incomplete', { action: 'oauth_profile_discord', requestId: tracking.requestId });
      }
      
      if (!usernameBase) {
        edgeLogger.warn('Discord username missing - using ID as fallback', { action: 'oauth_profile_discord', requestId: tracking.requestId });
        usernameBase = discordId;
      }
      
      edgeLogger.info('Discord user (Supabase format)', { 
        action: 'oauth_profile_discord',
        requestId: tracking.requestId,
        avatarUrl, 
        displayName, 
        usernameBase,
        discordId,
        email: discordEmail,
        hasAvatar: !!avatarUrl,
        source: discordData.avatar_url ? 'avatar_url' : discordData.picture ? 'picture' : 'none'
      });
    } else {
      edgeLogger.info('Unsupported provider', { action: 'oauth_profile', provider, requestId: tracking.requestId });
      return new Response(JSON.stringify({ success: true, message: 'Provider not supported' }), {
        headers: { ...corsHeaders, 'Content-Type': 'application/json' },
      });
    }

    // Check if profile already has avatar
    const { data: profile } = await supabase
      .from('profiles')
      .select('avatar_image_id, username')
      .eq('user_id', user.id)
      .single();

    if (profile?.avatar_image_id) {
      const duration = endRequest(tracking);
      edgeLogger.info('Avatar already exists, skipping', { action: 'oauth_profile', requestId: tracking.requestId, duration });
      return new Response(JSON.stringify({ success: true, message: 'Avatar already exists', requestId: tracking.requestId }), {
        headers: { ...corsHeaders, 'Content-Type': 'application/json', 'X-Request-ID': tracking.requestId },
      });
    }

    let cloudflareImageId: string | null = null;
    let cloudflareImageUrl: string | null = null;

    // Download and upload avatar to Cloudflare
    if (avatarUrl) {
      // Validate secrets before attempting upload
      if (!CLOUDFLARE_ACCOUNT_ID || !CLOUDFLARE_API_TOKEN) {
        edgeLogger.warn('Cloudflare secrets not configured, skipping avatar upload', { 
          action: 'oauth_profile_upload',
          requestId: tracking.requestId 
        });
        edgeLogger.warn('Missing Cloudflare configuration', {
          action: 'oauth_profile_upload',
          requestId: tracking.requestId,
          accountId: !CLOUDFLARE_ACCOUNT_ID,
          apiToken: !CLOUDFLARE_API_TOKEN,
        });
      } else {
        try {
          edgeLogger.info('Downloading avatar', { action: 'oauth_profile_upload', avatarUrl, requestId: tracking.requestId });
        
        // Download image with timeout
        const controller = new AbortController();
        const timeout = setTimeout(() => controller.abort(), 10000); // 10 second timeout
        
        const imageResponse = await fetch(avatarUrl, {
          signal: controller.signal,
        });
        clearTimeout(timeout);

        if (!imageResponse.ok) {
          throw new Error(`Failed to download avatar: ${imageResponse.statusText}`);
        }

        const imageBlob = await imageResponse.blob();
        
        // Validate image size (max 10MB)
        if (imageBlob.size > 10 * 1024 * 1024) {
          throw new Error('Image too large (max 10MB)');
        }

        edgeLogger.info('Downloaded image', {
          action: 'oauth_profile_upload',
          requestId: tracking.requestId,
          size: imageBlob.size,
          type: imageBlob.type,
        });

        // Get upload URL from Cloudflare
        const uploadUrlResponse = await fetch(
          `https://api.cloudflare.com/client/v4/accounts/${CLOUDFLARE_ACCOUNT_ID}/images/v2/direct_upload`,
          {
            method: 'POST',
            headers: {
              'Authorization': `Bearer ${CLOUDFLARE_API_TOKEN}`,
            },
          }
        );

        if (!uploadUrlResponse.ok) {
          throw new Error('Failed to get Cloudflare upload URL');
        }

        const uploadData = await uploadUrlResponse.json();
        const uploadURL = uploadData.result.uploadURL;

        edgeLogger.info('Got Cloudflare upload URL', { action: 'oauth_profile_upload', requestId: tracking.requestId });

        // Upload to Cloudflare
        const formData = new FormData();
        formData.append('file', imageBlob, 'avatar.png');

        const uploadResponse = await fetch(uploadURL, {
          method: 'POST',
          body: formData,
        });

        if (!uploadResponse.ok) {
          throw new Error('Failed to upload to Cloudflare');
        }

        const result = await uploadResponse.json();
        
        if (result.success) {
          cloudflareImageId = result.result.id;
          cloudflareImageUrl = `https://cdn.thrillwiki.com/images/${cloudflareImageId}/avatar`;
          edgeLogger.info('Uploaded to Cloudflare', { action: 'oauth_profile_upload', requestId: tracking.requestId, cloudflareImageId, cloudflareImageUrl });
        } else {
          throw new Error('Cloudflare upload failed');
        }
        } catch (error) {
          edgeLogger.error('Avatar upload failed', {
            action: 'oauth_profile_upload',
            requestId: tracking.requestId,
            error: error.message,
            provider: provider,
            accountId: CLOUDFLARE_ACCOUNT_ID,
            hasToken: !!CLOUDFLARE_API_TOKEN,
            avatarUrl,
          });
          // Continue without avatar - don't block profile creation
        }
      }
    }

    // Update profile with enhanced data
    const updateData: any = {};
    
    if (cloudflareImageId) {
      updateData.avatar_image_id = cloudflareImageId;
      updateData.avatar_url = cloudflareImageUrl;
    }
    
    if (displayName) {
      updateData.display_name = displayName;
    }

    // Update username if it's currently a generic UUID-based username
    if (usernameBase && profile?.username?.startsWith('user_')) {
      const newUsername = await ensureUniqueUsername(supabase, usernameBase, user.id);
      updateData.username = newUsername;
      edgeLogger.info('Updating generic username', { action: 'oauth_profile', requestId: tracking.requestId, oldUsername: profile.username, newUsername });
    }

    // Only update if we have data to update
    if (Object.keys(updateData).length > 0) {
      const { error: updateError } = await supabase
        .from('profiles')
        .update(updateData)
        .eq('user_id', user.id);

      if (updateError) {
        edgeLogger.error('Failed to update profile', { action: 'oauth_profile', requestId: tracking.requestId, error: updateError });
        return new Response(JSON.stringify({ error: 'Failed to update profile' }), {
          status: 500,
          headers: { ...corsHeaders, 'Content-Type': 'application/json' },
        });
      }

      edgeLogger.info('Profile updated successfully', { action: 'oauth_profile', requestId: tracking.requestId });
    }

    const duration = endRequest(tracking);
    edgeLogger.info('Processing complete', { action: 'oauth_profile', requestId: tracking.requestId, duration });
    
    return new Response(JSON.stringify({
      success: true,
      avatar_uploaded: !!cloudflareImageId,
      profile_updated: Object.keys(updateData).length > 0,
      requestId: tracking.requestId
    }), {
      headers: { ...corsHeaders, 'Content-Type': 'application/json', 'X-Request-ID': tracking.requestId },
    });

  } catch (error) {
    const duration = endRequest(tracking);
    edgeLogger.error('Error in oauth profile processing', { action: 'oauth_profile', requestId: tracking.requestId, duration, error: error.message });
    return new Response(JSON.stringify({ error: error.message, requestId: tracking.requestId }), {
      status: 500,
      headers: { ...corsHeaders, 'Content-Type': 'application/json', 'X-Request-ID': tracking.requestId },
    });
  }
});
