from datetime import date

from fastapi import APIRouter, Depends, HTTPException, status
from fastapi.responses import StreamingResponse
from sqlalchemy.ext.asyncio import AsyncSession

from src.db.models.app_user import AppUser
from src.api.v1.deps import require_admin, require_executor
from src.db.session import get_db
from src.domain.schemas import (
    BaseListResponse,
    BaseSingleResponse,
    VSPCreate,
    VSPExportRequest,
    VSPInDB,
    VSPUpdate,
)
from src.services.vsp_service import VSPService

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


@router.get("", response_model=BaseListResponse[VSPInDB])
async def get_vsp(
    registration_number: str | None = None,
    address: str | None = None,
    ssp_id: int | None = None,
    open_date_start: date | None = None,
    open_date_end: date | None = None,
    placement_type: str | None = None,
    staff_count_min: int | None = None,
    staff_count_max: int | None = None,
    db: AsyncSession = Depends(get_db),
    current_user: AppUser = Depends(require_executor),
):
    """Получение записей справочника INFO."""
    service = VSPService(db)
    result = await service.get_list(
        user=current_user,
        registration_number=registration_number,
        address=address,
        ssp_id=ssp_id,
        open_date_start=open_date_start,
        open_date_end=open_date_end,
        placement_type=placement_type,
        staff_count_min=staff_count_min,
        staff_count_max=staff_count_max,
        load_org_unit=True,
        is_active=True,
        with_count=True,
    )
    return BaseListResponse(
        success=True,
        message="Список INFO",
        result=[VSPInDB.model_validate(vsp) for vsp in result[1]],
        count=result[0]
    )


@router.get("/dropdown", response_model=BaseListResponse[VSPInDB])
async def get_vsp_dropdown(
    ssp_id: int | None = None,
    form_id: int | None = None,
    db: AsyncSession = Depends(get_db),
    current_user: AppUser = Depends(require_executor),
):
    """Получение записей для выпадающего списка INFO."""
    service = VSPService(db)
    result = await service.get_dropdown(user=current_user, ssp_id=ssp_id, form_id=form_id, with_count=True)
    return BaseListResponse(
        success=True,
        message="Список INFO для выпадающего списка",
        result=[VSPInDB.model_validate(vsp) for vsp in result[1]],
        count=result[0],
    )


@router.post("/export")
async def export_info(
    body: VSPExportRequest,
    db: AsyncSession = Depends(get_db),
    current_user: AppUser = Depends(require_executor),
):
    """Экспорт справочника INFO."""
    service = VSPService(db)
    stream, filename = await service.export_xlsx(
        user=current_user,
        registration_number=body.registration_number,
        address=body.address,
        ssp_ids=body.ssp_ids,
        open_date_start=body.open_date_start,
        open_date_end=body.open_date_end,
        placement_type=body.placement_type,
        staff_count_min=body.staff_count_min,
        staff_count_max=body.staff_count_max,
    )
    return StreamingResponse(
        stream,
        media_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
        headers={"Content-Disposition": f'attachment; filename="{filename}"'},
    )


@router.post("", response_model=BaseSingleResponse[VSPInDB], status_code=201)
async def add_vsp(
    body: VSPCreate,
    db: AsyncSession = Depends(get_db),
    current_user: AppUser = Depends(require_admin),
):
    """Добавление строки в справочник INFO."""
    service = VSPService(db)
    result = await service.create(
        body,
        current_user,
        load_org_unit=True,
    )
    return BaseSingleResponse(
        success=True,
        message="Запись INFO создана",
        result=VSPInDB.model_validate(result),
    )


@router.get("/{vsp_id}", response_model=BaseSingleResponse[VSPInDB])
async def get_vsp_by_id(
    vsp_id: int,
    db: AsyncSession = Depends(get_db),
    current_user: AppUser = Depends(require_executor),
):
    """Получение записи справочника INFO по ID."""
    service = VSPService(db)
    result = await service.get(vsp_id, user=current_user, load_org_unit=True)
    if not result:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"ВСП не найден",
        )
    return BaseSingleResponse(
        success=True,
        message="Запись INFO",
        result=VSPInDB.model_validate(result),
    )


@router.put("/{vsp_id}", response_model=BaseSingleResponse[VSPInDB])
async def update_vsp(
    vsp_id: int,
    body: VSPUpdate,
    db: AsyncSession = Depends(get_db),
    current_user: AppUser = Depends(require_executor),
):
    """Редактирование строки справочника INFO."""
    service = VSPService(db)
    result = await service.update(
        vsp_id,
        body,
        current_user,
        load_org_unit=True,
    )
    if not result:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"ВСП не найден",
        )
    return BaseSingleResponse(
        success=True,
        message="Запись INFO обновлена",
        result=VSPInDB.model_validate(result),
    )


@router.delete("/{vsp_id}", response_model=BaseSingleResponse[VSPInDB])
async def delete_vsp(
    vsp_id: int,
    db: AsyncSession = Depends(get_db),
    current_user: AppUser = Depends(require_admin),
):
    """Удаление строки справочника INFO."""
    service = VSPService(db)
    if await service.logical_delete(vsp_id, current_user):
        return BaseSingleResponse(success=True, message="Запись INFO удалена")
    raise HTTPException(
        status_code=status.HTTP_404_NOT_FOUND,
        detail=f"ВСП не найден",
    ) 
