from datetime import date, timedelta, datetime, timezone
from typing import Dict, Any, List, Optional
from fastapi import APIRouter, Body, HTTPException, Query, Depends, Request
from pydantic import BaseModel
from sqlalchemy.orm import Session
import math
import requests
import os
from requests.auth import HTTPBasicAuth
from app.common.constants import BookingIntent, CallSource, TwilioTerminationReason
from app.common.database import get_db
from app.common.twillio_helper import get_twillio_client
from app.common.utils import convert_to_utc
from app.retell_service.routers.retell import get_current_time_in_timezone, get_directory, is_off_hours
from app.retell_service.services.caller_info_service import get_caller_name_by_phone_number
from ..services.auth_utils import validate_token
from app.common.models import Settings, Advisor, CallsLog, TransferResult
import httpx
from twilio.twiml.voice_response import VoiceResponse
from fastapi import APIRouter, Depends, HTTPException, status, Body
from fastapi.responses import Response
from twilio.twiml.voice_response import VoiceResponse, Connect, Start, Stream, Dial, Conference

router = APIRouter()

@router.post("/bdc/dashboard")
async def bdc_dashboard(
    request: Dict[str, Any] = Body(...),
    db: Session = Depends(get_db),
    current_user: Dict = Depends(validate_token)
):
    """
    Get bdc calls for a given date range.
    Returns calls along with total count.
    """
    start_date = request.get('start_date')
    end_date = request.get('end_date')
    timezone = request.get('timezone', 'America/Los_Angeles')

    page = request.get('page', 1)
    page_size = request.get('page_size', 10)
    offset = (page - 1) * page_size

    if isinstance(start_date, str):
        try:
            start_date = datetime.fromisoformat(start_date)
        except ValueError:
            start_date = datetime.strptime(start_date, "%Y-%m-%d")

    if isinstance(end_date, str):
        try:
            end_date = datetime.fromisoformat(end_date)
        except ValueError:
            end_date = datetime.strptime(end_date, "%Y-%m-%d")
            end_date = end_date.replace(hour=23, minute=59, second=59)

    today = datetime.now()
    if not start_date:
        start_date = today - timedelta(days=30)

    if not end_date:
        end_date = today

    if start_date:
        start_date = convert_to_utc(start_date)

    if end_date:
        end_date = convert_to_utc(end_date)
    
    start_datetime = datetime.combine(start_date, datetime.min.time())
    end_datetime = datetime.combine(end_date, datetime.max.time())
    
    today = date.today()
    if not start_date:
        start_date = today - timedelta(days=30)

    if not end_date:
        end_date = today

    bdc_settings = db.query(Settings).filter(
        Settings.name == 'BDC_NUMBER'
    ).first()
    
    if not bdc_settings:
        raise HTTPException(status_code=404, detail="BDC number not found in settings")
        
    bdc_number = bdc_settings.value.replace('"', '')
    
    advisor = db.query(Advisor).filter(
        Advisor.phone_number == bdc_number
    ).first()
    
    if not advisor:
        raise HTTPException(status_code=404, detail=f"No record found with BDC number: {bdc_number}")
        
    advisor_id = advisor.id
    
    query = db.query(CallsLog).filter(
        CallsLog.transferred_to == bdc_number,
        CallsLog.call_date_time >= start_datetime,
        CallsLog.call_date_time <= end_datetime,
        # CallsLog.company_id == current_user.get('default_company')
    )
    total_calls = query.count()
    calls = query.order_by(CallsLog.call_date_time.desc()).offset(offset).limit(page_size).all()

    calls_missed = (
        db.query(CallsLog)
        .join(TransferResult, CallsLog.twilio_call_id == TransferResult.twilio_call_id)
        .filter(
            CallsLog.transferred_to == bdc_number,
            CallsLog.call_date_time >= start_datetime,
            CallsLog.call_date_time <= end_datetime,
            TransferResult.status == False,
            # CallsLog.company_id == current_user.get('default_company')
        )
        .count()
    )

    scheduled = query.filter(CallsLog.booking_intent == BookingIntent.YES).count()
    not_scheduled = query.filter(CallsLog.booking_intent == BookingIntent.NO).count()

    call_data = []
    for call in calls:
        call_data.append({
            "call_datetime": call.call_date_time,
            "customer_name": call.caller_name,
            "customer_number": call.caller_number,
            "sentiment": call.sentiment_score,
            "twilio_call_id": call.twilio_call_id,
            "schedule_intention": "Positive" if call.booking_intent == 1 else "Negative",
            "schedule_datetime": call.schedule_datetime,
            "call_summary": call.twilio_recording_text or "",
            "call_id": call.call_id,
            "transcript": call.transcript,
        })

    total_pages = math.ceil(total_calls / page_size)
    calls_missed_percentage = 0;
    scheduled_percentage = 0;
    not_scheduled_percentage = 0;

    if total_calls > 0:
        calls_missed_percentage = (calls_missed / total_calls) * 100
        scheduled_percentage = (scheduled / total_calls) * 100
        not_scheduled_percentage = (not_scheduled / total_calls) * 100

    return {
        "summary": {
            "total_calls": total_calls,
            "calls_missed": calls_missed,
            "scheduled": scheduled,
            "not_scheduled": not_scheduled
        },
        "percentage": {
            "calls_missed": calls_missed_percentage,
            "scheduled": scheduled_percentage,
            "not_scheduled": not_scheduled_percentage
        },
        "calls": call_data,
        "page": page,
        "page_size": page_size,
        "total_pages": total_pages
    }