import os
import json
import time
from pathlib import Path
from app.agents.pm_agent import run_pm_agent
from app.agents.dev_agent import run_dev_agent
from app.agents.qa_agent import run_qa_agent
from app.services.retrieval_service import find_existing_project
from app.graph.state import WorkflowState
from langchain_core.runnables import RunnableConfig

async def pm_node(state: WorkflowState):    
    history = state.get("chat_history", []) or []
    
    if state.get("status") in ["spec_incomplete", "human_refused"] and state.get("user_feedback"):
        current_input = state["user_feedback"]
        full_user_input = f"{state['user_input']}\n{current_input}"
    else:
        current_input = state["user_input"]
        full_user_input = current_input
    
    spec = await run_pm_agent(user_input=current_input, history=history)
    
    updated_history = list(history)
    updated_history.append({"role": "user", "content": current_input})
    
    if not spec.is_complete and spec.clarifying_question:
        updated_history.append({"role": "assistant", "content": spec.clarifying_question})

    return {
        "spec": spec.model_dump(),
        "status": "spec_ready" if spec.is_complete else "spec_incomplete", 
        "chat_history": updated_history,
        "user_input": full_user_input, 
        "user_feedback": None,
        "loop_count": 0,
    }

async def retrieval_node(state: WorkflowState, config: RunnableConfig):
    qdrant_repo = config.get("configurable", {}).get("qdrant_repo")
    if not qdrant_repo:
        raise ValueError("❌ Erreur : Le repository Qdrant n'a pas été transmis au graphe.")
    
    existing_project = await find_existing_project(qdrant_repo, state["user_input"])

    return {
        "existing_project": existing_project,
        "status": "existing_found" if existing_project else "no_existing_project",
    }

async def dev_node(state: WorkflowState):
    qa_logs = []
    qa_result = state.get("qa_result")
    
    if qa_result:
        global_summary = qa_result.get("global_summary")
        technical_feedback = qa_result.get("technical_feedback", [])
        
        if global_summary:
            qa_logs.append(f"Résumé Global : {global_summary}")
        
        if isinstance(technical_feedback, list):
            qa_logs.extend(technical_feedback)
        elif technical_feedback:
            qa_logs.append(technical_feedback)

    generated_code_state = state.get("generated_code") or {}
    existing_repo_url = generated_code_state.get("repo_url")
    existing_files = generated_code_state.get("files")
    
    generated_code = await run_dev_agent(
        spec=state["spec"], 
        qa_feedback=qa_logs if qa_logs else None,
        repo_url=existing_repo_url,
        files=existing_files
    )
    
    return {
        "generated_code": generated_code,
        "status": "code_generated",
    }

async def qa_node(state: WorkflowState):
    dev_data = state.get("generated_code", {})
    project_title = dev_data.get("spec_title", "default_project")
    current_loops = state.get("loop_count", 0)

    qa_eval = await run_qa_agent(
        project_title=project_title,
        dev_output=dev_data
    )
    
    if hasattr(qa_eval, "model_dump"):
        clean_qa_result = qa_eval.model_dump()
    elif isinstance(qa_eval, dict):
        clean_qa_result = qa_eval
    else:
        clean_qa_result = {
            "is_complete_and_safe": getattr(qa_eval, "is_complete_and_safe", False),
            "global_summary": getattr(qa_eval, "global_summary", "Erreur d'analyse"),
            "technical_feedback": getattr(qa_eval, "technical_feedback", [])
        }

    is_success = clean_qa_result.get("is_complete_and_safe", False)

    return {
        "qa_result": clean_qa_result,
        "loop_count": current_loops if is_success else current_loops + 1,
        "status": "qa_done",
    }

async def human_review_node(state: WorkflowState):
    """
    Nœud pivot. Si le statut vient du QA, il bascule en attente de validation humaine.
    Si Chainlit a déjà collecté la décision, il laisse passer le flux vers le routage.
    """
    current_status = state.get("status")
    
    if current_status in ["qa_done", "existing_found"]:
        return {
            "status": "wait_human_review"
        }
        
    return {"status": current_status}

async def delivery_node(state: WorkflowState, config: RunnableConfig):
    """
    Nœud final de livraison : Archivage ZIP en mémoire et réindexation Qdrant.
    """
    dev_data = state.get("generated_code", {})
    project_title = dev_data.get("spec_title", f"project_{int(time.time())}")
    
    raw_files = dev_data.get("files", {})
    files = {}
    if isinstance(raw_files, list):
        for f in raw_files:
            if isinstance(f, dict):
                path = f.get("path") or f.get("filename") or f.get("name")
                content = f.get("content") or f.get("code") or ""
                if path:
                    files[path] = content
    elif isinstance(raw_files, dict):
        files = raw_files

    # 3. Réindexation dans Qdrant (en utilisant le payload mémoire)
    # qdrant_repo = config.get("configurable", {}).get("qdrant_repo")
    # if qdrant_repo:
    #     payload_text = f"Title: {project_title}\nDescription: {state.get('spec', {}).get('description')}"
        
    #     # /!\ À remplacer par ton vrai modèle d'embedding (ex: await qdrant_repo.embed(payload_text))
    #     dummy_vector = [0.1] * 1536 
        
    #     qdrant_repo.client.upsert(
    #         collection_name="arc_projects",
    #         points=[
    #             PointStruct(
    #                 id=str(Path(project_title).name), 
    #                 vector=dummy_vector,
    #                 payload=metadata
    #             )
    #         ]
    #     )

    return {
        "is_completed": True,
        "status": "delivered",
        "user_input": f"{state.get('user_input')}\n\n[System] Projet {project_title} validé et package ZIP disponible."
    }