#spec.py
from pydantic import BaseModel, Field, model_validator
from typing import List, Optional, Literal

class InputOutputConfig(BaseModel):
    has_inputs: bool = Field(default=False, description="Le script prend-il des éléments en entrée ?")
    input_type: Optional[Literal["file", "directory", "api", "database", "none"]] = Field(None, description="Type d'entrée principale")
    input_paths_or_sources: List[str] = Field(default_factory=list, description="Chemins, tables ou endpoints sources")
    
    has_outputs: bool = Field(default=False, description="Le script génère-t-style des éléments en sortie ?")
    output_type: Optional[Literal["file", "directory", "database", "api_response", "log_only"]] = Field(None, description="Type de sortie principale")
    output_formats: List[str] = Field(default_factory=list, description="Formats attendus (ex: CSV, JSON, XLSX)")

class AuthenticationConfig(BaseModel):
    requires_auth: bool = Field(default=False, description="Le script nécessite-t-il des accès sécurisés ?")
    auth_method: Optional[Literal["env_variables", "service_account_json", "oauth2", "api_key", "none"]] = Field(None, description="Méthode d'authentification")
    target_tools_and_apis: List[str] = Field(default_factory=list, description="Logiciels ou API avec lesquels interagir (ex: Sharepoint, JIRA)")

class EnvironmentConfig(BaseModel):
    target_os: Literal["linux", "windows", "macos", "cross_platform"] = Field(default="cross_platform", description="Système d'exploitation cible")
    language_version: str = Field(default="^3.11", description="Contrainte de version du langage")
    critical_dependencies: List[str] = Field(default_factory=list, description="Librairies tierces indispensables")

class ProjectSpec(BaseModel):
    title: Optional[str] = Field(None, description="Nom clair et concis du script")
    description: Optional[str] = Field(None, description="Description macro de l'objectif du script")
    requirements: List[str] = Field(default_factory=list, description="Liste des fonctionnalités pas-à-pas attendues")
    constraints: List[str] = Field(default_factory=list, description="Normes, formats de code et conventions de nommage imposés")
    language: str = Field(default="Python", description="Langage de programmation principal")
    target_stack: str = Field(None, description="Stack technique ou framework attendu (ex: Pandas, FastAPI, Flask, Django, etc.)")
    
    # Sous-configurations détaillées (permettent la détection des champs manquants)
    io_config: InputOutputConfig = Field(default_factory=InputOutputConfig)
    auth_config: AuthenticationConfig = Field(default_factory=AuthenticationConfig)
    env_config: EnvironmentConfig = Field(default_factory=EnvironmentConfig)
    
    error_handling_strategy: Literal["abort_on_error", "log_and_continue", "retry_policy"] = Field(
        default="log_and_continue", 
        description="Comportement du script face à une anomalie"
    )
    is_complete: bool = Field(default=False, description="Passez à True UNIQUEMENT si vous avez TOUTES les infos pour coder (titre, desc, reqs, io_config, auth_config si besoin).")
    clarifying_question: Optional[str] = Field(None, description="Si is_complete est False, écrivez ici une question claire et polie pour Chainlit pour demander les détails manquants.")

    @model_validator(mode="after")
    def validate_conditional_fields(self) -> 'ProjectSpec':
        """Validation des dépendances logiques pour marquer le cahier des charges comme valide."""
        # Si les champs majeurs sont remplis, on valide la cohérence interne
        if self.title and self.description and len(self.requirements) > 0:
            if self.io_config.has_inputs and not self.io_config.input_type:
                raise ValueError("input_type manquant alors que has_inputs est True")
            if self.io_config.has_outputs and not self.io_config.output_type:
                raise ValueError("output_type manquant alors que has_outputs est True")
            if self.auth_config.requires_auth and (not self.auth_config.auth_method or self.auth_config.auth_method == "none"):
                raise ValueError("auth_method manquante alors que requires_auth est True")
        return self