"""
Brynq Subscription Billing via Stripe.

Handles SaaS subscription tiers (Free, Pro, Team).
Creates checkout sessions, validates subscriptions, and manages customers.
Credentials must be provided via the STRIPE_API_KEY environment variable.
"""

import os
import time
import logging
from typing import Optional, Dict, Any, List

try:
    from dotenv import load_dotenv
    load_dotenv()
except ImportError:
    pass

try:
    import stripe
except ImportError:
    stripe = None

logger = logging.getLogger(__name__)

# ── Configuration ─────────────────────────────────────────────
STRIPE_API_KEY = os.environ.get("STRIPE_API_KEY")
if stripe and STRIPE_API_KEY:
    stripe.api_key = STRIPE_API_KEY

# Plan Definitions
PLANS = {
    "free": {"price_id": None, "amount": 0, "name": "Developer (Free)"},
    "pro": {"price_id": os.environ.get("STRIPE_PRICE_PRO", "price_1xxxxxx"), "amount": 4900, "name": "Pro"},
    "team": {"price_id": os.environ.get("STRIPE_PRICE_TEAM", "price_2xxxxxx"), "amount": 9900, "name": "Team"}
}

def _configured() -> bool:
    """Check if Stripe is properly configured and installed."""
    if not stripe:
        logger.warning("Stripe package not installed. Run `pip install stripe`.")
        return False
    if not STRIPE_API_KEY:
        logger.warning("STRIPE_API_KEY environment variable not set. Billing disabled.")
        return False
    return True

# ── Customer Management ───────────────────────────────────────

def get_or_create_customer(email: str, name: Optional[str] = None) -> Optional[Dict[str, Any]]:
    """Retrieve an existing Stripe customer by email, or create a new one."""
    if not _configured():
        return None
        
    try:
        # Search for existing customer
        customers = stripe.Customer.search(
            query=f"email:'{email}'",
            limit=1
        )
        if customers.data:
            return customers.data[0]
            
        # Create new customer
        customer = stripe.Customer.create(
            email=email,
            name=name,
            metadata={"source": "brynq_platform"}
        )
        return customer
    except Exception as e:
        logger.error(f"Failed to get/create Stripe customer: {e}")
        return None

# ── Checkout Sessions ─────────────────────────────────────────

def create_checkout_session(email: str, plan_id: str, success_url: str, cancel_url: str) -> Optional[str]:
    """Generate a Stripe Checkout URL for a specific subscription plan."""
    if not _configured():
        return None
        
    if plan_id not in PLANS or plan_id == "free":
        logger.error(f"Invalid paid plan ID: {plan_id}")
        return None
        
    try:
        customer = get_or_create_customer(email)
        if not customer:
            return None
            
        price_id = PLANS[plan_id]["price_id"]
        
        session = stripe.checkout.Session.create(
            customer=customer.id,
            payment_method_types=['card'],
            line_items=[{
                'price': price_id,
                'quantity': 1,
            }],
            mode='subscription',
            success_url=success_url,
            cancel_url=cancel_url,
        )
        return session.url
    except Exception as e:
        logger.error(f"Failed to create Stripe checkout session: {e}")
        return None

# ── Subscription Status ───────────────────────────────────────

def check_subscription_status(email: str) -> Dict[str, Any]:
    """
    Check the active subscription status for a user.
    Returns a dict with: 'status' (active/inactive), 'plan' (free/pro/team), 'current_period_end'
    """
    default_status = {"status": "active", "plan": "free", "current_period_end": None}
    
    if not _configured():
        return default_status
        
    try:
        customer = get_or_create_customer(email)
        if not customer:
            return default_status
            
        subscriptions = stripe.Subscription.list(
            customer=customer.id,
            status="active",
            limit=1
        )
        
        if not subscriptions.data:
            return default_status
            
        sub = subscriptions.data[0]
        price_id = sub.items.data[0].price.id
        
        # Reverse lookup the plan name from the price_id
        plan_name = "free"
        for pid, pdata in PLANS.items():
            if pdata.get("price_id") == price_id:
                plan_name = pid
                break
                
        return {
            "status": sub.status,
            "plan": plan_name,
            "current_period_end": sub.current_period_end,
            "cancel_at_period_end": sub.cancel_at_period_end
        }
    except Exception as e:
        logger.error(f"Failed to check subscription status: {e}")
        return default_status

def create_portal_session(email: str, return_url: str) -> Optional[str]:
    """Generate a Stripe Customer Portal URL so users can manage/cancel their subscription."""
    if not _configured():
        return None
        
    try:
        customer = get_or_create_customer(email)
        if not customer:
            return None
            
        session = stripe.billing_portal.Session.create(
            customer=customer.id,
            return_url=return_url,
        )
        return session.url
    except Exception as e:
        logger.error(f"Failed to create portal session: {e}")
        return None
