/**
 * GET /profile/:handle - Get user profile by handle
 * GET /profile/me - Get own profile
 * PATCH /profile - Update own profile
 *
 * Design intent:
 * - Profiles are public (unless blocked)
 * - Shows harmony tier (not score)
 * - Minimal public metrics
 */

import { serve } from 'https://deno.land/std@0.177.0/http/server.ts';
import { createSupabaseClient } from '../_shared/supabase-client.ts';
import { ValidationError } from '../_shared/validation.ts';
import { trySignR2Url } from '../_shared/r2_signer.ts';

const ALLOWED_ORIGIN = Deno.env.get('ALLOWED_ORIGIN') || '*';
const corsHeaders = {
  'Access-Control-Allow-Origin': ALLOWED_ORIGIN,
  'Access-Control-Allow-Methods': 'GET, PATCH',
  'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type',
};

serve(async (req) => {
  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 supabase = createSupabaseClient(authHeader);
    const {
      data: { user },
      error: authError,
    } = await supabase.auth.getUser();

    if (authError || !user) {
      return new Response(JSON.stringify({ error: 'Unauthorized' }), {
        status: 401,
        headers: { ...corsHeaders, 'Content-Type': 'application/json' },
      });
    }

    const url = new URL(req.url);
    const handle = url.searchParams.get('handle');

    // GET /profile/me or /profile?handle=username
    if (req.method === 'GET') {
      let profileQuery;
      let isOwnProfile = false;

      if (handle) {
        // Get profile by handle
        profileQuery = supabase
          .from('profiles')
          .select(
            `
            id,
            handle,
            display_name,
            bio,
            location,
            website,
            interests,
            avatar_url,
            cover_url,
            origin_country,
            is_private,
            is_official,
            created_at,
            trust_state (
              tier
            )
          `
          )
          .eq('handle', handle)
          .single();
      } else {
        // Get own profile
        isOwnProfile = true;
        profileQuery = supabase
          .from('profiles')
          .select(
            `
            id,
            handle,
            display_name,
            bio,
            location,
            website,
            interests,
            avatar_url,
            cover_url,
            origin_country,
            is_private,
            is_official,
            created_at,
            updated_at,
            trust_state (
              harmony_score,
              tier,
              posts_today
            )
          `
          )
          .eq('id', user.id)
          .single();
      }

      const { data: profile, error: profileError } = await profileQuery;

      if (profileError || !profile) {
        return new Response(JSON.stringify({ error: 'Profile not found' }), {
          status: 404,
          headers: { ...corsHeaders, 'Content-Type': 'application/json' },
        });
      }

      // Check if viewing own profile
      if (profile.id === user.id) {
        isOwnProfile = true;
      }

      // Get privacy settings for this profile
      const { data: privacySettings } = await supabase
        .from('profile_privacy_settings')
        .select('*')
        .eq('user_id', profile.id)
        .maybeSingle();

      const profileVisibility = privacySettings?.profile_visibility || 'public';

      // Apply privacy filtering based on viewer relationship
      if (!isOwnProfile && profileVisibility !== 'public') {
        // Check if viewer is following the profile
        const { data: followData } = await supabase
          .from('follows')
          .select('status')
          .eq('follower_id', user.id)
          .eq('following_id', profile.id)
          .maybeSingle();

        const followStatus = followData?.status as string | null;
        const isFollowing = followStatus === 'accepted';
        let isFollowedBy = false;
        if (user.id !== profile.id) {
          const { data: reverseFollow } = await supabase
            .from('follows')
            .select('status')
            .eq('follower_id', profile.id)
            .eq('following_id', user.id)
            .maybeSingle();
          isFollowedBy = reverseFollow?.status === 'accepted';
        }
        const isFriend = isFollowing && isFollowedBy;

        // Check privacy visibility
        if (profile.is_private || profileVisibility === 'private') {
          // Private profiles show minimal info to non-followers
          if (!isFollowing) {
            return new Response(
              JSON.stringify({
                profile: {
                  id: profile.id,
                  handle: profile.handle ?? 'unknown',
                  display_name: profile.display_name ?? 'Anonymous',
                  avatar_url: profile.avatar_url,
                  created_at: profile.created_at,
                  trust_state: profile.trust_state,
                },
                stats: {
                  posts: 0,
                  followers: 0,
                  following: 0,
                },
                is_following: false,
                is_followed_by: isFollowedBy,
                is_friend: isFriend,
                follow_status: followStatus,
                is_private: true,
              }),
              {
                status: 200,
                headers: { ...corsHeaders, 'Content-Type': 'application/json' },
              }
            );
          }
        } else if (profileVisibility === 'followers') {
          // Followers-only profiles hide details from non-followers
          if (!isFollowing) {
            profile.bio = null;
            profile.location = null;
            profile.website = null;
            profile.interests = null;
          }
        }
      }

      // Coalesce null values for older clients
      const safeProfile = {
        ...profile,
        handle: profile.handle ?? 'unknown',
        display_name: profile.display_name ?? 'Anonymous',
      };

      if (safeProfile.avatar_url) {
        safeProfile.avatar_url = await trySignR2Url(safeProfile.avatar_url);
      }
      if (safeProfile.cover_url) {
        safeProfile.cover_url = await trySignR2Url(safeProfile.cover_url);
      }

      // Get post count
      const { count: postCount } = await supabase
        .from('posts')
        .select('*', { count: 'exact', head: true })
        .eq('author_id', safeProfile.id);

      // Get follower/following counts
      const { count: followerCount } = await supabase
        .from('follows')
        .select('*', { count: 'exact', head: true })
        .eq('following_id', safeProfile.id)
        .eq('status', 'accepted');

      const { count: followingCount } = await supabase
        .from('follows')
        .select('*', { count: 'exact', head: true })
        .eq('follower_id', safeProfile.id)
        .eq('status', 'accepted');

      // Check if current user is following this profile
      let isFollowing = false;
      let isFollowedBy = false;
      let isFriend = false;
      let followStatus: string | null = null;
      if (user && user.id !== safeProfile.id) {
        const { data: followData } = await supabase
          .from('follows')
          .select('status')
          .eq('follower_id', user.id)
          .eq('following_id', safeProfile.id)
          .maybeSingle();

        followStatus = followData?.status as string | null;
        isFollowing = followStatus === 'accepted';

        const { data: reverseFollow } = await supabase
          .from('follows')
          .select('status')
          .eq('follower_id', safeProfile.id)
          .eq('following_id', user.id)
          .maybeSingle();
        isFollowedBy = reverseFollow?.status === 'accepted';
        isFriend = isFollowing && isFollowedBy;
      }

      const isPrivateForViewer = (profile.is_private ?? false) && !isFollowing && !isOwnProfile;

      return new Response(
        JSON.stringify({
          profile: safeProfile,
          stats: {
            posts: postCount || 0,
            followers: followerCount || 0,
            following: followingCount || 0,
          },
          is_following: isFollowing,
          is_followed_by: isFollowedBy,
          is_friend: isFriend,
          follow_status: followStatus,
          is_private: isPrivateForViewer,
        }),
        {
          status: 200,
          headers: { ...corsHeaders, 'Content-Type': 'application/json' },
        }
      );
    }

    // PATCH /profile - Update own profile
    if (req.method === 'PATCH') {
      const { handle, display_name, bio, location, website, interests, avatar_url, cover_url } = await req.json();

      const updates: any = {};

      // Handle username changes with 30-day limit
      if (handle !== undefined) {
        if (handle.trim().length < 3 || handle.length > 20) {
          throw new ValidationError('Username must be 3-20 characters', 'handle');
        }
        if (!/^[a-zA-Z0-9_]+$/.test(handle)) {
          throw new ValidationError('Username can only contain letters, numbers, and underscores', 'handle');
        }

        // Check if handle is already taken
        const { data: existingProfile } = await supabase
          .from('profiles')
          .select('id')
          .eq('handle', handle)
          .neq('id', user.id)
          .maybeSingle();

        if (existingProfile) {
          throw new ValidationError('Username is already taken', 'handle');
        }

        // Check 30-day limit
        const { data: canChange, error: canChangeError } = await supabase
          .rpc('can_change_handle', { p_user_id: user.id });

        if (canChangeError || !canChange) {
          throw new ValidationError('You can only change your username once every 30 days', 'handle');
        }

        updates.handle = handle;
      }

      if (display_name !== undefined) {
        if (display_name.trim().length === 0 || display_name.length > 50) {
          throw new ValidationError('Display name must be 1-50 characters', 'display_name');
        }
        updates.display_name = display_name;
      }

      if (bio !== undefined) {
        if (bio && bio.length > 300) {
          throw new ValidationError('Bio must be 300 characters or less', 'bio');
        }
        updates.bio = bio || null;
      }

      if (location !== undefined) {
        if (location && location.length > 100) {
          throw new ValidationError('Location must be 100 characters or less', 'location');
        }
        updates.location = location || null;
      }

      if (website !== undefined) {
        if (website) {
          if (website.length > 200) {
            throw new ValidationError('Website must be 200 characters or less', 'website');
          }
          // Validate URL format and scheme
          try {
            const url = new URL(website.startsWith('http') ? website : `https://${website}`);
            if (!['http:', 'https:'].includes(url.protocol)) {
              throw new ValidationError('Website must be a valid HTTP or HTTPS URL', 'website');
            }
          } catch (error) {
            throw new ValidationError('Website must be a valid URL', 'website');
          }
        }
        updates.website = website || null;
      }

      if (interests !== undefined) {
        if (Array.isArray(interests)) {
          updates.interests = interests;
        } else {
          throw new ValidationError('Interests must be an array', 'interests');
        }
      }

      if (avatar_url !== undefined) {
        updates.avatar_url = avatar_url || null;
      }

      if (cover_url !== undefined) {
        updates.cover_url = cover_url || null;
      }

      if (Object.keys(updates).length === 0) {
        return new Response(JSON.stringify({ error: 'No fields to update' }), {
          status: 400,
          headers: { ...corsHeaders, 'Content-Type': 'application/json' },
        });
      }

      updates.updated_at = new Date().toISOString();

      const { data: profile, error: updateError } = await supabase
        .from('profiles')
        .update(updates)
        .eq('id', user.id)
        .select()
        .single();

      if (updateError) {
        console.error('Error updating profile:', updateError);
        return new Response(JSON.stringify({ 
          error: 'Failed to update profile',
          details: updateError.message,
          code: updateError.code
        }), {
          status: 500,
          headers: { ...corsHeaders, 'Content-Type': 'application/json' },
        });
      }

      return new Response(
        JSON.stringify({
          profile,
          message: 'Profile updated',
        }),
        {
          status: 200,
          headers: { ...corsHeaders, 'Content-Type': 'application/json' },
        }
      );
    }

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

    console.error('Unexpected error:', error);
    return new Response(JSON.stringify({ error: 'Internal server error' }), {
      status: 500,
      headers: { ...corsHeaders, 'Content-Type': 'application/json' },
    });
  }
});
