from fastapi import APIRouter, Depends, HTTPException, BackgroundTasks, Response, status
from typing import List
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

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: str = None, sync: bool = False, skip_coworker: bool = False, 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")

        # Verify webhook secret...
        # (Lines 179-188 omitted for brevity in instruction, but kept in code)
        webhook_triggers = db.query(AgentTrigger).filter(
            AgentTrigger.instance_id == id,
            AgentTrigger.trigger_type == "webhook"
        ).all()
        
        if webhook_triggers:
            secrets = [t.webhook_secret for t in webhook_triggers if t.webhook_secret]
            if secrets and token not in secrets:
                raise HTTPException(status_code=403, detail="Invalid webhook 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)}"
        
        # Determine skip_coworker from payload override OR query param
        should_skip = skip_coworker or payload.get("skip_coworker") or False
            
        if sync:
            # Synchronous blocking mode
            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:
            # Asynchronous background mode (Default)
            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)
    def manual_trigger(id: str, payload: dict, background_tasks: BackgroundTasks, current_user: models.User = Depends(get_current_user), db: Session = Depends(get_db)):
        instance = db.query(AgentInstance).filter(
            AgentInstance.id == id,
            AgentInstance.user_id == current_user.id
        ).first()
        if not instance:
            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)
        background_tasks.add_task(AgentExecutor.run, instance.id, prompt, services, services.user_service, should_skip)
        return {"message": "Accepted"}

    @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)):
        instance = db.query(AgentInstance).filter(
            AgentInstance.id == id,
            AgentInstance.user_id == current_user.id
        ).first()
        if not instance:
            raise HTTPException(status_code=404, detail="Instance not found")
        return db.query(AgentTrigger).filter(AgentTrigger.instance_id == id).all()

    @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)):
        instance = db.query(AgentInstance).filter(
            AgentInstance.id == id,
            AgentInstance.user_id == current_user.id
        ).first()
        if not instance:
            raise HTTPException(status_code=404, detail="Instance not found")
            
        trigger = AgentTrigger(**request.model_dump())
        trigger.instance_id = id # Ensure it maps safely
        
        if trigger.trigger_type == "webhook" and not trigger.webhook_secret:
            import secrets
            trigger.webhook_secret = secrets.token_hex(16)
            
        db.add(trigger)
        db.commit()
        db.refresh(trigger)
        return trigger

    @router.delete("/triggers/{trigger_id}")
    def delete_agent_trigger(trigger_id: str, db: Session = Depends(get_db)):
        trigger = db.query(AgentTrigger).filter(AgentTrigger.id == trigger_id).first()
        if not trigger:
            raise HTTPException(status_code=404, detail="Trigger not found")
        db.delete(trigger)
        db.commit()
        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)):
        instance = db.query(AgentInstance).filter(
            AgentInstance.id == id,
            AgentInstance.user_id == current_user.id
        ).first()
        if not instance:
            raise HTTPException(status_code=404, detail="Instance not found")
        
        instance.total_runs = 0
        instance.successful_runs = 0
        instance.total_input_tokens = 0
        instance.total_output_tokens = 0
        instance.total_tokens_accumulated = 0
        instance.total_running_time_seconds = 0
        instance.tool_call_counts = {}
        
        db.commit()
        db.refresh(instance)
        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
