import { createClient } from 'https://esm.sh/@supabase/supabase-js@2'
import { getAllowedOrigin, getCorsHeaders } from '../_shared/cors.ts'
import { rateLimiters, withRateLimit } from '../_shared/rateLimiter.ts'
import { createEdgeFunction } from '../_shared/edgeFunctionWrapper.ts'
import { validateString } from '../_shared/typeValidation.ts'
import { addSpanEvent } from '../_shared/logger.ts'

// Helper to create authenticated Supabase client
const createAuthenticatedSupabaseClient = (authHeader: string) => {
  const supabaseUrl = Deno.env.get('SUPABASE_URL')
  const supabaseAnonKey = Deno.env.get('SUPABASE_ANON_KEY')
  
  if (!supabaseUrl || !supabaseAnonKey) {
    throw new Error('Missing Supabase environment variables')
  }
  
  return createClient(supabaseUrl, supabaseAnonKey, {
    global: { headers: { Authorization: authHeader } }
  })
}

/**
 * Report ban evasion attempts to system alerts
 */
async function reportBanEvasionToAlerts(
  supabaseClient: any,
  userId: string,
  action: string,
  requestId: string
): Promise<void> {
  try {
    await supabaseClient.rpc('create_system_alert', {
      p_alert_type: 'ban_attempt',
      p_severity: 'high',
      p_message: `Banned user attempted image upload: ${action}`,
      p_metadata: {
        user_id: userId,
        action,
        request_id: requestId,
        timestamp: new Date().toISOString()
      }
    });
  } catch (error) {
    // Non-blocking - log but don't fail the response
  }
}

// Apply strict rate limiting (5 requests/minute) to prevent abuse
const handler = createEdgeFunction(
  {
    name: 'upload-image',
    requireAuth: false, // Auth checked per-method
    corsHeaders: {} // Dynamic CORS
  },
  async (req, context) => {
    const requestOrigin = req.headers.get('origin');
    const allowedOrigin = getAllowedOrigin(requestOrigin);

    // Check if this is a CORS request with a disallowed origin
    if (requestOrigin && !allowedOrigin) {
      addSpanEvent(context.span, 'cors_rejected', { origin: requestOrigin });
      return new Response(
        JSON.stringify({
          error: 'Origin not allowed',
          message: 'The origin of this request is not allowed to access this resource'
        }),
        {
          status: 403,
          headers: { 'Content-Type': 'application/json' }
        }
      );
    }

    const corsHeaders = getCorsHeaders(allowedOrigin);
    context.span.setAttribute('http_method', req.method);
    context.span.setAttribute('action', 'upload_image');

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

    if (!CLOUDFLARE_ACCOUNT_ID || !CLOUDFLARE_IMAGES_API_TOKEN) {
      throw new Error('Missing Cloudflare credentials')
    }

    if (req.method === 'DELETE') {
      // Require authentication for DELETE operations
      const authHeader = req.headers.get('Authorization')
      if (!authHeader) {
        return new Response(
          JSON.stringify({ 
            error: 'Authentication required',
            message: 'Authentication required for delete operations'
          }),
          { 
            status: 401, 
            headers: { ...corsHeaders, 'Content-Type': 'application/json' } 
          }
        )
      }

      const supabase = createAuthenticatedSupabaseClient(authHeader)

      const { data: { user }, error: authError } = await supabase.auth.getUser()
      if (authError || !user) {
        throw new Error('Invalid authentication');
      }

      context.span.setAttribute('user_id', user.id);

      // Check if user is banned
      const { data: profile } = await supabase
        .from('profiles')
        .select('banned')
        .eq('user_id', user.id)
        .single()

      if (profile?.banned) {
        await reportBanEvasionToAlerts(supabase, user.id, 'image_delete', context.requestId);
        addSpanEvent(context.span, 'banned_user_blocked', { action: 'delete' });
        
        return new Response(
          JSON.stringify({ 
            error: 'Account suspended',
            message: 'Account suspended. Contact support for assistance.'
          }),
          { 
            status: 403, 
            headers: { ...corsHeaders, 'Content-Type': 'application/json' } 
          }
        )
      }

      // Delete image from Cloudflare
      const requestBody = await req.json();
      const { imageId } = requestBody;
      
      validateString(imageId, 'imageId', { userId: user.id, requestId: context.requestId });

      // Validate imageId format
      const validImageIdPattern = /^[a-zA-Z0-9_-]{1,100}$/;
      if (!validImageIdPattern.test(imageId)) {
        throw new Error('Invalid imageId format - must be alphanumeric with optional hyphens/underscores (max 100 chars)');
      }

      addSpanEvent(context.span, 'delete_image_start', { imageId });

      const deleteResponse = await fetch(
        `https://api.cloudflare.com/client/v4/accounts/${CLOUDFLARE_ACCOUNT_ID}/images/v1/${imageId}`,
        {
          method: 'DELETE',
          headers: {
            'Authorization': `Bearer ${CLOUDFLARE_IMAGES_API_TOKEN}`,
          },
        }
      )

      const deleteResult = await deleteResponse.json()

      if (!deleteResponse.ok) {
        throw new Error(deleteResult.errors?.[0]?.message || deleteResult.error || 'Failed to delete image');
      }

      addSpanEvent(context.span, 'image_deleted', { imageId });
      return new Response(
        JSON.stringify({ success: true, deleted: true }),
        { headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
      )
    }

    if (req.method === 'POST') {
      // Require authentication for POST operations
      const authHeader = req.headers.get('Authorization')
      if (!authHeader) {
        return new Response(
          JSON.stringify({ 
            error: 'Authentication required',
            message: 'Authentication required for upload operations'
          }),
          { 
            status: 401, 
            headers: { ...corsHeaders, 'Content-Type': 'application/json' } 
          }
        )
      }

      const supabase = createAuthenticatedSupabaseClient(authHeader)

      const { data: { user }, error: authError } = await supabase.auth.getUser()
      if (authError || !user) {
        throw new Error('Invalid authentication');
      }

      context.span.setAttribute('user_id', user.id);

      // Check if user is banned
      const { data: profile } = await supabase
        .from('profiles')
        .select('banned')
        .eq('user_id', user.id)
        .single()

      if (profile?.banned) {
        await reportBanEvasionToAlerts(supabase, user.id, 'image_upload', context.requestId);
        addSpanEvent(context.span, 'banned_user_blocked', { action: 'upload' });
        
        return new Response(
          JSON.stringify({ 
            error: 'Account suspended',
            message: 'Account suspended. Contact support for assistance.'
          }),
          { 
            status: 403, 
            headers: { ...corsHeaders, 'Content-Type': 'application/json' } 
          }
        )
      }

      // Request a direct upload URL from Cloudflare
      let requestBody;
      try {
        requestBody = await req.json();
      } catch (error: unknown) {
        requestBody = {};
      }

      const { metadata = {}, variant = 'public', requireSignedURLs = false } = requestBody;

      addSpanEvent(context.span, 'upload_url_request_start');

      // Create FormData for the request
      const formData = new FormData()
      formData.append('requireSignedURLs', requireSignedURLs.toString())
      
      if (metadata && Object.keys(metadata).length > 0) {
        formData.append('metadata', JSON.stringify(metadata))
      }

      const directUploadResponse = await fetch(
        `https://api.cloudflare.com/client/v4/accounts/${CLOUDFLARE_ACCOUNT_ID}/images/v2/direct_upload`,
        {
          method: 'POST',
          headers: {
            'Authorization': `Bearer ${CLOUDFLARE_IMAGES_API_TOKEN}`,
          },
          body: formData,
        }
      )

      const directUploadResult = await directUploadResponse.json()

      if (!directUploadResponse.ok) {
        throw new Error(directUploadResult.errors?.[0]?.message || directUploadResult.error || 'Unable to create upload URL');
      }

      addSpanEvent(context.span, 'upload_url_created', { imageId: directUploadResult.result.id });

      return new Response(
        JSON.stringify({
          success: true,
          uploadURL: directUploadResult.result.uploadURL,
          id: directUploadResult.result.id,
        }),
        { headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
      )
    } 

    if (req.method === 'GET') {
      // Require authentication for GET operations
      const authHeader = req.headers.get('Authorization')
      if (!authHeader) {
        return new Response(
          JSON.stringify({ 
            error: 'Authentication required',
            message: 'Authentication required for image status operations'
          }),
          { 
            status: 401, 
            headers: { ...corsHeaders, 'Content-Type': 'application/json' } 
          }
        )
      }

      const supabase = createAuthenticatedSupabaseClient(authHeader)

      const { data: { user }, error: authError } = await supabase.auth.getUser()
      if (authError || !user) {
        throw new Error('Invalid authentication');
      }

      context.span.setAttribute('user_id', user.id);

      // Check image status endpoint
      const url = new URL(req.url)
      const imageId = url.searchParams.get('id')
      
      validateString(imageId, 'id', { userId: user.id, requestId: context.requestId });

      addSpanEvent(context.span, 'get_image_status_start', { imageId });

      const imageResponse = await fetch(
        `https://api.cloudflare.com/client/v4/accounts/${CLOUDFLARE_ACCOUNT_ID}/images/v1/${imageId}`,
        {
          headers: {
            'Authorization': `Bearer ${CLOUDFLARE_IMAGES_API_TOKEN}`,
          },
        }
      )

      const imageResult = await imageResponse.json()

      if (!imageResponse.ok) {
        throw new Error(imageResult.errors?.[0]?.message || imageResult.error || 'Unable to retrieve image information');
      }

      // Return the image details with convenient URLs
      const result = imageResult.result
      const baseUrl = `https://cdn.thrillwiki.com/images/${result.id}`
      
      addSpanEvent(context.span, 'image_status_retrieved', { imageId: result.id });
      
      return new Response(
        JSON.stringify({
          success: true,
          id: result.id,
          uploaded: result.uploaded,
          variants: result.variants,
          draft: result.draft,
          urls: result.uploaded ? {
            public: `${baseUrl}/public`,
            thumbnail: `${baseUrl}/thumbnail`,
            medium: `${baseUrl}/medium`,
            large: `${baseUrl}/large`,
            avatar: `${baseUrl}/avatar`,
          } : null
        }),
        { headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
      )
    }

    return new Response(
      JSON.stringify({ 
        error: 'Method not allowed',
        message: 'HTTP method not supported for this endpoint'
      }),
      { 
        status: 405, 
        headers: { ...corsHeaders, 'Content-Type': 'application/json' } 
      }
    )
  }
);

export default withRateLimit(handler, rateLimiters.strict, {} as any);
