from fastapi import APIRouter, Depends, HTTPException, status

from app.api.dependencies.auth import get_access_token
from app.api.dependencies.permissions import require_permission
from app.application.admin.activity import ActivityService
from app.application.admin.experiments import ExperimentService
from app.schemas.auth import AuthenticatedUser
from app.schemas.admin import ActivityLogListResponse, ExperimentCreate, ExperimentListResponse, ExperimentRead, ExperimentUpdate

router = APIRouter()
service = ExperimentService()
activity_service = ActivityService()


@router.get("", response_model=ExperimentListResponse)
async def list_experiments(
    access_token: str = Depends(get_access_token),
    _: AuthenticatedUser = Depends(require_permission("can_manage_experiments")),
) -> ExperimentListResponse:
    # Admin list should always come from the application/service layer,
    # not from routes talking to Directus directly.
    items = await service.list_experiments(access_token=access_token)
    return ExperimentListResponse(items=items)


@router.get("/{experiment_id}", response_model=ExperimentRead)
async def get_experiment(
    experiment_id: str,
    access_token: str = Depends(get_access_token),
    _: AuthenticatedUser = Depends(require_permission("can_manage_experiments")),
) -> ExperimentRead:
    item = await service.get_experiment(experiment_id, access_token=access_token)
    if not item:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"Experiment '{experiment_id}' not found.",
        )
    return item


@router.post("", response_model=ExperimentRead, status_code=status.HTTP_201_CREATED)
async def create_experiment(
    payload: ExperimentCreate,
    access_token: str = Depends(get_access_token),
    _: AuthenticatedUser = Depends(require_permission("can_manage_experiments")),
) -> ExperimentRead:
    return await service.create_experiment(payload, access_token=access_token)


@router.patch("/{experiment_id}", response_model=ExperimentRead)
async def update_experiment(
    experiment_id: str,
    payload: ExperimentUpdate,
    access_token: str = Depends(get_access_token),
    _: AuthenticatedUser = Depends(require_permission("can_manage_experiments")),
) -> ExperimentRead:
    item = await service.update_experiment(experiment_id, payload, access_token=access_token)
    if not item:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"Experiment '{experiment_id}' not found.",
        )
    return item


@router.get("/{experiment_id}/activity", response_model=ActivityLogListResponse)
async def list_experiment_activity(
    experiment_id: str,
    access_token: str = Depends(get_access_token),
    _: AuthenticatedUser = Depends(require_permission("can_manage_experiments")),
) -> ActivityLogListResponse:
    items = await activity_service.list_for_experiment(
        experiment_id=experiment_id,
        access_token=access_token,
    )
    return ActivityLogListResponse(items=items)
