import os
from flask import Flask, request, jsonify, render_template
from dotenv import load_dotenv
import stripe
import json
from datetime import datetime

load_dotenv('stripe_config/.env')

app = Flask(__name__)

stripe.api_key = os.getenv("STRIPE_SECRET_KEY")
PUBLISHABLE_KEY = os.getenv("STRIPE_PUBLISHABLE_KEY")
DEFAULT_CURRENCY = os.getenv("DEFAULT_CURRENCY", "GBP")

# In-memory supporter storage (in production, use a proper database)
supporters = []

# Subscription tiers - UPDATE THESE WITH YOUR REAL STRIPE PRICE IDs
SUBSCRIPTION_TIERS = {
    "bronze": {
        "price_id": "price_1SFdA1H7p78X3gVbFafKga1f",  # Bronze tier price ID from Stripe Dashboard
        "amount": 2.00,
        "currency": "GBP",
        "interval": "month",
        "name": "Bronze",
        "description": "Essential support that makes a difference"
    },
    "silver": {
        "price_id": "price_1SFdD4H7p78X3gVb0ENAfHNZ",  # Silver tier price ID from Stripe Dashboard
        "amount": 5.00,
        "currency": "GBP", 
        "interval": "month",
        "name": "Silver",
        "description": "Enhanced support with greater impact"
    },
    "gold": {
        "price_id": "price_1SFdFkH7p78X3gVbLfjZvKIW",  # Gold tier price ID from Stripe Dashboard
        "amount": 10.00,
        "currency": "GBP",
        "interval": "month", 
        "name": "Gold",
        "description": "Premium support for maximum impact"
    },
    "diamond": {
        "price_id": "price_1SFdHFH7p78X3gVbN7UdxkPa",  # Diamond tier price ID from Stripe Dashboard
        "amount": 25.00,
        "currency": "GBP",
        "interval": "month", 
        "name": "Diamond",
        "description": "Ultimate support for our biggest champions"
    }
}

# In-memory customer storage (in production, use a proper database)
customers = []
subscriptions = []

@app.route("/")
def index():
    return render_template("index.html")

@app.route("/config")
def config():
    return jsonify({"publishableKey": PUBLISHABLE_KEY})

@app.route("/create-payment-intent", methods=["POST"])
def create_payment():
    data = request.get_json()
    amount = int(float(data["amount"]) * 100)  # convert to cents/pence
    currency = data.get("currency", DEFAULT_CURRENCY).lower()
    supporter_name = data.get("supporterName", "").strip()

    intent = stripe.PaymentIntent.create(
        amount=amount,
        currency=currency,
        automatic_payment_methods={
            "enabled": True,
            "allow_redirects": "never"  # Keep users on the page
        },
        metadata={
            "source": "donation_page",
            "currency": currency,
            "supporter_name": supporter_name if supporter_name else "Anonymous"
        }
    )
    return jsonify({"clientSecret": intent.client_secret})

@app.route("/add-supporter", methods=["POST"])
def add_supporter():
    data = request.get_json()
    supporter_name = data.get("name", "Anonymous").strip()
    amount = data.get("amount", 0)
    currency = data.get("currency", DEFAULT_CURRENCY)
    
    if supporter_name and supporter_name != "Anonymous":
        # Limit name length and sanitize
        supporter_name = supporter_name[:30]
        
        supporter = {
            "name": supporter_name,
            "amount": amount,
            "currency": currency,
            "timestamp": datetime.now().isoformat(),
            "time_ago": "just now"
        }
        
        # Add to beginning of list and keep only last 50
        supporters.insert(0, supporter)
        supporters[:] = supporters[:50]
        
        return jsonify({"success": True})
    
    return jsonify({"success": False})

@app.route("/supporters", methods=["GET"])
def get_supporters():
    # Update time_ago for each supporter
    now = datetime.now()
    for supporter in supporters:
        try:
            timestamp = datetime.fromisoformat(supporter["timestamp"])
            diff = now - timestamp
            
            if diff.days > 0:
                supporter["time_ago"] = f"{diff.days}d ago"
            elif diff.seconds > 3600:
                hours = diff.seconds // 3600
                supporter["time_ago"] = f"{hours}h ago"
            elif diff.seconds > 60:
                minutes = diff.seconds // 60
                supporter["time_ago"] = f"{minutes}m ago"
            else:
                supporter["time_ago"] = "just now"
        except:
            supporter["time_ago"] = "recently"
    
    return jsonify({"supporters": supporters[:20]})  # Return last 20

@app.route("/subscription-tiers", methods=["GET"])
def get_subscription_tiers():
    """Get available subscription tiers"""
    return jsonify({"tiers": SUBSCRIPTION_TIERS})

@app.route("/create-subscription", methods=["POST"])
def create_subscription():
    """Create a new subscription - NOTE: Requires real Stripe Price IDs"""
    data = request.get_json()
    tier_id = data.get("tier_id")
    email = data.get("email")
    name = data.get("name", "").strip()
    
    if tier_id not in SUBSCRIPTION_TIERS:
        return jsonify({"error": "Invalid subscription tier"}), 400
    
    if not email:
        return jsonify({"error": "Email is required for subscriptions"}), 400
    
    # Check if price IDs are still placeholders
    price_id = SUBSCRIPTION_TIERS[tier_id]["price_id"]
    if price_id.startswith("price_1234567890"):
        return jsonify({
            "error": "Subscription functionality requires setting up real Stripe Price IDs. "
                    "Please create products and prices in your Stripe Dashboard first."
        }), 400
    
    try:
        # Create or retrieve customer
        customer = stripe.Customer.create(
            email=email,
            name=name if name else None,
            metadata={
                "source": "donation_subscription"
            }
        )
        
        # Create subscription
        subscription = stripe.Subscription.create(
            customer=customer.id,
            items=[{"price": price_id}],
            payment_behavior="default_incomplete",
            payment_settings={"save_default_payment_method": "on_subscription"},
            expand=["latest_invoice.payment_intent"],
        )
        
        # Store customer and subscription data
        customer_data = {
            "id": customer.id,
            "email": email,
            "name": name,
            "created": datetime.now().isoformat()
        }
        customers.append(customer_data)
        
        subscription_data = {
            "id": subscription.id,
            "customer_id": customer.id,
            "tier_id": tier_id,
            "status": subscription.status,
            "created": datetime.now().isoformat()
        }
        subscriptions.append(subscription_data)
        
        return jsonify({
            "subscriptionId": subscription.id,
            "clientSecret": subscription.latest_invoice.payment_intent.client_secret
        })
        
    except Exception as e:
        # Catch all exceptions since IDE might not recognize stripe error classes
        error_msg = str(e)
        if "No such price" in error_msg:
            return jsonify({"error": "Invalid price ID. Please check your Stripe Dashboard."}), 400
        return jsonify({"error": f"Subscription creation failed: {error_msg}"}), 400

@app.route("/cancel-subscription", methods=["POST"])
def cancel_subscription():
    """Cancel a subscription"""
    data = request.get_json()
    subscription_id = data.get("subscription_id")
    
    if not subscription_id:
        return jsonify({"error": "Subscription ID is required"}), 400
    
    try:
        # Cancel the subscription at period end
        subscription = stripe.Subscription.modify(
            subscription_id,
            cancel_at_period_end=True
        )
        
        # Update local storage
        for sub in subscriptions:
            if sub["id"] == subscription_id:
                sub["status"] = "cancel_at_period_end"
                sub["cancelled_at"] = datetime.now().isoformat()
                break
        
        return jsonify({
            "success": True,
            "message": "Subscription will be cancelled at the end of the current billing period"
        })
        
    except Exception as e:
        return jsonify({"error": f"Cancellation failed: {str(e)}"}), 400

@app.route("/webhook", methods=["POST"])
def stripe_webhook():
    """Handle Stripe webhooks"""
    payload = request.data
    sig_header = request.headers.get('Stripe-Signature')
    endpoint_secret = os.getenv('STRIPE_WEBHOOK_SECRET')
    
    if not endpoint_secret:
        return jsonify({"error": "Webhook secret not configured"}), 400
    
    try:
        event = stripe.Webhook.construct_event(payload, sig_header, endpoint_secret)
    except ValueError:
        return jsonify({"error": "Invalid payload"}), 400
    except Exception as signature_error:
        if "signature" in str(signature_error).lower():
            return jsonify({"error": "Invalid signature"}), 400
        return jsonify({"error": "Webhook processing failed"}), 400
    
    # Handle the event
    if event['type'] == 'invoice.payment_succeeded':
        subscription = event['data']['object']['subscription']
        customer_id = event['data']['object']['customer']
        
        # Update subscription status
        for sub in subscriptions:
            if sub["id"] == subscription:
                sub["status"] = "active"
                sub["last_payment"] = datetime.now().isoformat()
                break
        
        print(f"Payment succeeded for subscription {subscription}")
        
    elif event['type'] == 'invoice.payment_failed':
        subscription = event['data']['object']['subscription']
        
        # Update subscription status
        for sub in subscriptions:
            if sub["id"] == subscription:
                sub["status"] = "past_due"
                sub["last_failed_payment"] = datetime.now().isoformat()
                break
        
        print(f"Payment failed for subscription {subscription}")
        
    elif event['type'] == 'customer.subscription.deleted':
        subscription_id = event['data']['object']['id']
        
        # Update subscription status
        for sub in subscriptions:
            if sub["id"] == subscription_id:
                sub["status"] = "cancelled"
                sub["cancelled_at"] = datetime.now().isoformat()
                break
        
        print(f"Subscription {subscription_id} was cancelled")
    
    return jsonify({"success": True})

if __name__ == "__main__":
    app.run(port=4242, debug=True)
