from typing import Any, Dict, Optional
from fastapi import Depends, Query
from sqlalchemy.orm import Session
from api.v1.common.tenant_crud_routes import (
    TenantCRUDRoutes,
    validate_access_to_resource,
    get_core_db,
    get_current_user,
)

from .dto import ExchangeRateCreateDTO, ExchangeRateResponseDTO, ExchangeRateUpdateDTO
from .services import ExchangeRateService

# Create router using TenantCRUDRoutes factory
route_handler = TenantCRUDRoutes(
    service=ExchangeRateService,
    create_schema=ExchangeRateCreateDTO,
    update_schema=ExchangeRateUpdateDTO,
    response_schema=ExchangeRateResponseDTO,
    prefix="/exchange-rate",
    tags=[],
    resource_name="Exchange Rate",
    id_name="id",  # Using numeric ID
    enable_list=False,  # Disable default list to provide custom one with filters
    enable_filters=False,
    default_page_size=50,
    max_page_size=100,
    # Permisos
    list_permissions=["cat_exchange_rates.view"],
    get_permissions=["cat_exchange_rates.view"],
    create_permissions=["cat_exchange_rates.create"],
    update_permissions=["cat_exchange_rates.edit"],
    delete_permissions=["cat_exchange_rates.delete"],
)

crud_router = route_handler.router

# Create a custom router for specific endpoints that must be matched BEFORE generic CRUD routes
# We use the same prefix so they are grouped together
from fastapi import APIRouter
custom_router = APIRouter(prefix="/exchange-rate", tags=[])

# CSV import: add to custom_router BEFORE including it in master, so /exchange-rate/imports/* is registered
from api.v1.modules.a76.layouts_csv.exchange_rate.routes import router as imports_router
custom_router.include_router(imports_router, prefix="/imports", tags=["exchange_rate / csv_import"])

@custom_router.get("/test-ping")
async def test_ping():
    return {"message": "pong"}

# Master router to export
router = APIRouter()
# Include custom routes FIRST to avoid shadowing by /{id}
router.include_router(custom_router)
# router.include_router(crud_router)


@custom_router.get(
    "/",
    response_model=Dict[str, Any],
    summary="List Exchange Rates",
    description="Get paginated list of exchange rates with optional date filter",
)
async def list_exchange_rates(
    company_id: int = Query(..., description="Company ID"),
    date: Optional[str] = Query(None, description="Filter by date (YYYY-MM-DD)"),
    page: int = Query(1, ge=1, description="Page number"),
    page_size: int = Query(
        50,
        ge=1,
        le=100,
        description="Page size",
    ),
    db: Session = Depends(get_core_db),
    current_user: Dict[str, Any] = Depends(get_current_user),
):
    tenant_id = validate_access_to_resource(db, company_id, current_user, ["cat_exchange_rates.view"])

    skip = (page - 1) * page_size
    filters = {}
    if date:
        filters["date"] = date

    items, total = ExchangeRateService.get_all(
        db, tenant_id, company_id, skip, page_size, filters
    )

    return {
        "items": [ExchangeRateResponseDTO.model_validate(item) for item in items],
        "total": total,
        "page": page,
        "page_size": page_size,
    }

@custom_router.get(
    "/dof-search",
    response_model=Dict[str, Any],
    summary="Fetch Exchange Rate from DOF",
    description="Fetches the exchange rate from the Official Journal of the Federation (DOF) for a specific date.",
)
async def fetch_exchange_rate_dof(
    date: str = Query(..., description="Date in YYYY-MM-DD format"),
    db: Session = Depends(get_core_db),
    current_user: Dict[str, Any] = Depends(get_current_user),
):
    # This endpoint can be public or protected. Assuming protected for now.
    # No specific tenant validation needed since it's an external query, 
    # but good to ensure user is authenticated.
    
    try:
        print(f"DEBUG: Route called with date={date}")
        rate = ExchangeRateService.fetch_from_dof(date)
        
        if rate is None:
            return {"success": False, "message": "No se encontró el tipo de cambio en el DOF para la fecha especificada o el servicio no está disponible.", "value": None}
            
        return {"success": True, "value": rate}
    except Exception as e:
        print(f"DEBUG: Error in route: {e}")
        import traceback
        traceback.print_exc()
        return {"success": False, "message": f"Error interno: {str(e)}", "value": None}

# Include routers at the end to ensure all routes are registered
# Include custom routes FIRST to avoid shadowing by /{id} of crud_router
router.include_router(custom_router)
router.include_router(crud_router)
