"""
Servicio para gestionar relaciones entre usuarios y tenants
"""

import logging
from typing import List, Optional

from fastapi import HTTPException
from sqlalchemy import and_
from sqlalchemy.orm import Session

from ..tenants.models import Tenant
from .models import UserTenant

logger = logging.getLogger(__name__)


class UserTenantService:
    """Servicio para gestionar acceso de usuarios a tenants"""

    def __init__(self, db: Session):
        self.db = db

    def add_user_to_tenant(
        self, keycloak_user_id: str, tenant_id: int, role: Optional[str] = None
    ) -> UserTenant:
        """
        Agrega un usuario a un tenant

        Args:
            keycloak_user_id: ID del usuario en Keycloak
            tenant_id: ID del tenant
            role: Rol opcional del usuario en este tenant

        Returns:
            UserTenant creado
        """
        # Verificar que el tenant existe
        tenant = self.db.query(Tenant).filter(Tenant.id == tenant_id).first()
        if not tenant:
            raise HTTPException(status_code=404, detail="Tenant not found")

        # Verificar si la relación ya existe
        existing = (
            self.db.query(UserTenant)
            .filter(
                and_(
                    UserTenant.keycloak_user_id == keycloak_user_id,
                    UserTenant.tenant_id == tenant_id,
                )
            )
            .first()
        )

        if existing:
            # Si existe pero está inactiva, reactivarla
            if not existing.is_active:
                existing.is_active = True
                existing.role = role
                self.db.commit()
                self.db.refresh(existing)
                return existing
            else:
                raise HTTPException(
                    status_code=409, detail="User already has access to this tenant"
                )

        # Crear nueva relación
        user_tenant = UserTenant(
            keycloak_user_id=keycloak_user_id,
            tenant_id=tenant_id,
            role=role,
            is_active=True,
        )

        self.db.add(user_tenant)
        self.db.commit()
        self.db.refresh(user_tenant)
        return user_tenant

    def remove_user_from_tenant(
        self, keycloak_user_id: str, tenant_id: int, soft_delete: bool = True
    ) -> bool:
        """
        Elimina un usuario de un tenant

        Args:
            keycloak_user_id: ID del usuario en Keycloak
            tenant_id: ID del tenant
            soft_delete: Si True, solo marca como inactivo. Si False, elimina físicamente

        Returns:
            True si se eliminó correctamente
        """
        user_tenant = (
            self.db.query(UserTenant)
            .filter(
                and_(
                    UserTenant.keycloak_user_id == keycloak_user_id,
                    UserTenant.tenant_id == tenant_id,
                )
            )
            .first()
        )

        if not user_tenant:
            raise HTTPException(
                status_code=404, detail="User-tenant relationship not found"
            )

        if soft_delete:
            user_tenant.is_active = False
            self.db.commit()
        else:
            self.db.delete(user_tenant)
            self.db.commit()

        return True

    def get_user_tenants(self, keycloak_user_id: str) -> List[Tenant]:
        """
        Obtiene todos los tenants a los que tiene acceso un usuario

        Args:
            keycloak_user_id: ID del usuario en Keycloak

        Returns:
            Lista de tenants
        """
        user_tenants = (
            self.db.query(UserTenant)
            .filter(
                and_(
                    UserTenant.keycloak_user_id == keycloak_user_id,
                    UserTenant.is_active,
                )
            )
            .all()
        )

        tenant_ids = [ut.tenant_id for ut in user_tenants]

        tenants = (
            self.db.query(Tenant)
            .filter(and_(Tenant.id.in_(tenant_ids), Tenant.is_active))
            .all()
        )

        return tenants

    def get_tenant_users(self, tenant_id: int) -> List[UserTenant]:
        """
        Obtiene todos los usuarios que tienen acceso a un tenant

        Args:
            tenant_id: ID del tenant

        Returns:
            Lista de relaciones UserTenant
        """
        return (
            self.db.query(UserTenant)
            .filter(and_(UserTenant.tenant_id == tenant_id, UserTenant.is_active))
            .all()
        )

    def user_has_access_to_tenant(self, keycloak_user_id: str, tenant_id: int) -> bool:
        """
        Verifica si un usuario tiene acceso a un tenant

        Args:
            keycloak_user_id: ID del usuario en Keycloak
            tenant_id: ID del tenant

        Returns:
            True si tiene acceso, False en caso contrario
        """
        user_tenant = (
            self.db.query(UserTenant)
            .filter(
                and_(
                    UserTenant.keycloak_user_id == keycloak_user_id,
                    UserTenant.tenant_id == tenant_id,
                    UserTenant.is_active,
                )
            )
            .first()
        )

        return user_tenant is not None

    def update_user_role_in_tenant(
        self, keycloak_user_id: str, tenant_id: int, role: str
    ) -> UserTenant:
        """
        Actualiza el rol de un usuario en un tenant

        Args:
            keycloak_user_id: ID del usuario en Keycloak
            tenant_id: ID del tenant
            role: Nuevo rol

        Returns:
            UserTenant actualizado
        """
        user_tenant = (
            self.db.query(UserTenant)
            .filter(
                and_(
                    UserTenant.keycloak_user_id == keycloak_user_id,
                    UserTenant.tenant_id == tenant_id,
                )
            )
            .first()
        )

        if not user_tenant:
            raise HTTPException(
                status_code=404, detail="User-tenant relationship not found"
            )

        user_tenant.role = role
        self.db.commit()
        self.db.refresh(user_tenant)
        return user_tenant
