from fastapi import APIRouter, HTTPException, status
from app.schemas.auth import RegisterRequest, LoginRequest, TokenResponse
from app.core.supabase_client import supabase, supabase_admin

router = APIRouter(prefix="/auth", tags=["auth"])


def _fetch_role(user_id: str) -> str:
    result = (
        supabase_admin.table("users")
        .select("role")
        .eq("id", user_id)
        .maybe_single()
        .execute()
    )
    return result.data["role"] if result.data else "citizen"


def _fetch_route_for_citizen(user_id: str) -> str | None:
    """
    Busca la primera dirección verificada del ciudadano y devuelve su `route_id`.
    Devuelve None si no hay dirección verificada.
    """
    try:
        res = (
            supabase_admin.table("addresses")
            .select("route_id")
            .eq("user_id", user_id)
            .eq("verified", True)
            .limit(1)
            .maybe_single()
            .execute()
        )
        if res.data and isinstance(res.data, dict):
            return res.data.get("route_id")
    except Exception:
        return None

    return None


@router.post("/register", response_model=TokenResponse, status_code=status.HTTP_201_CREATED)
def register(body: RegisterRequest):
    """
    Registro por email o teléfono. Usa el admin client para confirmar automáticamente
    sin requerir que el usuario verifique su correo.
    """
    if not body.email and not body.phone:
        raise HTTPException(status_code=400, detail="Se requiere email o teléfono")

    if len(body.password) < 6:
        raise HTTPException(status_code=400, detail="La contraseña debe tener al menos 6 caracteres.")

    # Crear usuario con confirmación automática vía service_role (bypasea email confirmation)
    try:
        create_attrs: dict = {"password": body.password}
        if body.email:
            create_attrs["email"] = body.email
            create_attrs["email_confirm"] = True
        else:
            create_attrs["phone"] = body.phone
            create_attrs["phone_confirm"] = True

        admin_resp = supabase_admin.auth.admin.create_user(create_attrs)
    except Exception as e:
        error_msg = str(e)
        if "already registered" in error_msg.lower() or "user already exists" in error_msg.lower() or "already been registered" in error_msg.lower():
            raise HTTPException(status_code=400, detail="El usuario ya está registrado.")
        if "signups are disabled" in error_msg.lower():
            raise HTTPException(status_code=400, detail="El registro de nuevos usuarios está deshabilitado temporalmente.")
        raise HTTPException(status_code=400, detail=error_msg)

    auth_user = admin_resp.user
    if not auth_user:
        raise HTTPException(status_code=400, detail="No se pudo crear el usuario en Supabase Auth")

    # Crear entrada en public.users con el rol y nombre elegidos
    try:
        supabase_admin.table("users").upsert(
            {"id": str(auth_user.id), "role": body.role, "name": body.name}
        ).execute()
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Error al guardar el usuario: {e}")

    # Iniciar sesión para obtener el JWT
    try:
        if body.email:
            session_resp = supabase.auth.sign_in_with_password(
                {"email": body.email, "password": body.password}
            )
        else:
            session_resp = supabase.auth.sign_in_with_password(
                {"phone": body.phone, "password": body.password}
            )
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Usuario creado pero no se pudo iniciar sesión: {e}")

    # Guardar dirección inicial si viene en el payload (evita un segundo HTTP call desde Flutter)
    saved_route_id: str | None = None
    
    calle = body.address_calle or body.addressCalle
    colonia = body.address_colonia or body.addressColonia
    label = body.address_label or body.addressLabel or "Mi Casa"
    lat = body.address_lat if body.address_lat is not None else body.addressLat
    lng = body.address_lng if body.address_lng is not None else body.addressLng

    if calle and colonia:
        try:
            from app.services.simulation import get_colonias
            mapping = get_colonias()
            match = next(
                (c for c in mapping if c.get("colonia", "").lower() == colonia.lower() or c.get("nombre", "").lower() == colonia.lower()),
                None,
            )
            if match:
                addr_data: dict = {
                    "user_id": str(auth_user.id),
                    "label": label,
                    "calle": calle,
                    "colonia": colonia,
                    "route_id": match["routeId"],
                    "verified": False,
                }
                if lat is not None:
                    addr_data["lat"] = lat
                if lng is not None:
                    addr_data["lng"] = lng
                
                try:
                    supabase_admin.table("addresses").insert(addr_data).execute()
                    saved_route_id = match["routeId"]
                except Exception as db_err:
                    if "PGRST204" in str(db_err) or "lat" in str(db_err):
                        addr_data.pop("lat", None)
                        addr_data.pop("lng", None)
                        supabase_admin.table("addresses").insert(addr_data).execute()
                        saved_route_id = match["routeId"]
                    else:
                        raise db_err
        except Exception as e:
            print(f"[register] No se pudo guardar la dirección inicial: {e}")

    return TokenResponse(
        access_token=session_resp.session.access_token,
        user_id=str(auth_user.id),
        role=body.role,
        route_id=saved_route_id,
    )


@router.post("/login", response_model=TokenResponse)
def login(body: LoginRequest):
    """Login por email o teléfono; devuelve JWT de Supabase."""
    if not body.email and not body.phone:
        raise HTTPException(status_code=400, detail="Se requiere email o teléfono")

    try:
        if body.email:
            resp = supabase.auth.sign_in_with_password(
                {"email": body.email, "password": body.password}
            )
        else:
            resp = supabase.auth.sign_in_with_password(
                {"phone": body.phone, "password": body.password}
            )
    except Exception:
        raise HTTPException(status_code=401, detail="Credenciales inválidas")

    auth_user = resp.user
    user_id = str(auth_user.id)
    role = _fetch_role(user_id)

    route_id = None
    if role == 'citizen':
        route_id = _fetch_route_for_citizen(user_id)

    return TokenResponse(
        access_token=resp.session.access_token,
        user_id=user_id,
        role=role,
        route_id=route_id,
    )
