from django.db.models import Count, Q
from apps.calls.constants import TRANSFER_STATUS
from apps.core.models import User
from apps.calls.models import Call
from apps.userprofile.services import ProfileServices

USER_PERFORMANCE_COLOR_THRESHOLDS = [
    (50, "#e76f51"),
    (25, "#f4a261"),
    (0, "#76c487"),
]

def percent(value: float) -> str:
    return f"{value:.2f}%"

def format_user_performance(stats, users, show_all=False):
    """
    Output format for:
    - user-performance (dashboard cards)
    """

    results = []

    for row in stats:
        user = users.get(row["transfer_user"])
        if not user:
            continue

        total = row["total_calls"]
        missed = row["calls_missed"]
        attended = row["calls_attended"]

        missed_percentage = round((missed / total) * 100, 1) if total else 0

        background_color = USER_PERFORMANCE_COLOR_THRESHOLDS[-1][1]
        for threshold, color in USER_PERFORMANCE_COLOR_THRESHOLDS:
            if missed_percentage >= threshold:
                background_color = color
                break

        full_name = ProfileServices.resolve_display_name(user=user)

        entry = {
            "user_id": user.id,
            "username": full_name,
            "total_calls": total,
            "successful_calls": attended,
            "missed_calls": missed,
            "missed_percentage": missed_percentage,
            "background_color": background_color,
        }

        if show_all:
            results.append(entry)
        else:
            if total > 0:
                results.append(entry)

    return sorted(results, key=user_performance_sort_key)

def user_performance_sort_key(row):
    return (
        -row["missed_percentage"],
        -row["total_calls"],
    )

def format_best_worst(stats, users, *, order_by, show_all=False):
    """
    Output format for:
    - best-performing-users
    - worst-performing-users
    """

    results = []

    for row in stats:
        user = users.get(row["transfer_user"])
        if not user:
            continue

        total = row["total_calls"]
        attended = row["calls_attended"]
        missed = row["calls_missed"]

        avg_attended = round((attended / total) * 100, 1) if total else 0
        avg_missed = round((missed / total) * 100, 1) if total else 0

        full_name = ProfileServices.resolve_display_name(user=user)

        entry = {
            "username": full_name,
            "calls_missed": missed,
            "calls_attended": attended,

            "avg_attended_value": avg_attended,
            "avg_missed_value": avg_missed,

            "average_missed": percent(avg_missed),
            "avg_attended": percent(avg_attended),
            "total_calls": total,
        }

        if show_all:
            results.append(entry)
        else:
            if total > 0:
                results.append(entry)

    return sorted(
        results,
        key=lambda x: (
            -x[order_by],
            -x["total_calls"],
        )
    )

def get_company_users(user, superuser_limit=5):
    """
    Returns queryset of active users for the current company or superuser.
    """
    users = User.objects.filter(
        is_superuser=False,
        is_active=True,
        profile__isnull=False,
        profile__phone_number__isnull=False
    ).exclude(profile__phone_number="").select_related('profile')

    if not user.is_superuser and getattr(user, "active_company", None):
        users = users.filter(companies=user.active_company)
    elif user.is_superuser:
        users = users[:superuser_limit]
    else:
        return None

    return users

def aggregate_user_calls(*, calls_qs, company_users):
    call_ids = (
        calls_qs
        .values_list("id", flat=True)
        .distinct()
    )

    raw_stats = (
        Call.objects
        .filter(id__in=call_ids, transfer_user__in=company_users)
        .values("transfer_user")
        .annotate(
            total_calls=Count("id"),
            calls_attended=Count(
                "id",
                filter=Q(transfer_status=TRANSFER_STATUS.SUCCESSFUL.value)
            ),
            calls_missed=Count(
                "id",
                filter=Q(transfer_status=TRANSFER_STATUS.FAILED.value)
            ),
        )
    )

    stats_map = {
        row["transfer_user"]: row
        for row in raw_stats
    }

    final_stats = []
    for user in company_users.select_related("profile"):
        row = stats_map.get(
            user.id,
            {
                "transfer_user": user.id,
                "total_calls": 0,
                "calls_attended": 0,
                "calls_missed": 0,
            }
        )
        final_stats.append(row)

    users = {u.id: u for u in company_users}

    return final_stats, users
