from typing import Optional
from sqlalchemy.exc import IntegrityError
from sqlalchemy.ext.asyncio import AsyncSession
from fastapi import APIRouter, Depends, HTTPException, Query, status

from src.core.database import get_db
from src.services.times import TimeService
from src.core.auth import require_enterprise_or_front, AuthContext
from src.schemas.times import TimeCreate, TimeUpdate, TimeResponse
from src.core.api_responses import (
    build_success_payload,
    SuccessResponse,
    ErrorResponse,
)

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

time_service = TimeService()


@router.post(
    "/criar",
    summary="Criar time",
    description="Cria um novo time vinculado a uma empresa.",
    status_code=status.HTTP_201_CREATED,
    response_model=SuccessResponse,
    responses={
        201: {"description": "Time criado com sucesso"},
        400: {"description": "Dados inválidos", "model": ErrorResponse},
        401: {
            "description": "Credenciais inválidas ou ausentes",
            "model": ErrorResponse,
        },
        500: {"description": "Erro interno", "model": ErrorResponse},
    },
)
async def criar_time(
    payload: TimeCreate,
    db: AsyncSession = Depends(get_db),
    auth_ctx: AuthContext = Depends(require_enterprise_or_front),
) -> SuccessResponse:
    """Criar um novo time."""
    if auth_ctx.get("type") == "enterprise":
        if payload.empresa_id != auth_ctx["empresa"].id:
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail="Não autorizado a criar time para outra empresa",
            )
    try:
        time = await time_service.create_time(db, payload)
        return build_success_payload(
            data=TimeResponse.model_validate(time),
            message=f"Time criado com sucesso (ID: {time.id})",
        )
    except IntegrityError:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="Erro ao criar time. Verifique os dados fornecidos.",
        )
    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Erro ao criar time: {str(e)}",
        )


@router.get(
    "/{time_id}",
    summary="Obter time por ID",
    description="Recupera os detalhes de um time específico.",
    status_code=status.HTTP_200_OK,
    response_model=SuccessResponse,
    responses={
        200: {"description": "Time encontrado"},
        404: {"description": "Time não encontrado", "model": ErrorResponse},
        401: {
            "description": "Credenciais inválidas ou ausentes",
            "model": ErrorResponse,
        },
    },
)
async def obter_time(
    time_id: int,
    db: AsyncSession = Depends(get_db),
    auth_ctx: AuthContext = Depends(require_enterprise_or_front),
) -> SuccessResponse:
    """Obter time por ID."""
    time = await time_service.get_time(db, time_id)
    if not time:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Time não encontrado",
        )
    if auth_ctx.get("type") == "enterprise":
        if time.empresa_id != auth_ctx["empresa"].id:
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail="Time não pertence à sua empresa",
            )
    return build_success_payload(
        data=TimeResponse.model_validate(time),
        message="Time encontrado",
    )


@router.get(
    "/empresa/{empresa_id}",
    summary="Listar times de uma empresa",
    description="Lista todos os times vinculados a uma empresa específica.",
    status_code=status.HTTP_200_OK,
    response_model=SuccessResponse,
    responses={
        200: {
            "description": "Times listados com sucesso"},
        401: {
            "description": "Credenciais inválidas ou ausentes",
            "model": ErrorResponse},
    },
)
async def listar_times_empresa(
    empresa_id: str,
    db: AsyncSession = Depends(get_db),
    auth_ctx: AuthContext = Depends(require_enterprise_or_front),
) -> SuccessResponse:
    """Listar times de uma empresa."""
    if auth_ctx.get("type") == "enterprise":
        if empresa_id != auth_ctx["empresa"].id:
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail="Não autorizado a listar times de outra empresa",
            )
    times = await time_service.get_times_by_empresa(db, empresa_id)
    return build_success_payload(
        data=[TimeResponse.model_validate(t) for t in times],
        message=f"Total de {len(times)} time(s) encontrado(s)",
    )


@router.get(
    "",
    summary="Listar times",
    description="Lista todos os times com filtros opcionais.",
    status_code=status.HTTP_200_OK,
    response_model=SuccessResponse,
    responses={
        200: {"description": "Times listados com sucesso"},
        401: {
            "description": "Credenciais inválidas ou ausentes",
            "model": ErrorResponse,
        },
    },
)
async def listar_times(
    empresa_id: Optional[str] = Query(
        None, description="Filtrar por empresa_id"
    ),
    nome: Optional[str] = Query(
        None, description="Filtrar por nome"
    ),
    db: AsyncSession = Depends(get_db),
    auth_ctx: AuthContext = Depends(require_enterprise_or_front),
) -> SuccessResponse:
    """Listar todos os times."""
    if auth_ctx.get("type") == "enterprise":
        empresa_id = auth_ctx["empresa"].id
    times = await time_service.list_times(db, empresa_id=empresa_id, nome=nome)
    return build_success_payload(
        data=[TimeResponse.model_validate(t) for t in times],
        message=f"Total de {len(times)} time(s) encontrado(s)",
    )


@router.put(
    "/{time_id}",
    summary="Atualizar time",
    description="Atualiza os dados de um time específico.",
    status_code=status.HTTP_200_OK,
    response_model=SuccessResponse,
    responses={
        200: {"description": "Time atualizado com sucesso"},
        404: {"description": "Time não encontrado", "model": ErrorResponse},
        400: {"description": "Dados inválidos", "model": ErrorResponse},
        401: {
            "description": "Credenciais inválidas ou ausentes",
            "model": ErrorResponse,
        },
    },
)
async def atualizar_time(
    time_id: int,
    payload: TimeUpdate,
    db: AsyncSession = Depends(get_db),
    auth_ctx: AuthContext = Depends(require_enterprise_or_front),
) -> SuccessResponse:
    """Atualizar time."""
    existing_time = await time_service.get_time(db, time_id)
    if not existing_time:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Time não encontrado",
        )
        if existing_time.empresa_id != auth_ctx["empresa"].id:
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail="Time não pertence à sua empresa",
            )
        if payload.empresa_id and payload.empresa_id != auth_ctx["empresa"].id:
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail="Não autorizado a mover time para outra empresa",
            )
    try:
        time = await time_service.update_time(db, time_id, payload)
        return build_success_payload(
            data=TimeResponse.model_validate(time),
            message="Time atualizado com sucesso",
        )
    except IntegrityError:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="Erro ao atualizar time. Verifique os dados fornecidos.",
        )
    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Erro ao atualizar time: {str(e)}",
        )


@router.delete(
    "/{time_id}",
    summary="Deletar time",
    description="Remove um time específico.",
    status_code=status.HTTP_200_OK,
    response_model=SuccessResponse,
    responses={
        200: {"description": "Time deletado com sucesso"},
        404: {"description": "Time não encontrado", "model": ErrorResponse},
        401: {
            "description": "Credenciais inválidas ou ausentes",
            "model": ErrorResponse,
        },
    },
)
async def deletar_time(
    time_id: int,
    db: AsyncSession = Depends(get_db),
    auth_ctx: AuthContext = Depends(require_enterprise_or_front),
) -> SuccessResponse:
    """Deletar time."""
    time = await time_service.get_time(db, time_id)
    if not time:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Time não encontrado",
        )
    if auth_ctx.get("type") == "enterprise":
        if time.empresa_id != auth_ctx["empresa"].id:
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail="Time não pertence à sua empresa",
            )
    success = await time_service.delete_time(db, time_id)
    if not success:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Erro ao deletar time",
        )
    return build_success_payload(
        data=None,
        message="Time deletado com sucesso",
    )
