"""Export Intel Cockpit page + API proxy.""" from __future__ import annotations import os from typing import Any, Optional import httpx from fastapi import APIRouter, Query, Request from fastapi.responses import RedirectResponse, StreamingResponse from fastapi.templating import Jinja2Templates from pathlib import Path router = APIRouter() BASE = Path(__file__).resolve().parent.parent.parent templates = Jinja2Templates(directory=str(BASE / "templates")) TOOLS = os.getenv("TOOLS_API_URL", "http://tools-api:8700").rstrip("/") async def _proxy(method: str, path: str, **kwargs) -> Any: url = f"{TOOLS}/export-intel{path}" async with httpx.AsyncClient(timeout=60.0) as client: r = await client.request(method, url, **kwargs) if r.status_code >= 400: return {"error": r.text, "status": r.status_code} if "text/csv" in r.headers.get("content-type", ""): return r return r.json() @router.get("/foodlinkk") def foodlinkk_home(): return RedirectResponse(url="/export-intel", status_code=302) @router.get("/export-intel") def export_intel_page(request: Request): return templates.TemplateResponse( "export_intel.html", {"request": request, "page_title": "Wereldexport"}, ) @router.get("/api/export-intel/stats") async def api_stats(country: Optional[str] = None, region: Optional[str] = None): params = {k: v for k, v in {"country": country, "region": region}.items() if v} return await _proxy("GET", "/stats", params=params) @router.get("/api/export-intel/regions") async def api_regions(): return await _proxy("GET", "/regions") @router.get("/api/export-intel/territories") async def api_territories(region: Optional[str] = None): params = {"region": region} if region else {} return await _proxy("GET", "/territories", params=params) @router.get("/api/export-intel/entities") async def api_entities( country: Optional[str] = None, region: Optional[str] = None, entity_type: Optional[str] = None, entity_types: Optional[str] = None, q: Optional[str] = None, favorite_only: bool = False, crm_linked: Optional[bool] = None, limit: int = 200, offset: int = 0, ): params = {k: v for k, v in { "country": country, "region": region, "entity_type": entity_type, "entity_types": entity_types, "q": q, "limit": limit, "offset": offset, "favorite_only": favorite_only, "crm_linked": crm_linked, }.items() if v is not None and v is not False} return await _proxy("GET", "/entities", params=params) @router.get("/api/export-intel/entities/{entity_id}") async def api_entity(entity_id: int): return await _proxy("GET", f"/entities/{entity_id}") @router.get("/api/export-intel/contacts") async def api_contacts( country: Optional[str] = None, entity_type: Optional[str] = None, has_email: Optional[bool] = None, q: Optional[str] = None, limit: int = 200, offset: int = 0, ): params: dict[str, Any] = {"limit": limit, "offset": offset} if country: params["country"] = country if entity_type: params["entity_type"] = entity_type if has_email is not None: params["has_email"] = has_email if q: params["q"] = q return await _proxy("GET", "/contacts", params=params) @router.get("/api/export-intel/contacts/export.csv") async def api_contacts_export(country: Optional[str] = None, entity_type: Optional[str] = None): params = {k: v for k, v in {"country": country, "entity_type": entity_type}.items() if v} url = f"{TOOLS}/export-intel/contacts/export.csv" async with httpx.AsyncClient(timeout=60.0) as client: r = await client.get(url, params=params) return StreamingResponse( iter([r.content]), media_type="text/csv", headers={"Content-Disposition": "attachment; filename=export-intel-contacts.csv"}, ) @router.get("/api/export-intel/caterers/brands") async def api_caterer_brands(): return await _proxy("GET", "/caterers/brands") @router.get("/api/export-intel/caterers/presence") async def api_caterer_presence(country: Optional[str] = None): params = {"country": country} if country else {} return await _proxy("GET", "/caterers/presence", params=params) @router.get("/api/export-intel/gov-sources") async def api_gov_sources(country: Optional[str] = None): params = {"country": country} if country else {} return await _proxy("GET", "/gov-sources", params=params) @router.get("/api/export-intel/map/bundle") async def api_map_bundle( country: Optional[str] = None, region: Optional[str] = None, entity_type: Optional[str] = None, entity_types: Optional[str] = None, q: Optional[str] = None, halal_min: Optional[float] = None, favorite_only: bool = False, crm_linked: Optional[bool] = None, ): params = {k: v for k, v in { "country": country, "region": region, "entity_type": entity_type, "entity_types": entity_types, "q": q, "halal_min": halal_min, "favorite_only": favorite_only, "crm_linked": crm_linked, }.items() if v is not None and v is not False} return await _proxy("GET", "/map/bundle", params=params) @router.post("/api/export-intel/entities/favorites") async def api_set_favorites(request: Request): body = await request.json() return await _proxy("POST", "/entities/favorites", json=body) @router.get("/api/export-intel/entities/favorites") async def api_list_favorites(country: Optional[str] = None, region: Optional[str] = None, limit: int = 200): params = {k: v for k, v in {"country": country, "region": region, "limit": limit}.items() if v is not None} return await _proxy("GET", "/entities/favorites", params=params) @router.post("/api/export-intel/crm/push") async def api_crm_push(request: Request): body = await request.json() return await _proxy("POST", "/crm/push", json=body) @router.get("/api/export-intel/crm/pipeline") async def api_crm_pipeline(country: Optional[str] = None, region: Optional[str] = None, limit: int = 100): params = {k: v for k, v in {"country": country, "region": region, "limit": limit}.items() if v is not None} return await _proxy("GET", "/crm/pipeline", params=params) @router.get("/api/export-intel/halal/markets") async def api_halal_markets( region: Optional[str] = None, country: Optional[str] = None, limit: int = 30, ): params = {k: v for k, v in {"region": region, "country": country, "limit": limit}.items() if v is not None} return await _proxy("GET", "/halal/markets", params=params) @router.get("/api/export-intel/tenders") async def api_tenders(country: Optional[str] = None, status: Optional[str] = "open", limit: int = 100): params = {k: v for k, v in {"country": country, "status": status, "limit": limit}.items() if v is not None} return await _proxy("GET", "/tenders", params=params) @router.post("/api/export-intel/sync/{kind}") async def api_sync(kind: str, request: Request): body = {} if request.headers.get("content-type", "").startswith("application/json"): try: body = await request.json() except Exception: body = {} if kind not in ("contacts", "caterers", "distributors", "customers", "tenders", "all", "world", "region"): return {"error": "unknown sync kind"} timeout = 7200.0 if kind in ("world", "region", "all") else 600.0 async with httpx.AsyncClient(timeout=timeout) as client: url = f"{TOOLS}/export-intel/sync/{kind}" r = await client.post(url, json=body) return r.json()