from django.contrib import admin, messages
from django.utils.translation import ngettext, gettext_lazy as _
from django.utils.html import format_html
from django.db.models import Sum, Count, F, Case, When, IntegerField
from django.urls import path, reverse
from django.shortcuts import get_object_or_404, redirect, render
from django.http import HttpResponse, JsonResponse
from django.template.response import TemplateResponse
from django.contrib.admin.utils import unquote
from django.core.exceptions import ValidationError
from decimal import Decimal
import csv

from .models import ShareType, ShareSubscription, SharePayment
from apps.banking.models import Account


class PaymentInline(admin.TabularInline):
    """Inline pour afficher les paiements d'une souscription"""

    model = SharePayment
    extra = 0
    readonly_fields = (
        "financial_transaction",
        "amount_paid",
        "created_at",
        "created_by",
    )
    fields = (
        "paid_quantity",
        "amount_paid",
        "financial_transaction",
        "created_at",
        "created_by",
    )

    def has_add_permission(self, request, obj=None):
        return False

    def has_delete_permission(self, request, obj=None):
        return False


@admin.register(ShareType)
class ShareTypeAdmin(admin.ModelAdmin):
    list_display = (
        "name",
        "nominal_value",
        "total_subscriptions",
        "total_subscribed_shares",
        "total_paid_shares",
        "total_value",
    )
    search_fields = ("name",)
    readonly_fields = ("created_at", "updated_at", "created_by", "updated_by")

    fieldsets = (
        (_("Informations principales"), {"fields": ("name", "nominal_value")}),
        (
            _("Audit"),
            {
                "fields": ("created_at", "updated_at", "created_by", "updated_by"),
                "classes": ("collapse",),
            },
        ),
    )

    def get_queryset(self, request):
        """Optimise les requêtes avec les annotations nécessaires"""
        return (
            super()
            .get_queryset(request)
            .annotate(
                _total_subscriptions=Count("sharesubscription"),
                _total_subscribed=Sum("sharesubscription__subscribed_quantity"),
            )
        )

    def total_subscriptions(self, obj):
        """Nombre total de souscriptions pour ce type de part"""
        return getattr(obj, "_total_subscriptions", 0)

    total_subscriptions.short_description = _("Total souscriptions")
    total_subscriptions.admin_order_field = "_total_subscriptions"

    def total_subscribed_shares(self, obj):
        """Nombre total de parts souscrites"""
        total = getattr(obj, "_total_subscribed", 0)
        return format_html("<strong>{}</strong>", total or 0)

    total_subscribed_shares.short_description = _("Parts souscrites")
    total_subscribed_shares.admin_order_field = "_total_subscribed"

    def total_paid_shares(self, obj):
        """Nombre total de parts payées"""
        total_paid = (
            SharePayment.objects.filter(subscription__share_type=obj).aggregate(
                Sum("paid_quantity")
            )["paid_quantity__sum"]
            or 0
        )
        return format_html('<strong style="color: green;">{}</strong>', total_paid)

    total_paid_shares.short_description = _("Parts payées")

    def total_value(self, obj):
        """Valeur totale des parts payées"""
        total_paid = (
            SharePayment.objects.filter(subscription__share_type=obj).aggregate(
                Sum("paid_quantity")
            )["paid_quantity__sum"]
            or 0
        )
        value = total_paid * obj.nominal_value
        formatted_value = f"{value:,.0f} FCFA"
        return format_html("<strong>{}</strong>", formatted_value)

    total_value.short_description = _("Valeur totale payée")


class PaymentStatusFilter(admin.SimpleListFilter):
    """Filtre pour le statut de paiement des souscriptions"""

    title = _("Statut de paiement")
    parameter_name = "payment_status"

    def lookups(self, request, model_admin):
        return (
            ("fully_paid", _("Entièrement payé")),
            ("partially_paid", _("Partiellement payé")),
            ("not_paid", _("Non payé")),
        )

    def queryset(self, request, queryset):
        if self.value() == "fully_paid":
            return queryset.filter(
                id__in=[sub.id for sub in queryset if sub.is_fully_paid]
            )
        elif self.value() == "partially_paid":
            return queryset.filter(
                id__in=[
                    sub.id
                    for sub in queryset
                    if sub.paid_quantity > 0 and not sub.is_fully_paid
                ]
            )
        elif self.value() == "not_paid":
            return queryset.filter(
                id__in=[sub.id for sub in queryset if sub.paid_quantity == 0]
            )
        return queryset


@admin.register(ShareSubscription)
class ShareSubscriptionAdmin(admin.ModelAdmin):
    list_display = (
        "id",
        "member_info",
        "share_type",
        "subscribed_quantity",
        "paid_quantity_display",
        "payment_progress",
        "remaining_amount",
        "subscription_date",
        "payment_status",
        "payment_actions",
    )
    list_filter = ("share_type", PaymentStatusFilter, "subscription_date")
    search_fields = (
        "member__user__email",
        "member__user__first_name",
        "member__user__last_name",
        "member__membership_number",
    )
    readonly_fields = (
        "subscription_date",
        "paid_quantity",
        "is_fully_paid",
        "created_at",
        "updated_at",
        "created_by",
        "updated_by",
    )
    actions = ["mark_as_fully_paid", "make_partial_payment", "export_subscriptions_csv"]
    inlines = [PaymentInline]

    fieldsets = (
        (
            _("Informations de souscription"),
            {
                "fields": (
                    "member",
                    "share_type",
                    "subscribed_quantity",
                    "subscription_date",
                )
            },
        ),
        (
            _("Statut de paiement"),
            {"fields": ("paid_quantity", "is_fully_paid"), "classes": ("collapse",)},
        ),
        (
            _("Audit"),
            {
                "fields": ("created_at", "updated_at", "created_by", "updated_by"),
                "classes": ("collapse",),
            },
        ),
    )

    def get_urls(self):
        """Ajoute des URLs personnalisées pour les paiements"""
        urls = super().get_urls()
        custom_urls = [
            path(
                "<uuid:subscription_id>/make_payment/",
                self.admin_site.admin_view(self.make_payment_view),
                name="shares_sharesubscription_make_payment",
            ),
            path(
                "<uuid:subscription_id>/payment_history/",
                self.admin_site.admin_view(self.payment_history_view),
                name="shares_sharesubscription_payment_history",
            ),
        ]
        return custom_urls + urls

    def make_payment_view(self, request, subscription_id):
        """Vue pour effectuer un paiement sur une souscription"""
        subscription = get_object_or_404(ShareSubscription, id=subscription_id)

        if request.method == "POST":
            try:
                quantity = int(request.POST.get("quantity", 0))
                account_id = request.POST.get("from_account")

                if quantity <= 0:
                    raise ValidationError("La quantité doit être supérieure à 0")

                from_account = get_object_or_404(Account, id=account_id)

                # Effectuer le paiement
                subscription.make_payment(
                    quantity=quantity, by_user=request.user, from_account=from_account
                )

                messages.success(
                    request,
                    f"Paiement de {quantity} part(s) effectué avec succès pour {subscription.member.user.email}",
                )

                # Rediriger vers la liste des souscriptions
                return redirect("admin:shares_sharesubscription_changelist")

            except (ValueError, ValidationError) as e:
                messages.error(request, f"Erreur lors du paiement: {e}")
            except Exception as e:
                messages.error(request, f"Erreur inattendue: {e}")

        # Récupérer les comptes disponibles
        available_accounts = Account.objects.filter(
            owner=subscription.member.user, is_active=True
        ).exclude(type=Account.AccountType.SHARE_CAPITAL)

        # Si aucun compte personnel, récupérer la caisse
        if not available_accounts.exists():
            available_accounts = Account.objects.filter(
                type=Account.AccountType.CASH_DESK, is_active=True
            )

        context = {
            "subscription": subscription,
            "available_accounts": available_accounts,
            "unpaid_quantity": subscription.subscribed_quantity
            - subscription.paid_quantity,
            "unpaid_amount": (
                subscription.subscribed_quantity - subscription.paid_quantity
            )
            * subscription.share_type.nominal_value,
            "title": f"Effectuer un paiement - Souscription #{subscription.id}",
            "opts": self.model._meta,
        }

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

    def payment_history_view(self, request, subscription_id):
        """Vue pour voir l'historique des paiements"""
        subscription = get_object_or_404(ShareSubscription, id=subscription_id)
        payments = subscription.payments.all().order_by("-created_at")

        context = {
            "subscription": subscription,
            "payments": payments,
            "title": f"Historique des paiements - Souscription #{subscription.id}",
            "opts": self.model._meta,
        }

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

    def payment_actions(self, obj):
        """Boutons d'action pour les paiements"""
        if obj.is_fully_paid:
            return format_html(
                '<span style="color: green;">✅ Payé intégralement</span><br/>'
                '<a href="{}" class="button" style="margin-top: 5px;">📊 Historique</a>',
                reverse(
                    "admin:shares_sharesubscription_payment_history", args=[obj.id]
                ),
            )
        else:
            return format_html(
                '<a href="{}" class="button" style="background: #28a745; color: white; margin-right: 5px;">💳 Payer</a>'
                '<a href="{}" class="button">📊 Historique</a>',
                reverse("admin:shares_sharesubscription_make_payment", args=[obj.id]),
                reverse(
                    "admin:shares_sharesubscription_payment_history", args=[obj.id]
                ),
            )

    payment_actions.short_description = _("Actions")
    payment_actions.allow_tags = True

    def member_info(self, obj):
        """Affiche les informations complètes du membre"""
        user = obj.member.user
        return format_html(
            "<strong>{} {}</strong><br/><small>{}</small><br/><small>N° {}</small>",
            user.first_name or "",
            user.last_name or "",
            user.email,
            obj.member.membership_number or "N/A",
        )

    member_info.short_description = _("Membre")
    member_info.admin_order_field = "member__user__last_name"

    def paid_quantity_display(self, obj):
        """Affiche la quantité payée avec style"""
        paid = obj.paid_quantity
        total = obj.subscribed_quantity
        if paid == total:
            color = "green"
        elif paid > 0:
            color = "orange"
        else:
            color = "red"
        return format_html(
            '<strong style="color: {};">{}/{}</strong>', color, paid, total
        )

    paid_quantity_display.short_description = _("Parts payées/souscrites")

    def payment_progress(self, obj):
        """Barre de progression du paiement"""
        if obj.subscribed_quantity == 0:
            percentage = 0
        else:
            percentage = (obj.paid_quantity / obj.subscribed_quantity) * 100

        if percentage == 100:
            color = "#28a745"  # Vert
        elif percentage > 0:
            color = "#ffc107"  # Orange
        else:
            color = "#dc3545"  # Rouge

        percentage_text = f"{percentage:.0f}%"
        return format_html(
            '<div style="width: 100px; background-color: #e9ecef; border-radius: 3px;">'
            '<div style="width: {}%; height: 20px; background-color: {}; border-radius: 3px; '
            'display: flex; align-items: center; justify-content: center; color: white; font-size: 11px;">'
            "{}</div></div>",
            percentage,
            color,
            percentage_text,
        )

    payment_progress.short_description = _("Progression")

    def remaining_amount(self, obj):
        """Montant restant à payer"""
        remaining_shares = obj.subscribed_quantity - obj.paid_quantity
        amount = remaining_shares * obj.share_type.nominal_value
        if amount > 0:
            formatted_amount = f"{amount:,.0f} FCFA"
            return format_html(
                '<strong style="color: red;">{}</strong>', formatted_amount
            )
        return format_html('<strong style="color: green;">Soldé</strong>')

    remaining_amount.short_description = _("Montant restant")

    def payment_status(self, obj):
        """Badge de statut de paiement"""
        if obj.is_fully_paid:
            return format_html(
                '<span style="background: #28a745; color: white; padding: 2px 8px; border-radius: 3px; font-size: 11px;">PAYÉ</span>'
            )
        elif obj.paid_quantity > 0:
            return format_html(
                '<span style="background: #ffc107; color: black; padding: 2px 8px; border-radius: 3px; font-size: 11px;">PARTIEL</span>'
            )
        else:
            return format_html(
                '<span style="background: #dc3545; color: white; padding: 2px 8px; border-radius: 3px; font-size: 11px;">NON PAYÉ</span>'
            )

    payment_status.short_description = _("Statut")

    def mark_as_fully_paid(self, request, queryset):
        """Action pour marquer les souscriptions sélectionnées comme entièrement payées"""
        updated_count = 0
        error_subscriptions = []

        for subscription in queryset.filter(
            id__in=[sub.id for sub in queryset if not sub.is_fully_paid]
        ):
            try:
                # Trouver le compte courant du membre pour le paiement
                from_account = Account.objects.get(
                    owner=subscription.member.user, type=Account.AccountType.CURRENT
                )

                unpaid_quantity = (
                    subscription.subscribed_quantity - subscription.paid_quantity
                )
                if unpaid_quantity > 0:
                    subscription.make_payment(
                        quantity=unpaid_quantity,
                        by_user=request.user,
                        from_account=from_account,
                    )
                    updated_count += 1

            except Account.DoesNotExist:
                error_subscriptions.append(
                    f"#{subscription.id}: Compte courant introuvable"
                )
            except ValueError as e:
                error_subscriptions.append(f"#{subscription.id}: {e}")

        if updated_count > 0:
            self.message_user(
                request,
                ngettext(
                    "%d souscription a été marquée comme payée.",
                    "%d souscriptions ont été marquées comme payées.",
                    updated_count,
                )
                % updated_count,
                messages.SUCCESS,
            )

        if error_subscriptions:
            self.message_user(
                request, f"Erreurs: {'; '.join(error_subscriptions)}", messages.ERROR
            )

    mark_as_fully_paid.short_description = _("Marquer comme entièrement payées")

    def make_partial_payment(self, request, queryset):
        """Action pour effectuer un paiement partiel sur les souscriptions sélectionnées"""
        # Filtrer seulement les souscriptions non entièrement payées
        unpaid_subscriptions = [sub for sub in queryset if not sub.is_fully_paid]

        if not unpaid_subscriptions:
            self.message_user(
                request,
                "Toutes les souscriptions sélectionnées sont déjà entièrement payées.",
                messages.WARNING,
            )
            return

        if len(unpaid_subscriptions) > 1:
            self.message_user(
                request,
                "Veuillez sélectionner une seule souscription pour effectuer un paiement partiel.",
                messages.ERROR,
            )
            return

        # Rediriger vers le formulaire de paiement de la souscription unique
        subscription = unpaid_subscriptions[0]
        return redirect("admin:shares_sharesubscription_make_payment", subscription.id)

    make_partial_payment.short_description = _("Effectuer un paiement partiel")

    def export_subscriptions_csv(self, request, queryset):
        """Exporte les souscriptions sélectionnées en CSV"""
        response = HttpResponse(content_type="text/csv")
        response["Content-Disposition"] = (
            'attachment; filename="souscriptions_parts.csv"'
        )
        response.write("\ufeff")  # BOM pour Excel

        writer = csv.writer(response)
        writer.writerow(
            [
                "ID",
                "Membre",
                "Email",
                "Numéro membre",
                "Type de part",
                "Quantité souscrite",
                "Quantité payée",
                "Montant payé",
                "Montant restant",
                "Statut",
                "Date souscription",
            ]
        )

        for subscription in queryset:
            user = subscription.member.user
            paid_amount = (
                subscription.paid_quantity * subscription.share_type.nominal_value
            )
            remaining_amount = (
                subscription.subscribed_quantity - subscription.paid_quantity
            ) * subscription.share_type.nominal_value
            if subscription.is_fully_paid:
                status = "Payé"
            elif subscription.paid_quantity > 0:
                status = "Partiel"
            else:
                status = "Non payé"

            writer.writerow(
                [
                    subscription.id,
                    f"{user.first_name} {user.last_name}".strip(),
                    user.email,
                    subscription.member.membership_number or "",
                    subscription.share_type.name,
                    subscription.subscribed_quantity,
                    subscription.paid_quantity,
                    f"{paid_amount:.0f}",
                    f"{remaining_amount:.0f}",
                    status,
                    subscription.subscription_date.strftime("%d/%m/%Y"),
                ]
            )

        return response

    export_subscriptions_csv.short_description = _("Exporter en CSV")


@admin.register(SharePayment)
class SharePaymentAdmin(admin.ModelAdmin):
    list_display = (
        "id",
        "subscription_info",
        "paid_quantity",
        "amount_paid_display",
        "payment_date",
        "transaction_reference",
        "created_by",
    )
    list_filter = ("created_at", "subscription__share_type")
    search_fields = (
        "subscription__member__user__email",
        "subscription__member__user__first_name",
        "subscription__member__user__last_name",
    )
    readonly_fields = (
        "subscription",
        "paid_quantity",
        "financial_transaction",
        "amount_paid",
        "created_at",
        "updated_at",
        "created_by",
        "updated_by",
    )

    fieldsets = (
        (
            _("Informations de paiement"),
            {
                "fields": (
                    "subscription",
                    "paid_quantity",
                    "amount_paid",
                    "financial_transaction",
                )
            },
        ),
        (
            _("Audit"),
            {
                "fields": ("created_at", "updated_at", "created_by", "updated_by"),
                "classes": ("collapse",),
            },
        ),
    )

    def has_add_permission(self, request):
        return False

    def has_delete_permission(self, request, obj=None):
        return False

    def subscription_info(self, obj):
        """Informations de la souscription"""
        user = obj.subscription.member.user
        return format_html(
            "<strong>{} {}</strong><br/><small>{}</small><br/><small>Souscription #{}</small>",
            user.first_name or "",
            user.last_name or "",
            obj.subscription.share_type.name,
            obj.subscription.id,
        )

    subscription_info.short_description = _("Souscription")
    subscription_info.admin_order_field = "subscription__member__user__last_name"

    def amount_paid_display(self, obj):
        """Affiche le montant payé avec formatage"""
        formatted_amount = f"{obj.amount_paid:,.0f} FCFA"
        return format_html("<strong>{}</strong>", formatted_amount)

    amount_paid_display.short_description = _("Montant payé")
    amount_paid_display.admin_order_field = "financial_transaction__amount"

    def payment_date(self, obj):
        """Date de paiement"""
        return obj.created_at.strftime("%d/%m/%Y à %H:%M")

    payment_date.short_description = _("Date de paiement")
    payment_date.admin_order_field = "created_at"

    def transaction_reference(self, obj):
        """Référence de la transaction"""
        if obj.financial_transaction:
            # Use transaction ID since 'reference' field doesn't exist
            return f"TXN-{obj.financial_transaction.id}"
        return "N/A"

    transaction_reference.short_description = _("Référence transaction")
    transaction_reference.admin_order_field = "financial_transaction__id"
            return f"TXN-{obj.financial_transaction.id}"
        return "N/A"

    transaction_reference.short_description = _("Référence transaction")
    transaction_reference.admin_order_field = "financial_transaction__id"
