"""Mapping routes — AI-powered multi-file column classification.""" from fastapi import APIRouter, HTTPException from app.api.deps import get_mapping_agent, get_session, load_template from app.audit.logger import compute_hash, log_action from app.models.mapping import MappingConfirmation, MappingRequest, MappingResult router = APIRouter(prefix="/mapping", tags=["mapping"]) @router.post("/analyze", response_model=MappingResult) async def analyze_mapping(request: MappingRequest) -> MappingResult: """Send metadata from all files + user request to AI agent. The AI analyzes relationships between files, identifies join keys, and classifies every column. It receives ONLY metadata — never raw data. """ session = get_session(request.session_id) if not session or "all_metadata" not in session: raise HTTPException(status_code=404, detail="Session not found or metadata not extracted") all_metadata = session["all_metadata"] all_sample_values = session.get("all_sample_values", {}) template = load_template(request.template_name) agent = get_mapping_agent() try: result = agent.analyze_mapping( all_metadata=all_metadata, template=template, user_request=request.user_prompt, session_id=request.session_id, all_sample_values=all_sample_values, ) except Exception as e: raise HTTPException(status_code=500, detail=f"AI analysis failed: {e}") session["mapping_result"] = result session["ai_suggestions"] = result.columns session["status"] = "mapping_proposed" log_action( session_id=request.session_id, action="analyze", input_hash=compute_hash(request.user_prompt), output_hash=compute_hash(result.model_dump_json()), details={ "num_files": len(all_metadata), "num_joins": len(result.joins), "num_columns": len(result.columns), }, ) return result @router.post("/confirm") async def confirm_mapping(confirmation: MappingConfirmation) -> dict: """User confirms joins and column classifications.""" session = get_session(confirmation.session_id) if not session: raise HTTPException(status_code=404, detail="Session not found") session["confirmed_joins"] = confirmation.joins session["confirmed_columns"] = confirmation.columns session["confirmed_primary_file"] = confirmation.primary_file session["status"] = "mapping_confirmed" log_action( session_id=confirmation.session_id, action="confirm", input_hash=compute_hash(confirmation.model_dump_json()), details={ "num_joins": len(confirmation.joins), "num_columns": len(confirmation.columns), }, ) return { "session_id": confirmation.session_id, "status": "confirmed", "num_joins": len(confirmation.joins), "num_columns": len(confirmation.columns), }