from django.shortcuts import render
from django.contrib.admin.views.decorators import staff_member_required
from django.db.models import Sum, Count, Avg, F, DecimalField
from django.db.models.functions import Coalesce
from django.utils.decorators import method_decorator
from django.views.generic import TemplateView
from decimal import Decimal

from .models import ShareType, ShareSubscription, SharePayment
from apps.members.models import Member


@method_decorator(staff_member_required, name="dispatch")
class SharesDashboardView(TemplateView):
    """Vue tableau de bord pour les statistiques des parts sociales"""

    template_name = "admin/shares/dashboard.html"

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)

        # Statistiques générales
        total_members = Member.objects.count()
        members_with_shares = (
            Member.objects.filter(subscriptions__isnull=False).distinct().count()
        )

        # Statistiques des souscriptions
        subscriptions_stats = ShareSubscription.objects.aggregate(
            total_subscriptions=Count("id"),
            total_subscribed_shares=Coalesce(Sum("subscribed_quantity"), 0),
            total_subscription_value=Coalesce(
                Sum(F("subscribed_quantity") * F("share_type__nominal_value")),
                Decimal("0"),
                output_field=DecimalField(),
            ),
        )

        # Statistiques des paiements
        payment_stats = SharePayment.objects.aggregate(
            total_payments=Count("id"),
            total_paid_shares=Coalesce(Sum("paid_quantity"), 0),
            total_paid_amount=Coalesce(
                Sum("financial_transaction__amount"), Decimal("0")
            ),
        )

        # Taux de participation
        participation_rate = 0
        if total_members > 0:
            participation_rate = (members_with_shares / total_members) * 100

        # Taux de libération (paiement)
        liberation_rate = 0
        if subscriptions_stats["total_subscribed_shares"] > 0:
            liberation_rate = (
                payment_stats["total_paid_shares"]
                / subscriptions_stats["total_subscribed_shares"]
            ) * 100

        # Top 5 des membres par parts payées
        top_shareholders = []
        for subscription in (
            ShareSubscription.objects.select_related("member__user", "share_type")
            .annotate(
                total_paid=Coalesce(Sum("payments__paid_quantity"), 0),
                total_value=Coalesce(
                    Sum("payments__paid_quantity") * F("share_type__nominal_value"),
                    Decimal("0"),
                ),
            )
            .filter(total_paid__gt=0)
            .order_by("-total_paid")[:5]
        ):
            user = subscription.member.user
            top_shareholders.append(
                {
                    "name": f"{user.first_name} {user.last_name}".strip() or user.email,
                    "membership_number": subscription.member.membership_number,
                    "paid_shares": subscription.total_paid,
                    "value": subscription.total_value,
                }
            )

        # Statistiques par type de part
        share_types_stats = []
        for share_type in ShareType.objects.annotate(
            subscriptions_count=Count("sharesubscription"),
            total_subscribed=Coalesce(Sum("sharesubscription__subscribed_quantity"), 0),
            total_paid=Coalesce(Sum("sharesubscription__payments__paid_quantity"), 0),
            total_value=Coalesce(
                Sum("sharesubscription__payments__paid_quantity") * F("nominal_value"),
                Decimal("0"),
            ),
        ):
            liberation_rate_type = 0
            if share_type.total_subscribed > 0:
                liberation_rate_type = (
                    share_type.total_paid / share_type.total_subscribed
                ) * 100

            share_types_stats.append(
                {
                    "name": share_type.name,
                    "nominal_value": share_type.nominal_value,
                    "subscriptions_count": share_type.subscriptions_count,
                    "total_subscribed": share_type.total_subscribed,
                    "total_paid": share_type.total_paid,
                    "total_value": share_type.total_value,
                    "liberation_rate": liberation_rate_type,
                }
            )

        # Souscriptions récentes (derniers 30 jours)
        from django.utils import timezone
        from datetime import timedelta

        recent_date = timezone.now().date() - timedelta(days=30)
        recent_subscriptions = (
            ShareSubscription.objects.filter(subscription_date__gte=recent_date)
            .select_related("member__user", "share_type")
            .order_by("-subscription_date")[:10]
        )

        context.update(
            {
                "total_members": total_members,
                "members_with_shares": members_with_shares,
                "participation_rate": participation_rate,
                "liberation_rate": liberation_rate,
                "subscriptions_stats": subscriptions_stats,
                "payment_stats": payment_stats,
                "top_shareholders": top_shareholders,
                "share_types_stats": share_types_stats,
                "recent_subscriptions": recent_subscriptions,
            }
        )

        return context


@staff_member_required
def shares_summary_report(request):
    """Rapport de synthèse des parts sociales"""

    # Données pour le rapport
    share_types = ShareType.objects.annotate(
        subscriptions_count=Count("sharesubscription"),
        members_count=Count("sharesubscription__member", distinct=True),
        total_subscribed=Coalesce(Sum("sharesubscription__subscribed_quantity"), 0),
        total_paid=Coalesce(Sum("sharesubscription__payments__paid_quantity"), 0),
    )

    # Souscriptions non payées
    unpaid_subscriptions = ShareSubscription.objects.filter(
        id__in=[
            sub.id for sub in ShareSubscription.objects.all() if not sub.is_fully_paid
        ]
    ).select_related("member__user", "share_type")

    # Souscriptions partiellement payées
    partially_paid = [
        sub
        for sub in ShareSubscription.objects.all()
        if sub.paid_quantity > 0 and not sub.is_fully_paid
    ]

    context = {
        "share_types": share_types,
        "unpaid_subscriptions": unpaid_subscriptions,
        "partially_paid_count": len(partially_paid),
        "title": "Rapport de synthèse des parts sociales",
    }

    return render(request, "admin/shares/summary_report.html", context)
