# apps/shares/api/views.py
from rest_framework import viewsets, status
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated
from django.db.models import Sum, Count, Q
from django.utils import timezone
from datetime import timedelta

from ..models import ShareType, ShareSubscription, SharePayment
from .serializers import (
    ShareTypeSerializer,
    ShareSubscriptionSerializer,
    SharePaymentSerializer,
)
from apps.members.models import Member


class ShareTypeViewSet(viewsets.ModelViewSet):
    queryset = ShareType.objects.all()
    serializer_class = ShareTypeSerializer


class ShareSubscriptionViewSet(viewsets.ModelViewSet):
    queryset = ShareSubscription.objects.all()
    serializer_class = ShareSubscriptionSerializer


class SharePaymentViewSet(viewsets.ModelViewSet):
    queryset = SharePayment.objects.all()
    serializer_class = SharePaymentSerializer


class PaymentTrackingViewSet(viewsets.ReadOnlyModelViewSet):
    """API pour le suivi des paiements de parts sociales"""

    permission_classes = [IsAuthenticated]

    @action(detail=False, methods=["get"])
    def member_payment_history(self, request):
        """Historique des paiements d'un membre"""
        member_id = request.query_params.get("member_id")

        if not member_id:
            return Response(
                {"error": "member_id parameter is required"},
                status=status.HTTP_400_BAD_REQUEST,
            )

        try:
            member = Member.objects.get(id=member_id)
        except Member.DoesNotExist:
            return Response(
                {"error": "Member not found"}, status=status.HTTP_404_NOT_FOUND
            )

        # Récupérer toutes les souscriptions du membre
        subscriptions = ShareSubscription.objects.filter(member=member)

        # Récupérer tous les paiements du membre
        payments = SharePayment.objects.filter(subscription__member=member).order_by(
            "-created_at"
        )

        # Calculs des totaux
        total_subscribed_amount = sum(
            sub.subscribed_quantity * sub.share_type.nominal_value
            for sub in subscriptions
        )
        total_paid_amount = sum(
            sub.paid_quantity * sub.share_type.nominal_value for sub in subscriptions
        )

        data = {
            "member": {
                "id": member.id,
                "name": f"{member.user.first_name} {member.user.last_name}",
                "email": member.user.email,
                "membership_number": member.membership_number,
            },
            "financial_summary": {
                "total_subscribed_amount": total_subscribed_amount,
                "total_paid_amount": total_paid_amount,
                "remaining_amount": total_subscribed_amount - total_paid_amount,
                "payment_completion_rate": (
                    (total_paid_amount / total_subscribed_amount * 100)
                    if total_subscribed_amount > 0
                    else 0
                ),
            },
            "subscriptions": [
                {
                    "id": sub.id,
                    "share_type": sub.share_type.name,
                    "subscribed_quantity": sub.subscribed_quantity,
                    "paid_quantity": sub.paid_quantity,
                    "subscription_date": sub.subscription_date,
                    "is_fully_paid": sub.is_fully_paid,
                    "subscribed_amount": sub.subscribed_quantity
                    * sub.share_type.nominal_value,
                    "paid_amount": sub.paid_quantity * sub.share_type.nominal_value,
                    "remaining_amount": (sub.subscribed_quantity - sub.paid_quantity)
                    * sub.share_type.nominal_value,
                }
                for sub in subscriptions
            ],
            "payment_history": [
                {
                    "id": payment.id,
                    "subscription_id": payment.subscription.id,
                    "share_type": payment.subscription.share_type.name,
                    "paid_quantity": payment.paid_quantity,
                    "amount_paid": payment.amount_paid,
                    "payment_date": payment.created_at,
                    "transaction_reference": f"TXN-{payment.financial_transaction.id}",
                }
                for payment in payments
            ],
        }

        return Response(data)

    @action(detail=False, methods=["get"])
    def payment_statistics(self, request):
        """Statistiques générales des paiements"""
        period_days = int(request.query_params.get("period_days", 30))
        start_date = timezone.now().date() - timedelta(days=period_days)

        # Statistiques générales
        total_subscriptions = ShareSubscription.objects.count()
        recent_payments = SharePayment.objects.filter(created_at__date__gte=start_date)
        recent_payments_amount = (
            recent_payments.aggregate(total=Sum("financial_transaction__amount"))[
                "total"
            ]
            or 0
        )

        # Répartition par statut
        all_subscriptions = ShareSubscription.objects.all()
        fully_paid = [s for s in all_subscriptions if s.is_fully_paid]
        partially_paid = [
            s for s in all_subscriptions if s.paid_quantity > 0 and not s.is_fully_paid
        ]
        not_paid = [s for s in all_subscriptions if s.paid_quantity == 0]

        data = {
            "period_info": {
                "period_days": period_days,
                "start_date": start_date,
                "end_date": timezone.now().date(),
            },
            "general_statistics": {
                "total_subscriptions": total_subscriptions,
                "recent_payments_count": recent_payments.count(),
                "recent_payments_amount": recent_payments_amount,
            },
            "payment_status_breakdown": {
                "fully_paid": {
                    "count": len(fully_paid),
                    "percentage": (
                        len(fully_paid) / total_subscriptions * 100
                        if total_subscriptions > 0
                        else 0
                    ),
                },
                "partially_paid": {
                    "count": len(partially_paid),
                    "percentage": (
                        len(partially_paid) / total_subscriptions * 100
                        if total_subscriptions > 0
                        else 0
                    ),
                },
                "not_paid": {
                    "count": len(not_paid),
                    "percentage": (
                        len(not_paid) / total_subscriptions * 100
                        if total_subscriptions > 0
                        else 0
                    ),
                },
            },
        }

        return Response(data)

    @action(detail=False, methods=["post"])
    def record_payment(self, request):
        """Enregistrer un nouveau paiement"""
        subscription_id = request.data.get("subscription_id")
        quantity = request.data.get("quantity")

        if not subscription_id or not quantity:
            return Response(
                {"error": "subscription_id and quantity are required"},
                status=status.HTTP_400_BAD_REQUEST,
            )

        try:
            subscription = ShareSubscription.objects.get(id=subscription_id)
        except ShareSubscription.DoesNotExist:
            return Response(
                {"error": "Subscription not found"}, status=status.HTTP_404_NOT_FOUND
            )

        try:
            # Vérifier que le membre a un compte courant
            from apps.banking.models import Account

            from_account = Account.objects.get(
                owner=subscription.member.user, type=Account.AccountType.CURRENT
            )

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

            # Récupérer le paiement créé
            latest_payment = subscription.payments.order_by("-created_at").first()

            return Response(
                {
                    "success": True,
                    "message": f"Paiement de {quantity} parts enregistré avec succès",
                    "payment": {
                        "id": latest_payment.id,
                        "quantity": latest_payment.paid_quantity,
                        "amount": latest_payment.amount_paid,
                        "transaction_reference": f"TXN-{latest_payment.financial_transaction.id}",
                        "date": latest_payment.created_at,
                    },
                    "subscription_status": {
                        "paid_quantity": subscription.paid_quantity,
                        "subscribed_quantity": subscription.subscribed_quantity,
                        "is_fully_paid": subscription.is_fully_paid,
                    },
                }
            )

        except Account.DoesNotExist:
            return Response(
                {"error": "Member current account not found"},
                status=status.HTTP_400_BAD_REQUEST,
            )
        except ValueError as e:
            return Response({"error": str(e)}, status=status.HTTP_400_BAD_REQUEST)
        except Exception as e:
            return Response(
                {"error": f"Payment processing error: {str(e)}"},
                status=status.HTTP_500_INTERNAL_SERVER_ERROR,
            )
