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

from src.api.v1.deps import get_current_active_user_with_set_db
from src.db.models.app_user import AppUser
from src.db.session import get_db
from src.domain.schemas import DirectionSchemaEnum, ExportBulkRequest
from src.services.export_service import ExportService

router = APIRouter(prefix="/export", tags=["export"])
FORM3_ALLOWED_SECTIONS = {"q1", "q2", "q3", "q4", "year"}


def _parse_sections_csv(sections: str | None) -> list[str] | None:
    if sections is None:
        return None
    raw = [section.strip() for section in sections.split(",") if section.strip()]
    normalized: list[str] = []
    seen: set[str] = set()
    quarter_tokens = {"q1", "q2", "q3", "q4", "totals"}
    for section in raw:
        if "." in section:
            base_section, nested_section = section.split(".", 1)
            nested_section = nested_section.strip()
            tokens = [base_section.strip()]
            if nested_section in quarter_tokens:
                tokens.append(nested_section)
            for token in tokens:
                if token and token not in seen:
                    seen.add(token)
                    normalized.append(token)
            continue
        if section not in seen:
            seen.add(section)
            normalized.append(section)
    return normalized or None


def _parse_form3_sections_csv(sections: str | None) -> list[str] | None:
    if not sections:
        return None
    parsed = [section.strip() for section in sections.split(",") if section.strip()]
    invalid = sorted(set(parsed) - FORM3_ALLOWED_SECTIONS)
    if invalid:
        raise ValueError(f"Недопустимые sections для FORM_3: {', '.join(invalid)}")
    return parsed


@router.get("/form/{form_id}")
async def export_form(
    form_id: int,
    direction: DirectionSchemaEnum | None = None,
    sections: str | None = None,
    db: AsyncSession = Depends(get_db),
    current_user: AppUser = Depends(get_current_active_user_with_set_db),
):
    export_service = ExportService(db)
    try:
        stream, filename, media_type = await export_service.export_form_payload(
            form_id=form_id,
            current_user=current_user,
            direction=direction.value if direction else None,
            sections=_parse_sections_csv(sections),
            ignore_non_applicable_query_params=True,
        )
    except ValueError as exc:
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(exc))
    return StreamingResponse(
        stream,
        media_type=media_type,
        headers={"Content-Disposition": export_service.build_content_disposition(filename)},
    )


@router.get("/form/{form_id}/sheet/{sheet}")
async def export_form_sheet(
    form_id: int,
    sheet: str,
    direction: DirectionSchemaEnum | None = None,
    sections: str | None = None,
    db: AsyncSession = Depends(get_db),
    current_user: AppUser = Depends(get_current_active_user_with_set_db),
):
    export_service = ExportService(db)
    try:
        stream, filename, media_type = await export_service.export_form_payload(
            form_id=form_id,
            current_user=current_user,
            sheet=sheet,
            direction=direction.value if direction else None,
            sections=_parse_sections_csv(sections),
        )
    except ValueError as exc:
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(exc))
    return StreamingResponse(
        stream,
        media_type=media_type,
        headers={"Content-Disposition": export_service.build_content_disposition(filename)},
    )


@router.post("/bulk")
async def export_forms_bulk(
    payload: ExportBulkRequest,
    direction: DirectionSchemaEnum | None = None,
    sections: str | None = None,
    db: AsyncSession = Depends(get_db),
    current_user: AppUser = Depends(get_current_active_user_with_set_db),
):
    export_service = ExportService(db)
    try:
        stream, filename, media_type = await export_service.export_bulk_payload(
            form_ids=payload.form_ids,
            current_user=current_user,
            skip_failed=payload.skip_failed,
            direction=direction.value if direction else None,
            sections=_parse_sections_csv(sections),
        )
    except ValueError as exc:
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(exc))
    return StreamingResponse(
        stream,
        media_type=media_type,
        headers={"Content-Disposition": export_service.build_content_disposition(filename)},
    )


@router.get("/project/{project_id}/report/{year}/{report_type}")
async def export_project_report(
    project_id: int,
    year: int,
    report_type: str,
    sections: str | None = None,
    db: AsyncSession = Depends(get_db),
    current_user: AppUser = Depends(get_current_active_user_with_set_db),
):
    export_service = ExportService(db)
    try:
        stream, filename, media_type = await export_service.export_project_report_payload(
            project_id=project_id,
            year=year,
            report_type=report_type,
            current_user=current_user,
            sections=_parse_form3_sections_csv(sections),
        )
    except ValueError as exc:
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(exc))
    return StreamingResponse(
        stream,
        media_type=media_type,
        headers={"Content-Disposition": export_service.build_content_disposition(filename)},
    )


