from typing import List, Optional, Dict, Any

from fastapi import APIRouter, Depends, Query, HTTPException
from sqlalchemy.orm import Session

from core.database import get_core_db
from core.security import get_current_user, validate_access_to_resource
from .dtos import (
    ManifestCreateDTO,
    ManifestUpdateDTO,
    ManifestResponseDTO,
    ManifestListDTO,
    InvoiceManifestUpdateDTO,
)
from .service import ManifestService

router = APIRouter(prefix="/manifests")


@router.get("/", response_model=ManifestListDTO)
async def list_manifests(
    company_id: int = Query(..., description="Company ID"),
    search: Optional[str] = Query(None, description="Search term"),
    manifest_number: Optional[str] = Query(None, description="Manifest number"),
    start_date: Optional[int] = Query(None, description="Start date (YYYYMMDD)"),
    end_date: Optional[int] = Query(None, description="End date (YYYYMMDD)"),
    skip: int = Query(0, ge=0, description="Skip"),
    limit: int = Query(50, ge=1, le=100, description="Limit"),
    db: Session = Depends(get_core_db),
    current_user: Dict[str, Any] = Depends(get_current_user),
):
    """
    List all manifests for a company with pagination and filters
    """
    tenant_id = validate_access_to_resource(db, company_id, current_user, required_permissions=["export_manifest.view"])
    filters = {
        "search": search,
        "manifest_number": manifest_number,
        "start_date": start_date,
        "end_date": end_date,
    }
    items, total = ManifestService.get_all(
        db, tenant_id, company_id, skip=skip, limit=limit, filters=filters
    )
    return {
        "items": [ManifestResponseDTO.model_validate(item) for item in items],
        "total": total,
        "page": (skip // limit) + 1,
        "page_size": limit,
    }


@router.post("/", response_model=ManifestResponseDTO)
async def create_manifest(
    manifest_data: ManifestCreateDTO,
    company_id: int = Query(..., description="Company ID"),
    db: Session = Depends(get_core_db),
    current_user: dict = Depends(get_current_user),
):
    tenant_id = validate_access_to_resource(db, company_id, current_user, required_permissions=["export_manifest.view"])
    return ManifestService.create(db, manifest_data, tenant_id, company_id)


@router.get("/{manifest_id}", response_model=ManifestResponseDTO)
async def get_manifest(
    manifest_id: int,
    company_id: int = Query(..., description="Company ID"),
    db: Session = Depends(get_core_db),
    current_user: dict = Depends(get_current_user),
):
    tenant_id = validate_access_to_resource(db, company_id, current_user, required_permissions=["export_manifest.view"])
    manifest = ManifestService.get_by_id(db, manifest_id, tenant_id, company_id)
    if not manifest:
        raise HTTPException(status_code=404, detail="Manifest not found")
    return manifest


@router.patch("/{manifest_id}", response_model=ManifestResponseDTO)
async def update_manifest(
    manifest_id: int,
    manifest_data: ManifestUpdateDTO,
    company_id: int = Query(..., description="Company ID"),
    db: Session = Depends(get_core_db),
    current_user: dict = Depends(get_current_user),
):
    tenant_id = validate_access_to_resource(db, company_id, current_user, required_permissions=["export_manifest.view"])
    manifest = ManifestService.update(
        db, manifest_id, tenant_id, company_id, manifest_data
    )
    if not manifest:
        raise HTTPException(status_code=404, detail="Manifest not found")
    return manifest


@router.delete("/{manifest_id}", response_model=bool)
async def delete_manifest(
    manifest_id: int,
    company_id: int = Query(..., description="Company ID"),
    db: Session = Depends(get_core_db),
    current_user: dict = Depends(get_current_user),
):
    tenant_id = validate_access_to_resource(db, company_id, current_user, required_permissions=["export_manifest.view"])
    success = ManifestService.delete(db, manifest_id, tenant_id, company_id)
    if not success:
        raise HTTPException(status_code=404, detail="Manifest not found")
    return success


@router.patch("/invoices/{invoice_id}/compliance", response_model=bool)
async def update_invoice_manifest(
    invoice_id: int,
    data: InvoiceManifestUpdateDTO,
    company_id: int = Query(..., description="Company ID"),
    db: Session = Depends(get_core_db),
    current_user: dict = Depends(get_current_user),
):
    """
    Dedicated endpoint to update manifest_number for an invoice.
    Safely bypasses all core invoice update validations.
    """
    tenant_id = validate_access_to_resource(db, company_id, current_user)
    success = ManifestService.update_invoice_manifest(
        db, invoice_id, tenant_id, company_id, data.manifest_number
    )
    if not success:
        raise HTTPException(status_code=404, detail="Invoice not found")
    return success
