from recharge.models import RechargeTransaction
from payments.models import (
    ExternalWalletTopUp,
    ExternalWalletUsage,
    ViralPeWalletUsage,
    RechargePaymentSummary,
)
from decimal import Decimal
from django.utils.timezone import localtime

import random, string
from django.utils.timezone import now

def generate_wallet_credit_order_id() -> str:
    """
    15 chars, starts with 'WCR' (Wallet CReddit), then yymmdd, then 6 random digits.
    Example: WCR250923123456
    """
    prefix = "WCR"
    date = now().strftime("%y%m%d")       # 6
    tail = ''.join(random.choices(string.digits, k=6))
    return f"{prefix}{date}{tail}"        # 3 + 6 + 6 = 15



def _to_float(x):
    try:
        return float(Decimal(x))
    except Exception:
        try:
            return float(x)
        except Exception:
            return 0.0
        
from django.utils.timezone import localtime
from decimal import Decimal

def _to_float(v):
    if v is None:
        return 0.0
    if isinstance(v, Decimal):
        return float(v)
    try:
        return float(v)
    except Exception:
        return 0.0


def get_all_user_transactions(user):

    # 🚧 If not authenticated, return empty list (or raise)
    # if not getattr(user, "is_authenticated", False) or not getattr(user, "pk", None):
    #     return []

    uid = user.pk
    transactions: list[dict] = []

    # ---- Recharge Transactions (Debit) ----
    # Prefer scoping by user_id; fall back cleanly if your model lacks that field.
    try:
        r_qs = RechargeTransaction.objects.filter(
            user_id=uid, number__isnull=False
        ).order_by("-created_at")
    except Exception:
        # TODO: if your RechargeTransaction has a different user field (e.g. created_by),
        # replace below accordingly, or remove this block if recharges are global by design.
        r_qs = RechargeTransaction.objects.none()

    for r in r_qs:
        transactions.append({
            "id": f"recharge-{r.id}",
            "type": "Recharge",
            "service": "recharge",
            "is_credit": False,
            "amount": _to_float(r.amount),
            "timestamp": localtime(r.created_at),
            "order_id": getattr(r, "order_id", None),
            "description": f"Recharge to {getattr(r, 'number', '')}",
            "full_data": r,  # stripped later in the API
        })

    # # ---- External Wallet Top-Ups (Credit) ----
    # for w in ExternalWalletTopUp.objects.filter(user_id=uid).order_by("-added_on"):
    #     transactions.append({
    #         "id": f"topup-{w.id}",
    #         "type": "Wallet Top-up",
    #         "service": "wallet",
    #         "is_credit": True,
    #         "amount": _to_float(w.amount),
    #         "timestamp": localtime(w.added_on),
    #         "order_id": f"EXT-{w.id}",
    #         "description": "External Wallet Top-up",
    #         "full_data": w,
    #     })

    # # ---- External Wallet Usages (Debit) ----
    # for e in ExternalWalletUsage.objects.filter(user_id=uid).order_by("-used_on"):
    #     transactions.append({
    #         "id": f"extuse-{e.id}",
    #         "type": "Wallet Debit",
    #         "service": "wallet",
    #         "is_credit": False,
    #         "amount": _to_float(e.amount_used),
    #         "timestamp": localtime(e.used_on),
    #         "order_id": f"EXTU-{e.id}",
    #         "description": f"{getattr(e, 'used_for', '')}",
    #         "full_data": e,
    #     })

    # # ---- ViralPe Wallet Usages (Debit) ----
    # for v in ViralPeWalletUsage.objects.filter(user_id=uid).order_by("-used_on"):
    #     transactions.append({
    #         "id": f"vpuse-{v.id}",
    #         "type": "VP Wallet Debit",
    #         "service": "wallet",
    #         "is_credit": False,
    #         "amount": _to_float(v.amount_used),
    #         "timestamp": localtime(v.used_on),
    #         "order_id": f"VPU-{v.id}",
    #         "description": f"{getattr(v, 'purpose', '')}",
    #         "full_data": v,
    #     })

    # NOTE: When you add Cashback/Commission models, follow the same user_id pattern.

    # Sort newest first
    transactions.sort(key=lambda x: x["timestamp"], reverse=True)
    return transactions

from django.core.exceptions import FieldError

def get_all_user_recharge_transactions(user):

    # 🚧 If not authenticated, return empty list (or raise)
    # if not getattr(user, "is_authenticated", False) or not getattr(user, "pk", None):
    #     return []

    uid = getattr(user, "pk", None)
    # transactions: list[dict] = []
    if uid is None:
        return transactions

    transactions = []
    # ---- Recharge Transactions (Debit) ----
    # Prefer scoping by user_id; fall back cleanly if your model lacks that field.
    try:
        r_qs = RechargeTransaction.objects.filter(
            user_id=uid, number__isnull=False
        ).order_by("-created_at")
    except FieldError:
        # Model doesn’t have user field — return empty to avoid leaking other users’ data
        return transactions

    for r in r_qs:
        transactions.append({
            "id": f"recharge-{r.id}",
            "type": "Recharge",
            "service": "recharge",
            "is_credit": False,
            "amount": _to_float(r.amount),

            # dates
            "timestamp": localtime(r.created_at),

            # core identifiers
            "order_id": getattr(r, "order_id", None),
            "client_txn_id": getattr(r, "client_txn_id", None),
            "provider_order_id": getattr(r, "provider_order_id", None),

            # status
            "status": getattr(r, "status", None),
            "status_message": getattr(r, "status_message", None),

            # what the txn was for
            "description": f"Recharge to {getattr(r, 'number', '')}",
            "number": getattr(r, "number", None),
            "service_type": getattr(r, "service_type", None),

            # operator / circle (defensive lookups)
            "operator_code": getattr(getattr(r, "operator", None), "code", None),
            "operator_name": getattr(getattr(r, "operator", None), "name", None),
            "circle_code": getattr(getattr(r, "circle", None), "code", None),
            "circle_name": getattr(getattr(r, "circle", None), "name", None),

            # payment split (for detail screen)
            "used_ext_wallet": _to_float(getattr(r, "used_ext_wallet", 0)),
            "used_viralpe_wallet": _to_float(getattr(r, "used_viralpe_wallet", 0)),
            "paid_via_gateway": _to_float(getattr(r, "paid_via_gateway", 0)),

            # refund state (optional)
            "refund_status": getattr(r, "refund_status", None),

            "full_data": r,  # will be stripped before sending
        })



    # NOTE: When you add Cashback/Commission models, follow the same user_id pattern.

    # Sort newest first
    transactions.sort(key=lambda x: x["timestamp"], reverse=True)
    # print(transactions)
    return transactions

from django.utils import timezone
from payments.models import CommissionLog, GeoCommissionWallet, CommissionConfig, CommissionSplitConfig
from django.db.models import F

def distribute_commissions(user, service_type, operator,amount, transaction_id):
    try:
        config = CommissionConfig.objects.get(operator=operator)
        operator_commission = config.fixed_percentage
        commission_amt = (amount * operator_commission) / 100.0
    except CommissionConfig.DoesNotExist:
        return  # No config defined, skip

    # print('======================= CommissionConfig > Operator ===============================')
    # print(config)
    # print(operator_commission)

    splits = CommissionSplitConfig.objects.all()
    # print('=========================== CommissionSplitConfig > All ===========================')
    # print(splits)
    for split in splits:
        role = split.role
        role_commission_amt = (commission_amt*split.percentage)/100.0

        
        
        # Determine target user
        if role == "user":
            target_user = user
        elif role == "referral":
            target_user = user.referred_by
        elif role == "vendor_ref":
            target_user = getattr(user, 'vendor_referred_by', None)
        elif role in ["pincode", "district", "state", "vertical", "TnM","company"]:
            target_user = getattr(user, f'{role}_head', None)
        else:
            continue

        if not target_user:
            continue

        CommissionLog.objects.create(
            user=target_user,
            transaction_id=transaction_id,
            service_type=service_type,
            amount=commission_amt,
            role=role,
            region_type=split.region_type or "",
            region_value=split.region_value or "",
            is_credited=True,
            approved_at=timezone.now()
        )

        # Update balance
        wallet, _ = GeoCommissionWallet.objects.get_or_create(user=target_user)
        wallet.balance = F('balance') + commission_amt
        wallet.save()
