# payments/management/commands/list_wallet_usage.py
from decimal import Decimal
from datetime import datetime, date

from django.core.management.base import BaseCommand, CommandError
from django.db.models.functions import TruncDate
from django.db.models import Sum

from accounts.models import User
from payments.models import ViralPeWallet, ViralPeWalletUsage


def signed(usage: ViralPeWalletUsage) -> Decimal:
    amt = Decimal(usage.amount_used)
    return amt if usage.transaction_type == "credit" else (amt * Decimal("-1"))


class Command(BaseCommand):
    help = (
        "List ViralPe wallet usage entries for a user (by mobile).\n"
        "Supports single date (--date) or a date range (--from, --to). "
        "Outputs totals for credit/debit and current wallet balance. "
        "Use --csv to export."
    )

    def add_arguments(self, parser):
        parser.add_argument("--mobile", required=True, help="Mobile number (e.g. 9000000007)")
        parser.add_argument("--date", dest="on_date", default=None, help="YYYY-MM-DD (single day)")
        parser.add_argument("--from", dest="date_from", default=None, help="YYYY-MM-DD (start, inclusive)")
        parser.add_argument("--to", dest="date_to", default=None, help="YYYY-MM-DD (end, inclusive)")
        parser.add_argument("--limit", type=int, default=None, help="Limit number of rows (newest first)")
        parser.add_argument("--csv", dest="csv_path", default=None, help="Path to write CSV export")
        parser.add_argument("--order", choices=["asc", "desc"], default="desc", help="Row order by used_on")

    def handle(self, *args, **opts):
        mobile = opts["mobile"]
        on_date = opts["on_date"]
        date_from = opts["date_from"]
        date_to = opts["date_to"]
        limit = opts["limit"]
        csv_path = opts["csv_path"]
        order = opts["order"]

        # Resolve user
        try:
            user = User.objects.get(mobile_number=mobile)
        except User.DoesNotExist:
            raise CommandError(f"User with mobile {mobile} not found.")

        qs = ViralPeWalletUsage.objects.filter(user=user)

        # Date filters
        if on_date:
            try:
                d = datetime.strptime(on_date, "%Y-%m-%d").date()
            except ValueError:
                raise CommandError("Invalid --date. Use YYYY-MM-DD")
            qs = qs.annotate(date_only=TruncDate("used_on")).filter(date_only=d)

        if date_from:
            try:
                d1 = datetime.strptime(date_from, "%Y-%m-%d").date()
            except ValueError:
                raise CommandError("Invalid --from. Use YYYY-MM-DD")
            qs = qs.filter(used_on__date__gte=d1)

        if date_to:
            try:
                d2 = datetime.strptime(date_to, "%Y-%m-%d").date()
            except ValueError:
                raise CommandError("Invalid --to. Use YYYY-MM-DD")
            qs = qs.filter(used_on__date__lte=d2)

        qs = qs.order_by(("-" if order == "desc" else "") + "used_on", "-" + "id")

        count = qs.count()

        # Current wallet balance
        wallet = ViralPeWallet.objects.filter(user=user).first()
        curr_balance = wallet.balance if wallet else Decimal("0.00")

        # Print header
        self.stdout.write(f"User: {user.id} / {mobile}")
        if on_date:
            self.stdout.write(f"Filter: date = {on_date}")
        else:
            if date_from or date_to:
                self.stdout.write(f"Filter: from={date_from or '-'} to={date_to or '-'}")
        self.stdout.write(f"Rows: {count}")
        self.stdout.write(f"Current Wallet Balance: {curr_balance}\n")

        # Sum credit & debit over filtered set (not entire history)
        agg_credit = qs.filter(transaction_type="credit").aggregate(s=Sum("amount_used"))["s"] or Decimal("0")
        agg_debit = qs.filter(transaction_type="debit").aggregate(s=Sum("amount_used"))["s"] or Decimal("0")
        self.stdout.write(f"Total Credit (filtered): {agg_credit}")
        self.stdout.write(f"Total Debit  (filtered): {agg_debit}\n")

        # Optional CSV export
        writer = None
        if csv_path:
            import csv
            f = open(csv_path, "w", newline="", encoding="utf-8")
            writer = csv.writer(f)
            writer.writerow([
                "id", "used_on", "type", "amount", "purpose_code", "purpose",
                "purpose_note", "order_id", "reference_user", "signed"
            ])

        # Print rows
        shown = 0
        for u in qs[:limit] if limit else qs:
            row = (
                f"#{u.id}  {u.used_on:%Y-%m-%d %H:%M:%S}  "
                f"[{u.transaction_type.upper():5}]  amt={u.amount_used}  "
                f"pcode={u.purpose_code}  purpose={u.purpose!r}  note={u.purpose_note!r}  "
                f"order_id={u.order_id or ''}  by={(u.reference_user.first_name if u.reference_user else '')}  "
                f"signed={signed(u)}"
            )
            self.stdout.write(row)
            if writer:
                writer.writerow([
                    u.id,
                    u.used_on.strftime("%Y-%m-%d %H:%M:%S"),
                    u.transaction_type,
                    f"{u.amount_used:.2f}",
                    u.purpose_code,
                    u.purpose,
                    u.purpose_note,
                    u.order_id or "",
                    (u.reference_user.first_name if u.reference_user else ""),
                    f"{signed(u):.2f}",
                ])
            shown += 1

        if writer:
            f.close()
            self.stdout.write(f"\nCSV written to: {csv_path}")

        self.stdout.write(f"\nShown: {shown} / {count}")
