from __future__ import annotations from datetime import datetime, timedelta from types import SimpleNamespace from fastapi import APIRouter, Depends, Request from fastapi.responses import HTMLResponse from fastapi.templating import Jinja2Templates from dependencies import get_unit_of_work from models import MiningOperationType from services.unit_of_work import UnitOfWork router = APIRouter(tags=["Dashboard"]) templates = Jinja2Templates(directory="templates") def _load_metrics(_: UnitOfWork) -> dict[str, object]: today = datetime.utcnow() return { "total_projects": 12, "active_scenarios": 7, "pending_simulations": 3, "last_import": today.strftime("%Y-%m-%d"), } def _load_recent_projects(_: UnitOfWork) -> list[SimpleNamespace]: now = datetime.utcnow() return [ SimpleNamespace( id=1, name="Copper Ridge Expansion", operation_type=MiningOperationType.OPEN_PIT, updated_at=now - timedelta(days=2), ), SimpleNamespace( id=2, name="Lithium Basin North", operation_type=MiningOperationType.UNDERGROUND, updated_at=now - timedelta(days=5), ), SimpleNamespace( id=3, name="Nickel Underground Phase II", operation_type=MiningOperationType.IN_SITU_LEACH, updated_at=now - timedelta(days=9), ), ] def _load_simulation_updates(_: UnitOfWork) -> list[SimpleNamespace]: now = datetime.utcnow() return [ SimpleNamespace( title="Monte Carlo Batch #21 completed", description="1,000 runs processed for Lithium Basin North.", timestamp=now - timedelta(hours=4), ), SimpleNamespace( title="Scenario validation queued", description="Copper Ridge Expansion pending validation on new cost inputs.", timestamp=now - timedelta(days=1, hours=3), ), ] def _load_scenario_alerts(_: UnitOfWork) -> list[SimpleNamespace]: return [ SimpleNamespace( title="Variance exceeds threshold", message="Nickel Underground Phase II deviates 18% from baseline forecast.", link="/projects/3/view", ), SimpleNamespace( title="Simulation backlog", message="Lithium Basin North has 2 pending simulation batches.", link="/projects/2/view", ), ] @router.get("/", response_class=HTMLResponse, include_in_schema=False, name="dashboard.home") def dashboard_home( request: Request, uow: UnitOfWork = Depends(get_unit_of_work), ) -> HTMLResponse: context = { "request": request, "metrics": _load_metrics(uow), "recent_projects": _load_recent_projects(uow), "simulation_updates": _load_simulation_updates(uow), "scenario_alerts": _load_scenario_alerts(uow), } return templates.TemplateResponse("dashboard.html", context)