#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import stripe
from pprint import pprint
from decimal import Decimal
import os

# ============================
# CONFIGURA AQUÍ EL INVOICE
# ============================
TEST_INVOICE_ID = "in_1SRukCEiGxFFi4pPp7hEkZRh"   # <-- cámbialo cuando quieras probar otro

# API KEY LIVE (SOLO LECTURA)
stripe.api_key = os.getenv("STRIPE_SECRET_KEY")

# IMPORTA TU APP Y MODELO (ajusta estos paths si hace falta)
from app import app  # donde defines Flask(...)
from models import Youtuber  # ajusta si tu modelo está en otro módulo


def _find_affiliate_in_db(youtuber_id, referrer_code):
    """
    MISMA LÓGICA QUE PRODUCCIÓN.
    Devuelve (yt, stripe_account_id, commission_percent_decimal) o (None, None, None)
    """
    try:
        with app.app_context():
            yt = None
            if youtuber_id:
                yt = Youtuber.query.filter_by(id=youtuber_id).first()
            if (not yt) and referrer_code:
                yt = Youtuber.query.filter_by(referrer_code=referrer_code).first()
            if yt and yt.stripe_account_id:
                pct = Decimal(str(yt.commission_percent or 10.0)) / Decimal("100")
                return yt, yt.stripe_account_id, pct
    except Exception as e:
        print(f"[affiliate_test] DB lookup error: {e}")
    return None, None, None


def detect_subscription(inv):
    """
    Detecta subscription_id usando los mismos métodos que en producción.
    """
    subscription_id = inv.get("subscription")

    if not subscription_id:
        lines = (inv.get("lines") or {}).get("data", [])
        for li in lines:
            if li.get("subscription"):
                subscription_id = li["subscription"]
                break

            parent = li.get("parent", {}).get("subscription_item_details", {})
            if parent.get("subscription"):
                subscription_id = parent["subscription"]
                break

    if not subscription_id:
        subscription_id = (
            inv.get("parent", {})
               .get("subscription_details", {})
               .get("subscription")
        )

    return subscription_id


def get_list_price(inv, subscription_id):
    """
    Detecta correctamente el precio de lista de la suscripción asociada.
    """
    list_price_cents = None
    lines = (inv.get("lines", {}) or {}).get("data", [])

    for li in lines:
        # Asegurarnos de que la línea corresponde a ESTA suscripción
        parent = li.get("parent", {}).get("subscription_item_details", {})
        if parent.get("subscription") and parent["subscription"] != subscription_id:
            continue

        # Formato nuevo (2024–2025): pricing.unit_amount_decimal
        pricing = li.get("pricing") or {}
        ua_dec = pricing.get("unit_amount_decimal")
        if ua_dec:
            try:
                return int(float(ua_dec))
            except Exception as e:
                print(f"[affiliate_test] error parsing unit_amount_decimal: {e}")

        # Formato antiguo: price.unit_amount
        price_obj = li.get("price") or {}
        ua_old = price_obj.get("unit_amount")
        if ua_old is not None:
            return int(ua_old)

    # Fallback: subtotal
    return int(inv.get("subtotal") or inv.get("amount_subtotal") or 0)


def test_invoice(invoice_id: str):
    print("\n================= PREVIEW COMISIÓN AFILIADO =================\n")

    inv = stripe.Invoice.retrieve(
        invoice_id,
        expand=["lines.data.price"]
    )

    amount_paid = int(inv.get("amount_paid") or 0)
    currency = inv.get("currency", "usd")
    billing_reason = inv.get("billing_reason") or ""

    print(f"invoice_id: {invoice_id}")
    print(f"amount_paid={amount_paid} {currency}  billing_reason={billing_reason}")

    # 1) Detectar subscription_id
    subscription_id = detect_subscription(inv)
    print(f"subscription_id_detectado: {subscription_id}\n")

    if not subscription_id:
        print("❌ No se encontró ninguna suscripción para este invoice.")
        print("\n============================================================")
        return

    # 2) Leer metadata de la suscripción
    sub = stripe.Subscription.retrieve(subscription_id)
    sub_meta = sub.get("metadata") or {}
    sub_status = sub.get("status")

    print("subscription metadata:")
    pprint(sub_meta)

    # 3) Detectar si ES un invoice de trial a 0 (igual que en producción)
    is_trial_zero_invoice = (
        amount_paid == 0 and
        billing_reason == "subscription_create" and
        sub_status == "trialing"
    )
    is_paid_invoice = amount_paid > 0

    # Leer datos de afiliado desde metadata
    referrer_code = sub_meta.get("referrer_code")
    youtuber_id = sub_meta.get("youtuber_id")

    # 4) Resolver afiliado real en tu DB
    yt, dest_acct, pct = _find_affiliate_in_db(youtuber_id, referrer_code)

    print("\nAfiliado en DB (real):")
    if yt:
        print(f"  youtuber_id : {yt.id}")
        print(f"  email       : {yt.email}")
        print(f"  ref_code    : {yt.referrer_code}")
        print(f"  dest_acct   : {dest_acct}")
        print(f"  pct         : {pct}")
    else:
        print("  ❌ No se encontró afiliado para esos parámetros.")
        print("\n============================================================")
        return

    # 5) Respetar la misma lógica de producción
    if is_trial_zero_invoice:
        print("\n⚠ Este invoice es de TRIAL $0 (subscription_create + trialing).")
        print("   En producción NO se paga comisión por este invoice.")
        print("   (Solo empezarías a pagar desde el primer invoice con amount_paid > 0).")
        print("\n============================================================")
        return

    if not is_paid_invoice:
        print("\n⚠ Este invoice no está pagado (amount_paid == 0).")
        print("   En producción tampoco se pagaría comisión aún.")
        print("\n============================================================")
        return

    # 6) Calcular base de comisión y comisión
    base_cents = get_list_price(inv, subscription_id)

    print("\nCálculo de comisión (DRY-RUN, NO se paga):")
    print(f"  base_cents        : {base_cents}  → {base_cents/100:.2f} usd")
    print(f"  pct               : {pct}  → {pct*100:.2f}%")

    commission_cents = int(Decimal(base_cents) * pct)
    print(f"  commission_cents  : {commission_cents}  → {commission_cents/100:.2f} usd")
    print(f"  destino (Connect) : {dest_acct}")

    print("\n============================================================")


if __name__ == "__main__":
    test_invoice(TEST_INVOICE_ID)
