"""
Profile service — business logic for Phase 1.4 (PUT /profiles/me).

Uses the supabase admin client (bypasses RLS). The endpoint layer (routes/profiles.py)
is responsible for extracting user_id from the JWT and applying authorization.

Custom exceptions:
- ProfileUpdateError: unexpected Supabase failure during UPDATE
- ProfileNotFound: reused from auth_service for consistency
"""
import logging
from typing import Any

from app.core.supabase_client import supabase
from app.services.auth_service import MeResult, ProfileNotFound, SupabaseAuthError

logger = logging.getLogger(__name__)


class ProfileUpdateError(Exception):
    """Raised on unexpected Supabase failures during PUT /profiles/me."""
    pass


def update_profile(user_id: str, fields: dict[str, Any]) -> MeResult:
    """
    Update the user's profile with the given fields (partial update).

    Args:
        user_id: from JWT (verified by get_current_user dependency)
        fields: dict of fields to update (e.g., {"phone": "+212...", "city": "Rabat"}).
                Only contains fields explicitly provided by the caller
                (use model_dump(exclude_unset=True) upstream).

    Returns:
        MeResult: the full updated profile (firstname, lastname, phone, profession,
                  city, role + email from auth.users).

    Raises:
        ProfileNotFound: no profile row exists for this user_id (data inconsistency)
        ProfileUpdateError: unexpected Supabase failure on UPDATE
        SupabaseAuthError: cannot fetch email from auth.users
    """
    # 1. Apply UPDATE only if there are fields to update
    if fields:
        try:
            supabase.table("profiles").update(fields).eq("id", user_id).execute()
        except Exception as e:
            logger.error("Profile UPDATE failed for user_id=%s: %s", user_id, e)
            raise ProfileUpdateError(f"Failed to update profile: {e}") from e

    # 2. Fetch updated profile
    profile_response = (
        supabase.table("profiles")
        .select("firstname, lastname, phone, profession, city, role")
        .eq("id", user_id)
        .maybe_single()
        .execute()
    )

    if profile_response.data is None:
        raise ProfileNotFound(f"No profile found for user_id={user_id}")

    # 3. Fetch email from auth.users (separate, since we need it for MeResult)
    try:
        auth_response = supabase.auth.admin.get_user_by_id(user_id)
        user_email = auth_response.user.email
    except Exception as e:
        logger.error("Failed to fetch auth.users email for user_id=%s: %s", user_id, e)
        raise SupabaseAuthError(f"Could not fetch user email: {e}") from e

    p = profile_response.data
    return MeResult(
        user_id=user_id,
        email=user_email,
        role=p["role"],
        firstname=p["firstname"],
        lastname=p["lastname"],
        phone=p.get("phone"),
        profession=p.get("profession"),
        city=p.get("city"),
    )
