from fastapi import APIRouter, HTTPException from pydantic import BaseModel from typing import Optional, List, Dict, Any from services.database import ( save_custom_pattern, get_custom_patterns, delete_custom_pattern, toggle_pattern_active ) router = APIRouter(prefix="/api/patterns", tags=["patterns"]) class PatternRequest(BaseModel): id: Optional[str] = None name: str description: str triggers: List[str] keywords: List[str] historical_instances: Optional[List[Dict[str, Any]]] = [] suggested_trades: Optional[List[Dict[str, Any]]] = [] asset_class: str expected_move_pct: float probability: float horizon_days: int ai_quality_score: Optional[int] = None ai_evaluation: Optional[Dict[str, Any]] = None source: Optional[str] = "custom" counter_thesis: Optional[str] = None invalidation_trigger: Optional[str] = None invalidation_probability: Optional[float] = None @router.get("/all") def list_all(): """Return all active patterns from DB (builtin + custom).""" return get_custom_patterns() @router.get("/builtin") def list_builtin(): return [p for p in get_custom_patterns() if p.get("source") == "builtin"] @router.get("/custom") def list_custom(): return [p for p in get_custom_patterns() if p.get("source") != "builtin"] @router.post("/custom") def create_pattern(req: PatternRequest): data = req.model_dump() data["source"] = "custom" pat_id = save_custom_pattern(data) return {"id": pat_id, "status": "saved"} @router.put("/custom/{pat_id}") def update_pattern(pat_id: str, req: PatternRequest): data = req.model_dump() data["id"] = pat_id save_custom_pattern(data) return {"id": pat_id, "status": "updated"} @router.delete("/custom/{pat_id}") def delete_pattern(pat_id: str): delete_custom_pattern(pat_id) return {"status": "deleted"} @router.put("/toggle/{pat_id}") def toggle_pattern(pat_id: str): """Enable or disable a pattern (works for builtin and custom).""" new_state = toggle_pattern_active(pat_id) return {"id": pat_id, "is_active": new_state}