from fastapi import APIRouter, status, HTTPException
from utils.auth_dependency import handles_authentication, user_dependency
from utils.database import db_dependency
from utils.exceptions import AuthenticationError
from schemas.agent import (
    AgentCreate,
    AgentResponse,
    SampleAgentSchema,
    AgentBase,
    AgentCreateSample,
    AgentCreateResponse,
    AgentLiveResponse,
    AgentListResponse,
)
from repositories import agent_repository
import httpx
import os
from retell import Retell
from schemas.phone_number import PhoneNumberCreate, PhoneNumberResponse
from typing import List
from models import SampleAgent, Company, Users
import json
from repositories.user_repository import UserRepository
from utils.constants import BusinessType, RegisterStep
from models import Company, Service, WeeklySchedule, Agent, Booking
import requests
from schemas.agent import BotRequest, BookingRequest


router = APIRouter(prefix="/api/agents", tags=["Agents"])

# RETELL_API_KEY = os.getenv("RETELL_API_KEY")


# @router.post(
#     "/create", status_code=status.HTTP_201_CREATED, response_model=AgentResponse
# )
# @handles_authentication
# async def create_agent(user: user_dependency, request: AgentCreate, db: db_dependency):
#     if user is None:
#         raise AuthenticationError
#     # Save agent in MySQL
#     client = Retell(
#         api_key=RETELL_API_KEY,
#     )
#     llmIDCreated = client.llm.create(
#         model= request.llmCreate["model"],
#         model_temperature= request.llmCreate["model_temperature"],
#         tool_call_strict_mode= request.llmCreate["tool_call_strict_mode"],
#         general_prompt= request.llmCreate["general_prompt"],
#         general_tools= request.llmCreate["general_tools"],
#         states= request.llmCreate["states"],
#         starting_state= request.llmCreate["starting_state"],
#         begin_message= request.llmCreate["begin_message"],
#     )
#     # Send payload to Retell
#     engine_response = client.agent.create(
#         agent_name=request.name,
#         voice_id=request.voice_id,
#         response_engine={
#             "type": request.response_engine["type"],
#             "llm_id": llmIDCreated.llm_id,
#             "version": request.response_engine["version"],
#         },
#     )
#     request.response_engine = engine_response.model_dump()
#     request.llmCreate = llmIDCreated.model_dump()

#     db_agent = agent_repository.create_agent(db, request)

#     return db_agent


# @router.post(
#     "/create", status_code=status.HTTP_201_CREATED, response_model=AgentLiveResponse
# )
# @handles_authentication
# async def create_agent(user: user_dependency, request: AgentCreate, db: db_dependency):
#     if user is None:
#         raise AuthenticationError

#     print("🔑 Logged in user:", user)
#     company = db.query(Company).filter(Company.user_id == user['id']).first()

#     # 1️⃣ Fetch the sample agent
#     sample_agent = (
#         db.query(SampleAgent).filter(SampleAgent.id == request.sample_agent_id).first()
#     )

#     # if not sample_agent:
#     #     raise HTTPException(status_code=404, detail="SampleAgent not found")

#     client = Retell(api_key=RETELL_API_KEY)
#     states = sample_agent.llmCreate["states"]
#     for state in states:
#         state.pop("edges", None)
#         state.pop("tools", None)

#     # 2️⃣ Use llmCreate from sample_agent, not request
#     llmIDCreated = client.llm.create(
#         model=sample_agent.llmCreate["model"],
#         model_temperature=sample_agent.llmCreate["model_temperature"],
#         tool_call_strict_mode=sample_agent.llmCreate["tool_call_strict_mode"],
#         general_prompt=sample_agent.llmCreate["general_prompt"],
#         general_tools=sample_agent.llmCreate["general_tools"],
#         states=states,
#         starting_state=sample_agent.llmCreate["starting_state"],
#         begin_message=sample_agent.llmCreate["begin_message"],
#     )

#     # 3️⃣ Create Agent in Retell
#     engine_response = client.agent.create(
#         agent_name=sample_agent.name,
#         voice_id=sample_agent.voice_id,
#         response_engine={
#             "type": sample_agent.response_engine["response_engine"]["type"],
#             "llm_id": llmIDCreated.llm_id,
#             "version": sample_agent.response_engine["response_engine"]["version"],
#         },
#     )

#     # 4️⃣ Prepare data for DB
#     agent_data = {
#         "name": sample_agent.name,
#         "gender": sample_agent.gender,
#         "about": sample_agent.about,
#         "webhook_url": sample_agent.webhook_url,
#         "voice_id": sample_agent.voice_id,
#         "language": sample_agent.language,
#         "response_engine": engine_response.model_dump(),
#         "voicemail_option": request.voicemail_option or sample_agent.voicemail_option,
#         "llmCreate": llmIDCreated.model_dump(),
#         "company_id": company.id
#     }

#     agent_obj = AgentBase(**agent_data)
#     # 5️⃣ Save to DB
#     db_agent = agent_repository.create_agent(db, agent_obj)

#     new_data = {
#         "message": "Live Agent created in successfully.",
#         "agent": db_agent,  # ✅ will now work with ORM object
#     }
#     return new_data


# @router.post(
#     "/create_sample",
#     status_code=status.HTTP_201_CREATED,
#     response_model=AgentCreateResponse,
# )
# @handles_authentication
# async def create_agent(
#     user: user_dependency, request: AgentCreateSample, db: db_dependency
# ):
#     if user is None:
#         raise AuthenticationError

#     client = Retell(api_key=RETELL_API_KEY)

#     # Create LLM
#     llmIDCreated = client.llm.create(
#         model=request.llmCreate["model"],
#         model_temperature=request.llmCreate["model_temperature"],
#         tool_call_strict_mode=request.llmCreate["tool_call_strict_mode"],
#         general_prompt=request.llmCreate["general_prompt"],
#         general_tools=request.llmCreate["general_tools"],
#         states=request.llmCreate["states"],
#         starting_state=request.llmCreate["starting_state"],
#         begin_message=request.llmCreate["begin_message"],
#     )

#     # Create Agent
#     engine_response = client.agent.create(
#         agent_name=request.name,
#         voice_id=request.voice_id,
#         response_engine={
#             "type": request.response_engine["type"],
#             "llm_id": llmIDCreated.llm_id,
#             "version": request.response_engine["version"],
#         },
#     )

#     # Build a new request object with updated fields
#     updated_request = request.copy(
#         update={
#             "response_engine": engine_response.model_dump(),
#             "llmCreate": llmIDCreated.model_dump(),
#         }
#     )

#     # Save agent in DB
#     db_agent = agent_repository.create_sample_agent(db, updated_request)

#     new_data = {
#         "message": "Sample Agent created in successfully.",
#         "agent": db_agent,  # ✅ will now work with ORM object
#     }
#     return new_data


# @router.get(
#     "/sample_bot_list", status_code=status.HTTP_200_OK, response_model=AgentListResponse
# )
# async def list_agents(user: user_dependency, db: db_dependency):
#     if user is None:
#         raise AuthenticationError

#     agents = agent_repository.get_all_sample_agents(db)
#     return {
#         "message": "Agent List",
#         "agents": agents,  # ✅ FastAPI will serialize with Pydantic
#     }


# @router.post(
#     "/create-phone-number",
#     status_code=status.HTTP_201_CREATED,
#     response_model=PhoneNumberResponse,
# )
# @handles_authentication
# async def create_phone_number(
#     user: user_dependency, request: PhoneNumberCreate, db: db_dependency
# ):
#     user_repo = UserRepository(db)
#     if user is None:
#         raise AuthenticationError
#     await user_repo.update_step(user.get('id'), RegisterStep.SETUP_ASSISTANT)

#     url = "https://api.retellai.com/create-phone-number"
#     headers = {
#         "Authorization": f"Bearer {RETELL_API_KEY}",
#         "Content-Type": "application/json",
#     }

#     async with httpx.AsyncClient() as client:
#         resp = await client.post(url, headers=headers, json=request.dict())

#     # Accept 200 or 201
#     if resp.status_code not in [200, 201]:
#         raise Exception(f"Retell error: {resp.text}")

#     data = resp.json()
#     data["agent_id"] = request.agent_id

#     # Save in DB
#     db_phone = agent_repository.create_phone_number(db, data)

#     return db_phone

VAPI_BASE_URL = "https://api.vapi.ai/"
headers = {"Authorization": "Bearer dd612bd6-92e6-4bb4-a0d1-37152cdb9ea3"}

days = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]


@router.post("/createAgent")
@handles_authentication
async def create_agent(user: user_dependency, req: BotRequest, db: db_dependency):
    if user is None:
        raise AuthenticationError

    # 1. Get company
    company = db.query(Company).filter(Company.id == req.company_id).first()
    if not company:
        raise HTTPException(status_code=404, detail="Company not found")

    # 2. Get services
    services = db.query(Service).filter(Service.company_id == req.company_id).all()
    services_text = (
        "\n".join([f"- {s.name} (${s.price})" for s in services])
        or "No services listed."
    )

    # 3. Get schedule
    schedules = (
        db.query(WeeklySchedule)
        .filter(WeeklySchedule.company_id == req.company_id)
        .all()
    )
    schedule_text = []
    for sch in schedules:
        if sch.is_day_off == 1:
            schedule_text.append(f"{days[sch.day_of_week]}: Closed")
        else:
            schedule_text.append(
                f"{days[sch.day_of_week]}: {sch.start_time.strftime('%H:%M')} - {sch.end_time.strftime('%H:%M')}"
            )
    schedule_str = "\n".join(schedule_text)

    # 4. Enrich system prompt
    enriched_prompt = f"""
# Company Info
You are a virtual assistant for **{company.name}**.

Business type: {company.business_type}  
Address: {company.address1}, {company.address2 or ''}, {company.zip_code}  
Official phone: {company.official_phone}  

# Services
Here are the services offered:  
{services_text}

# Weekly Schedule
The office hours are:  
{schedule_str}

# Assistant Instructions
{req.bot_system_prompt}
"""

    # 5. Prepare payload for VAPI
    payload = {
        "name": req.bot_name,
        "voice": {"voiceId": req.bot_voiceId, "provider": "vapi"},
        "model": {
            "model": req.bot_model,
            "messages": [{"role": "system", "content": enriched_prompt}],
            "provider": "openai",
            "functions": [  # 👈 Vapi expects this
                {
                    "name": "create_booking",
                    "serverUrl": "https://pm.backend.fluten.xyz/api/agents/booking",
                    "description": "Capture booking details",
                    "parameters": {
                        "type": "object",
                        "properties": {
                            "customer_name": {"type": "string"},
                            "phone": {"type": "string"},
                            "appointment_time": {"type": "string"},
                            "service": {"type": "string"},
                        },
                        "required": ["customer_name", "phone", "appointment_time"],
                    },
                }
            ],
        },
        "firstMessage": req.bot_firstMessage,
        "voicemailMessage": req.bot_voicemailMessage,
        "endCallMessage": req.bot_endCallMessage,
        "transcriber": {"model": "nova-2", "language": "en", "provider": "deepgram"},
        "backgroundSound": "office",
        "serverUrl": req.serverUrl,
    }

    # 6. Call Vapi API
    response = requests.post(
        f"{VAPI_BASE_URL}/assistant", json=payload, headers=headers
    )

    if response.status_code != 201:
        raise HTTPException(status_code=response.status_code, detail=response.json())

    resp_data = response.json()
    print("VAPI Response:", resp_data, response.status_code)  # DEBUG

    # Save to DB
    try:
        agent = Agent(
            company_id=req.company_id,
            bot_id=resp_data.get("id"),  # make sure this exists in resp_data
            name=resp_data.get("name", req.bot_name),
            voice_id=req.bot_voiceId,
            model=req.bot_model,
            system_prompt=enriched_prompt,
            first_message=req.bot_firstMessage,
            voicemail_message=req.bot_voicemailMessage,
            end_call_message=req.bot_endCallMessage,
            serverUrl=req.serverUrl,
            raw_response=resp_data,
        )
        db.add(agent)
        db.commit()
        db.refresh(agent)
    except Exception as e:
        db.rollback()
        print("DB Error:", str(e))
        raise HTTPException(status_code=500, detail=f"DB Error: {str(e)}")

    return {"agent": resp_data, "db_record": agent.id}


@router.post("/booking")
async def create_booking(req: dict, db: db_dependency):
    try:
        # Extract arguments from Vapi payload
        args = req.get("arguments", {})
        print("bookings Url")
        print(req, "FullRequest")
        print(args, "args")

        # # Validate with Pydantic
        # booking_data = BookingRequest(**args)

        # # Save into DB
        # booking = Booking(
        #     customer_name=booking_data.customer_name,
        #     phone=booking_data.phone,
        #     appointment_time=booking_data.appointment_time,
        #     service=booking_data.service,
        # )
        # db.add(booking)
        # db.commit()
        # db.refresh(booking)

        return {"success": True, "req": req}

    except Exception as e:
        db.rollback()
        raise HTTPException(status_code=400, detail=f"DB Error: {str(e)}")




@router.post("/vapi-webhook")
async def create_booking(req: dict, db: db_dependency):
    try:
        # Extract arguments from Vapi payload
        print("Vapi-webhook")
        print(req, "FullRequest")


        return {"success": True, "req": req}

    except Exception as e:
        db.rollback()
        raise HTTPException(status_code=400, detail=f"DB Error: {str(e)}")
