import { createClient } from 'https://esm.sh/@supabase/supabase-js@2.39.3';

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

interface NotificationRow {
  id: string;
  user_id: string;
  type: 'follow' | 'appreciate' | 'comment' | 'chain' | 'mention' | 'follow_request' | 'new_follower' | 'request_accepted';
  actor_id: string;
  post_id: string | null;
  comment_id: string | null;
  metadata: Record<string, unknown>;
  is_read: boolean;
  created_at: string;
}

interface NotificationResponse extends NotificationRow {
  actor: {
    id: string;
    handle: string;
    display_name: string;
    avatar_url: string | null;
  };
  post?: {
    id: string;
    body: string;
  } | null;
}

Deno.serve(async (req) => {
  // Handle CORS preflight
  if (req.method === 'OPTIONS') {
    return new Response('ok', { headers: corsHeaders });
  }

  try {
    const supabaseUrl = Deno.env.get('SUPABASE_URL') ?? '';
    const anonKey = Deno.env.get('SUPABASE_ANON_KEY') ?? '';
    const serviceRoleKey = Deno.env.get('SUPABASE_SERVICE_ROLE_KEY') ?? '';

    const supabaseClient = createClient(supabaseUrl, anonKey, {
      global: {
        headers: {
          Authorization: req.headers.get('Authorization') ?? '',
          apikey: anonKey,
        },
      },
    });

    const adminClient = createClient(supabaseUrl, serviceRoleKey);

    // Get authenticated user (explicit token from header)
    const authHeader =
      req.headers.get('Authorization') ?? req.headers.get('authorization') ?? '';
    const token = authHeader.startsWith('Bearer ')
      ? authHeader.slice('Bearer '.length)
      : authHeader;
    const {
      data: { user },
      error: authError,
    } = await supabaseClient.auth.getUser(token || undefined);

    if (authError || !user) {
      console.error('Auth error:', authError?.message ?? 'No user found');
      console.error('Auth header present:', !!authHeader, 'Length:', authHeader?.length ?? 0);
      return new Response(JSON.stringify({
        error: 'Unauthorized',
        code: 401,
        message: authError?.message ?? 'Invalid JWT'
      }), {
        status: 401,
        headers: { ...corsHeaders, 'Content-Type': 'application/json' },
      });
    }

    const url = new URL(req.url);
    const limit = parseInt(url.searchParams.get('limit') || '20');
    const offset = parseInt(url.searchParams.get('offset') || '0');
    const unreadOnly = url.searchParams.get('unread_only') === 'true';
    const includeArchived = url.searchParams.get('include_archived') === 'true';

    // Handle different HTTP methods
    if (req.method === 'GET') {
      // Build query
      let query = adminClient
        .from('notifications')
        .select(`
          id,
          user_id,
          type,
          actor_id,
          post_id,
          comment_id,
          metadata,
          is_read,
          archived_at,
          created_at,
          actor:actor_id (
            id,
            handle,
            display_name,
            avatar_url
          ),
          post:post_id (
            id,
            body
          )
        `)
        .eq('user_id', user.id)
        .order('created_at', { ascending: false })
        .range(offset, offset + limit - 1);

      if (!includeArchived) {
        query = query.is('archived_at', null);
      }

      if (unreadOnly) {
        query = query.eq('is_read', false);
      }

      const { data: notifications, error } = await query;

      if (error) {
        return new Response(JSON.stringify({ error: error.message }), {
          status: 400,
          headers: { ...corsHeaders, 'Content-Type': 'application/json' },
        });
      }

      return new Response(JSON.stringify({ notifications }), {
        headers: { ...corsHeaders, 'Content-Type': 'application/json' },
      });
    }

    if (req.method === 'PATCH' || req.method === 'POST') {
      // Mark notifications as read
      const body = await req.json();
      const { notification_ids, mark_all_read, archive_ids, archive_all } = body;
      const archiveAt = new Date().toISOString();
      let didAction = false;

      if (archive_all) {
        didAction = true;
        const { error } = await adminClient
          .from('notifications')
          .update({ archived_at: archiveAt, is_read: true })
          .eq('user_id', user.id)
          .is('archived_at', null);

        if (error) {
          return new Response(JSON.stringify({ error: error.message }), {
            status: 400,
            headers: { ...corsHeaders, 'Content-Type': 'application/json' },
          });
        }
      }

      if (archive_ids && Array.isArray(archive_ids)) {
        didAction = true;
        const { error } = await adminClient
          .from('notifications')
          .update({ archived_at: archiveAt, is_read: true })
          .in('id', archive_ids)
          .eq('user_id', user.id);

        if (error) {
          return new Response(JSON.stringify({ error: error.message }), {
            status: 400,
            headers: { ...corsHeaders, 'Content-Type': 'application/json' },
          });
        }
      }

      if (mark_all_read) {
        didAction = true;
        // Mark all notifications as read
        const { error } = await adminClient
          .from('notifications')
          .update({ is_read: true })
          .eq('user_id', user.id)
          .eq('is_read', false)
          .is('archived_at', null);

        if (error) {
          return new Response(JSON.stringify({ error: error.message }), {
            status: 400,
            headers: { ...corsHeaders, 'Content-Type': 'application/json' },
          });
        }

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

      if (notification_ids && Array.isArray(notification_ids)) {
        didAction = true;
        // Mark specific notifications as read
        const { error } = await adminClient
          .from('notifications')
          .update({ is_read: true })
          .in('id', notification_ids)
          .eq('user_id', user.id)
          .is('archived_at', null);

        if (error) {
          return new Response(JSON.stringify({ error: error.message }), {
            status: 400,
            headers: { ...corsHeaders, 'Content-Type': 'application/json' },
          });
        }

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

      if (!didAction) {
        return new Response(JSON.stringify({ error: 'Invalid request body' }), {
        status: 400,
        headers: { ...corsHeaders, 'Content-Type': 'application/json' },
        });
      }

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

    // Method not allowed
    return new Response(JSON.stringify({ error: 'Method not allowed' }), {
      status: 405,
      headers: { ...corsHeaders, 'Content-Type': 'application/json' },
    });
  } catch (error) {
    return new Response(JSON.stringify({ error: error.message }), {
      status: 500,
      headers: { ...corsHeaders, 'Content-Type': 'application/json' },
    });
  }
});
