/**
 * Shared member profile helpers used by both the profile and settings pages.
 * Consolidates avatar upload/removal and profile update logic.
 */

import { uploadAvatar, deleteAvatar, isS3Enabled } from '$lib/server/storage';
import { supabaseAdmin } from '$lib/server/supabase';
import type { SupabaseClient } from '@supabase/supabase-js';
import { sanitizeText } from '$lib/server/sanitize';

// ────────────────────────────────────────────────────────────────
// Types
// ────────────────────────────────────────────────────────────────

export interface ProfileUpdateData {
	first_name: string;
	last_name: string;
	phone?: string;
	address?: string;
	nationality?: string[];
}

export interface AvatarUploadResult {
	success: boolean;
	error?: string;
	successMessage?: string;
}

interface MemberAvatarInfo {
	id: string;
	avatar_url?: string | null;
	avatar_path?: string | null;
}

// ────────────────────────────────────────────────────────────────
// Avatar Upload
// ────────────────────────────────────────────────────────────────

/**
 * Handle avatar upload for a member.
 *
 * Supports two modes depending on the caller:
 *  - **Admin mode** (useAdmin = true, default for profile page): uses supabaseAdmin
 *    to bypass RLS and stores all URL variants (local, S3, path).
 *  - **User mode** (useAdmin = false, default for settings page): passes the user's
 *    supabase client to the storage layer and stores only the public URL.
 */
export async function handleAvatarUpload(
	member: MemberAvatarInfo,
	file: File,
	options?: {
		/** Use supabaseAdmin instead of a user-scoped client. Defaults to true. */
		useAdmin?: boolean;
		/** User-scoped Supabase client, required when useAdmin is false. */
		supabase?: SupabaseClient;
	}
): Promise<AvatarUploadResult> {
	const useAdmin = options?.useAdmin ?? true;
	const supabase = options?.supabase;

	// Validate file basics
	if (!file || !file.size) {
		return { success: false, error: 'Please select an image to upload' };
	}

	const allowedTypes = ['image/jpeg', 'image/png', 'image/webp', 'image/gif'];
	if (!allowedTypes.includes(file.type)) {
		return { success: false, error: 'Please upload a valid image (JPEG, PNG, WebP, or GIF)' };
	}

	if (file.size > 5 * 1024 * 1024) {
		return { success: false, error: 'Image must be less than 5MB' };
	}

	// Delete any existing avatar first
	if (member.avatar_path) {
		await deleteAvatar(member.id, member.avatar_path);
	} else {
		await deleteAvatar(member.id);
	}

	// Upload the new avatar
	const result = useAdmin
		? await uploadAvatar(member.id, file)
		: await uploadAvatar(member.id, file, supabase);

	if (!result.success) {
		return { success: false, error: result.error || 'Failed to upload avatar' };
	}

	// Update the member record
	const client = useAdmin ? supabaseAdmin : supabase!;

	if (useAdmin) {
		// Admin mode: store all URL variants for dual-backend storage
		const s3Active = await isS3Enabled();
		const activeUrl = s3Active ? result.s3Url : result.localUrl;

		const { error: updateError } = await client
			.from('members')
			.update({
				avatar_url: activeUrl || result.publicUrl,
				avatar_url_local: result.localUrl || null,
				avatar_url_s3: result.s3Url || null,
				avatar_path: result.path,
				updated_at: new Date().toISOString()
			})
			.eq('id', member.id);

		if (updateError) {
			console.error('Failed to update avatar URL:', updateError);
			return { success: false, error: 'Failed to update profile with new avatar' };
		}
	} else {
		// User mode: store only the public URL
		const { error: updateError } = await client
			.from('members')
			.update({
				avatar_url: result.publicUrl,
				updated_at: new Date().toISOString()
			})
			.eq('id', member.id);

		if (updateError) {
			console.error('Failed to update avatar URL:', updateError);
			return { success: false, error: 'Failed to update profile with new avatar' };
		}
	}

	return {
		success: true,
		successMessage: useAdmin ? 'Avatar uploaded successfully!' : 'Profile picture updated successfully!'
	};
}

// ────────────────────────────────────────────────────────────────
// Avatar Removal
// ────────────────────────────────────────────────────────────────

/**
 * Handle avatar removal for a member.
 *
 * Same admin/user mode distinction as handleAvatarUpload.
 */
export async function handleAvatarRemoval(
	member: MemberAvatarInfo,
	options?: {
		useAdmin?: boolean;
		supabase?: SupabaseClient;
	}
): Promise<AvatarUploadResult> {
	const useAdmin = options?.useAdmin ?? true;
	const supabase = options?.supabase;

	// Delete the avatar from storage backends
	if (member.avatar_path) {
		await deleteAvatar(member.id, member.avatar_path);
	} else if (member.avatar_url) {
		await deleteAvatar(member.id, member.avatar_url);
	} else {
		await deleteAvatar(member.id);
	}

	// Clear avatar fields in the member record
	const client = useAdmin ? supabaseAdmin : supabase!;

	if (useAdmin) {
		const { error: updateError } = await client
			.from('members')
			.update({
				avatar_url: null,
				avatar_url_local: null,
				avatar_url_s3: null,
				avatar_path: null,
				updated_at: new Date().toISOString()
			})
			.eq('id', member.id);

		if (updateError) {
			console.error('Failed to remove avatar URL:', updateError);
			return { success: false, error: 'Failed to update profile' };
		}
	} else {
		const { error: updateError } = await client
			.from('members')
			.update({
				avatar_url: null,
				updated_at: new Date().toISOString()
			})
			.eq('id', member.id);

		if (updateError) {
			console.error('Failed to remove avatar URL:', updateError);
			return { success: false, error: 'Failed to update profile' };
		}
	}

	return {
		success: true,
		successMessage: useAdmin ? 'Avatar removed successfully!' : 'Profile picture removed!'
	};
}

// ────────────────────────────────────────────────────────────────
// Profile Update
// ────────────────────────────────────────────────────────────────

/**
 * Validate and update a member's profile fields.
 *
 * @param memberId  The member's UUID.
 * @param data      The profile fields to update.
 * @param options   Controls which Supabase client is used and which fields are required.
 */
export async function handleProfileUpdate(
	memberId: string,
	data: ProfileUpdateData,
	options?: {
		/** Use supabaseAdmin instead of a user-scoped client. Defaults to true. */
		useAdmin?: boolean;
		/** User-scoped Supabase client, required when useAdmin is false. */
		supabase?: SupabaseClient;
		/** Whether phone, address, and nationality are required. Defaults to false. */
		requireAllFields?: boolean;
	}
): Promise<{ success: boolean; error?: string }> {
	const useAdmin = options?.useAdmin ?? true;
	const requireAllFields = options?.requireAllFields ?? false;

	// Validate required fields
	if (!data.first_name || data.first_name.length < 2) {
		return { success: false, error: 'First name must be at least 2 characters' };
	}

	if (!data.last_name || data.last_name.length < 2) {
		return { success: false, error: 'Last name must be at least 2 characters' };
	}

	if (requireAllFields) {
		if (!data.phone) {
			return { success: false, error: 'Phone number is required' };
		}
		if (!data.address || data.address.length < 10) {
			return { success: false, error: 'Please enter a complete address' };
		}
		if (!data.nationality || data.nationality.length === 0) {
			return { success: false, error: 'Please select at least one nationality' };
		}
	}

	// Sanitize text fields before storage
	const firstName = sanitizeText(data.first_name, 100);
	const lastName = sanitizeText(data.last_name, 100);
	const phone = data.phone ? sanitizeText(data.phone, 50) : data.phone;
	const address = data.address ? sanitizeText(data.address, 500) : data.address;

	// Build the update payload
	const updatePayload: Record<string, unknown> = {
		first_name: firstName,
		last_name: lastName,
		nationality: data.nationality || [],
		updated_at: new Date().toISOString()
	};

	// Only include optional fields if provided or if they are required
	if (requireAllFields) {
		updatePayload.phone = phone;
		updatePayload.address = address;
	} else {
		updatePayload.phone = phone || null;
		updatePayload.address = address || null;
	}

	const client = useAdmin ? supabaseAdmin : options?.supabase;
	if (!client) {
		return { success: false, error: 'Internal error: no database client available' };
	}

	const { error } = await client
		.from('members')
		.update(updatePayload)
		.eq('id', memberId);

	if (error) {
		console.error('Failed to update profile:', error);
		return { success: false, error: 'Failed to update profile. Please try again.' };
	}

	return { success: true };
}
