from fastapi import APIRouter, Depends, HTTPException, BackgroundTasks, Response, status, Query
from typing import List, Optional, Annotated
from sqlalchemy.orm import Session
from app.api.dependencies import ServiceContainer, get_db, get_current_user
from app.api import schemas
from app.db import models
from app.db.models.agent import AgentTemplate, AgentInstance, AgentTrigger
from app.db.models import Message
from app.api.schemas import (
    AgentTemplateCreate, AgentTemplateResponse,
    AgentInstanceCreate, AgentInstanceResponse, AgentInstanceStatusUpdate
)
import uuid
import json
import os
import logging
from app.core.orchestration.agent_loop import AgentExecutor

from sqlalchemy.orm import joinedload

logger = logging.getLogger(__name__)

def create_agents_router(services: ServiceContainer) -> APIRouter:
    router = APIRouter()

    @router.get("", response_model=List[AgentInstanceResponse])
    def get_agents(current_user: models.User = Depends(get_current_user), db: Session = Depends(get_db)):
        return services.agent_service.list_user_agents(db, current_user.id)

    @router.get("/{id}", response_model=AgentInstanceResponse)
    def get_agent(id: str, current_user: models.User = Depends(get_current_user), db: Session = Depends(get_db)):
        return services.agent_service.get_agent_instance(db, id, current_user.id)
        
    @router.post("/templates", response_model=AgentTemplateResponse)
    def create_template(request: AgentTemplateCreate, current_user: models.User = Depends(get_current_user), db: Session = Depends(get_db)):
        return services.agent_service.create_template(db, current_user.id, request)

    @router.post("/instances", response_model=AgentInstanceResponse)
    def create_instance(request: AgentInstanceCreate, current_user: models.User = Depends(get_current_user), db: Session = Depends(get_db)):
        return services.agent_service.create_instance(db, current_user.id, request)

    @router.patch("/{id}/status", response_model=AgentInstanceResponse)
    def update_status(id: str, request: AgentInstanceStatusUpdate, current_user: models.User = Depends(get_current_user), db: Session = Depends(get_db)):
        return services.agent_service.update_status(db, id, current_user.id, request.status)

    @router.patch("/{id}/config", response_model=AgentInstanceResponse)
    def update_config(id: str, request: schemas.AgentConfigUpdate, current_user: models.User = Depends(get_current_user), db: Session = Depends(get_db)):
        return services.agent_service.update_config(db, id, current_user.id, request)

    @router.post("/{id}/webhook")
    async def webhook_receiver(
        id: str, 
        payload: dict, 
        background_tasks: BackgroundTasks, 
        response: Response, 
        token: Annotated[Optional[str], Query()] = None, 
        sync: bool = False, 
        skip_coworker: bool = False, 
        db: Session = Depends(get_db)
    ):
        logger.info(f"[Webhook] Trigger received for agent {id} (token provided: {bool(token)})")
        instance = services.agent_service.validate_webhook_trigger(db, id, token)

        # Extract prompt from payload (supports 'prompt' or legacy 'override_prompt')
        prompt = payload.get("prompt") or payload.get("override_prompt") or f"Webhook Event: {json.dumps(payload)}"
        should_skip = skip_coworker or payload.get("skip_coworker") or False
            
        if sync:
            try:
                result = await AgentExecutor.run(instance.id, prompt, services, services.user_service, skip_coworker=should_skip)
                return {"status": "success", **result}
            except Exception as e:
                raise HTTPException(status_code=500, detail=f"Agent execution failed: {str(e)}")
        else:
            background_tasks.add_task(AgentExecutor.run, instance.id, prompt, services, services.user_service, should_skip)
            response.status_code = status.HTTP_202_ACCEPTED
            return {"status": "accepted", "message": "Background task initiated"}

    @router.post("/{id}/run", status_code=202)
    async def manual_trigger(id: str, payload: dict, background_tasks: BackgroundTasks, current_user: models.User = Depends(get_current_user), db: Session = Depends(get_db)):
        try:
            logger.info(f"[ManualTrigger] Agent {id} manual run initiated by user {current_user.id}")
            logger.debug(f"[ManualTrigger] Payload: {json.dumps(payload)}")
            
            instance = db.query(AgentInstance).filter(
                AgentInstance.id == id,
                AgentInstance.user_id == current_user.id
            ).first()
            
            if not instance:
                logger.warning(f"[ManualTrigger] Instance {id} not found for user {current_user.id}")
                raise HTTPException(status_code=404, detail="Instance not found")
                
            prompt = payload.get("prompt") or f"Manual triggered execution for agent {id}."
            should_skip = payload.get("skip_coworker", False)
            
            logger.info(f"[ManualTrigger] Scheduling AgentExecutor for {id}")
            background_tasks.add_task(AgentExecutor.run, instance.id, prompt, services, services.user_service, should_skip)
            return {"message": "Accepted"}
        except HTTPException:
            raise
        except Exception as e:
            logger.error(f"[ManualTrigger] Internal error: {e}")
            raise HTTPException(status_code=500, detail=f"Failed to initiate trigger: {str(e)}")

    @router.get("/{id}/triggers", response_model=List[schemas.AgentTriggerResponse])
    def get_agent_triggers(id: str, current_user: models.User = Depends(get_current_user), db: Session = Depends(get_db)):
        return services.agent_service.list_agent_triggers(db, id, current_user.id)

    @router.post("/{id}/triggers", response_model=schemas.AgentTriggerResponse)
    def create_agent_trigger(id: str, request: schemas.AgentTriggerCreate, current_user: models.User = Depends(get_current_user), db: Session = Depends(get_db)):
        return services.agent_service.create_agent_trigger(db, id, current_user.id, request)

    @router.delete("/triggers/{trigger_id}")
    def delete_agent_trigger(trigger_id: str, db: Session = Depends(get_db)):
        services.agent_service.delete_agent_trigger(db, trigger_id)
        return {"message": "Trigger deleted successfully"}

    @router.post("/{id}/metrics/reset")
    def reset_agent_metrics(id: str, current_user: models.User = Depends(get_current_user), db: Session = Depends(get_db)):
        services.agent_service.reset_agent_metrics(db, id, current_user.id)
        return {"message": "Metrics reset successfully"}

    @router.get("/{id}/telemetry")
    def get_telemetry(id: str, db: Session = Depends(get_db)):
        instance = db.query(AgentInstance).filter(AgentInstance.id == id).first()
        if not instance:
            raise HTTPException(status_code=404, detail="Instance not found")
        # For MVP/Area 3, return mock telemetry data (e.g. baseline or from cgroup)
        # Real cgroup-based metrics will come in Phase 2
        return {
            "cpu_usage": 2.5,
            "memory_usage": 512,
            "network_tx": 120,
            "network_rx": 450
        }

    @router.get("/{id}/dependencies")
    def get_dependencies(id: str, db: Session = Depends(get_db)):
        instance = db.query(AgentInstance).filter(AgentInstance.id == id).first()
        if not instance:
            raise HTTPException(status_code=404, detail="Instance not found")
        return {
            "dependencies": [],
            "edges": []
        }

    @router.post("/deploy")
    def deploy_agent(request: schemas.DeployAgentRequest, background_tasks: BackgroundTasks, current_user: models.User = Depends(get_current_user), db: Session = Depends(get_db)):
        result = services.agent_service.deploy_agent(db, current_user.id, request)
        if request.initial_prompt:
             background_tasks.add_task(AgentExecutor.run, result["instance_id"], request.initial_prompt, services, services.user_service)
        return result

    @router.delete("/{id}")
    def delete_agent(id: str, current_user: models.User = Depends(get_current_user), db: Session = Depends(get_db)):
        services.agent_service.delete_agent(db, id, current_user.id)
        return {"message": "Agent deleted successfully"}

    return router
