#!/usr/bin/env python3
"""
Eden PayPal IPN Handler
Automatically detects payments and completes orders
"""
import sys
sys.path.append('/Eden/CORE')

import json
import sqlite3
import hashlib
import urllib.parse
import urllib.request
from datetime import datetime
from pathlib import Path
from http.server import HTTPServer, BaseHTTPRequestHandler
import threading
import time

from sage_product_catalog import SageProductCatalog

PAYPAL_EMAIL = "jamlen@hotmail.ca"
DB_PATH = "/Eden/DATA/sales.db"
IPN_LOG = "/Eden/DATA/paypal_ipn.log"

# PayPal IPN verification URLs
PAYPAL_VERIFY_URL = "https://ipnpb.paypal.com/cgi-bin/webscr"  # Live
PAYPAL_SANDBOX_URL = "https://ipnpb.sandbox.paypal.com/cgi-bin/webscr"  # Sandbox

USE_SANDBOX = False  # Set True for testing


class PayPalIPNHandler(BaseHTTPRequestHandler):
    """Handle incoming PayPal IPN notifications"""
    
    def log_message(self, format, *args):
        """Log to file instead of stderr"""
        with open(IPN_LOG, 'a') as f:
            f.write(f"[{datetime.now().isoformat()}] {format % args}\n")
    
    def do_POST(self):
        """Process IPN POST from PayPal"""
        try:
            # Read the POST data
            content_length = int(self.headers.get('Content-Length', 0))
            post_data = self.rfile.read(content_length).decode('utf-8')
            
            # Log incoming IPN
            self.log_ipn("RECEIVED", post_data)
            
            # Verify with PayPal
            if self.verify_ipn(post_data):
                # Parse the data
                params = urllib.parse.parse_qs(post_data)
                self.process_payment(params)
                
            # Always respond 200 to PayPal
            self.send_response(200)
            self.end_headers()
            
        except Exception as e:
            self.log_ipn("ERROR", str(e))
            self.send_response(200)  # Still respond 200
            self.end_headers()
    
    def verify_ipn(self, post_data: str) -> bool:
        """Verify IPN with PayPal"""
        # Prepend cmd=_notify-validate
        verify_data = f"cmd=_notify-validate&{post_data}"
        
        verify_url = PAYPAL_SANDBOX_URL if USE_SANDBOX else PAYPAL_VERIFY_URL
        
        try:
            req = urllib.request.Request(verify_url, verify_data.encode('utf-8'))
            req.add_header('Content-Type', 'application/x-www-form-urlencoded')
            
            with urllib.request.urlopen(req, timeout=30) as response:
                result = response.read().decode('utf-8')
                
            if result == "VERIFIED":
                self.log_ipn("VERIFIED", "PayPal confirmed")
                return True
            else:
                self.log_ipn("INVALID", f"PayPal response: {result}")
                return False
                
        except Exception as e:
            self.log_ipn("VERIFY_ERROR", str(e))
            return False
    
    def process_payment(self, params: dict):
        """Process verified payment"""
        # Extract payment details
        payment_status = params.get('payment_status', [''])[0]
        receiver_email = params.get('receiver_email', [''])[0]
        mc_gross = params.get('mc_gross', ['0'])[0]
        txn_id = params.get('txn_id', [''])[0]
        payer_email = params.get('payer_email', [''])[0]
        custom = params.get('custom', [''])[0]  # Order ID if we set it
        item_name = params.get('item_name', [''])[0]
        
        self.log_ipn("PAYMENT", f"Status: {payment_status}, Amount: ${mc_gross}, From: {payer_email}")
        
        # Verify it's for us
        if receiver_email.lower() != PAYPAL_EMAIL.lower():
            self.log_ipn("WRONG_RECEIVER", f"Got {receiver_email}, expected {PAYPAL_EMAIL}")
            return
        
        # Only process completed payments
        if payment_status != "Completed":
            self.log_ipn("NOT_COMPLETED", f"Status: {payment_status}")
            return
        
        # Find matching order
        order_id = self.find_order(float(mc_gross), payer_email, custom)
        
        if order_id:
            self.complete_order(order_id, txn_id, mc_gross, payer_email)
        else:
            # New payment without order - create one
            self.record_direct_payment(txn_id, mc_gross, payer_email, item_name)
    
    def find_order(self, amount: float, payer_email: str, custom: str) -> str:
        """Find matching pending order"""
        conn = sqlite3.connect(DB_PATH)
        c = conn.cursor()
        
        # Try custom field (order ID) first
        if custom:
            c.execute("SELECT id FROM orders WHERE id = ? AND status = 'pending'", (custom,))
            result = c.fetchone()
            if result:
                conn.close()
                return result[0]
        
        # Try matching by amount and email
        c.execute("""SELECT id FROM orders 
                    WHERE amount = ? AND status = 'pending' 
                    ORDER BY created_at DESC LIMIT 1""", (amount,))
        result = c.fetchone()
        conn.close()
        
        return result[0] if result else None
    
    def complete_order(self, order_id: str, txn_id: str, amount: str, payer_email: str):
        """Mark order as completed"""
        conn = sqlite3.connect(DB_PATH)
        c = conn.cursor()
        
        c.execute("""UPDATE orders 
                    SET status = 'completed', 
                        payment_id = ?,
                        completed_at = CURRENT_TIMESTAMP
                    WHERE id = ?""", (txn_id, order_id))
        
        # Get order details for logging
        c.execute("SELECT product_id, amount FROM orders WHERE id = ?", (order_id,))
        order = c.fetchone()
        
        conn.commit()
        conn.close()
        
        self.log_ipn("ORDER_COMPLETED", 
                    f"Order {order_id} | Product: {order[0]} | ${order[1]} | TXN: {txn_id}")
        
        # Celebrate!
        print(f"\n{'='*50}")
        print(f"  💰 PAYMENT RECEIVED!")
        print(f"  Order: {order_id}")
        print(f"  Amount: ${amount}")
        print(f"  From: {payer_email}")
        print(f"  Product: {order[0]}")
        print(f"{'='*50}\n")
    
    def record_direct_payment(self, txn_id: str, amount: str, payer_email: str, item_name: str):
        """Record payment that didn't match an order"""
        conn = sqlite3.connect(DB_PATH)
        c = conn.cursor()
        
        # Create a completed order for tracking
        order_id = hashlib.sha256(txn_id.encode()).hexdigest()[:16].upper()
        
        c.execute("""INSERT INTO orders 
                    (id, product_id, customer_email, amount, status, payment_id, completed_at)
                    VALUES (?, 'direct_payment', ?, ?, 'completed', ?, CURRENT_TIMESTAMP)""",
                 (order_id, payer_email, float(amount), txn_id))
        
        conn.commit()
        conn.close()
        
        self.log_ipn("DIRECT_PAYMENT", f"${amount} from {payer_email} | TXN: {txn_id}")
        
        print(f"\n{'='*50}")
        print(f"  💰 DIRECT PAYMENT RECEIVED!")
        print(f"  Amount: ${amount}")
        print(f"  From: {payer_email}")
        print(f"  Item: {item_name or 'N/A'}")
        print(f"{'='*50}\n")
    
    def log_ipn(self, event_type: str, message: str):
        """Log IPN event"""
        log_entry = {
            "timestamp": datetime.now().isoformat(),
            "type": event_type,
            "message": message
        }
        with open(IPN_LOG, 'a') as f:
            f.write(json.dumps(log_entry) + "\n")


def run_ipn_server(port: int = 8765):
    """Run the IPN listener server"""
    server = HTTPServer(('0.0.0.0', port), PayPalIPNHandler)
    print(f"[IPN SERVER] Listening on port {port}")
    print(f"[IPN SERVER] PayPal email: {PAYPAL_EMAIL}")
    print(f"[IPN SERVER] Mode: {'SANDBOX' if USE_SANDBOX else 'LIVE'}")
    server.serve_forever()


def check_manual_payment(txn_id: str = None, amount: float = None, payer_email: str = None):
    """Manually check/record a payment"""
    catalog = SageProductCatalog()
    
    if txn_id and amount:
        # Find matching order
        conn = sqlite3.connect(DB_PATH)
        c = conn.cursor()
        
        c.execute("""SELECT id, product_id, amount FROM orders 
                    WHERE amount = ? AND status = 'pending'
                    ORDER BY created_at DESC LIMIT 1""", (amount,))
        order = c.fetchone()
        
        if order:
            c.execute("""UPDATE orders 
                        SET status = 'completed', payment_id = ?, completed_at = CURRENT_TIMESTAMP
                        WHERE id = ?""", (txn_id, order[0]))
            conn.commit()
            print(f"[MANUAL] Completed order {order[0]} for ${order[2]}")
        else:
            # Record as direct payment
            order_id = hashlib.sha256(txn_id.encode()).hexdigest()[:16].upper()
            c.execute("""INSERT INTO orders 
                        (id, product_id, customer_email, amount, status, payment_id, completed_at)
                        VALUES (?, 'direct_payment', ?, ?, 'completed', ?, CURRENT_TIMESTAMP)""",
                     (order_id, payer_email or 'unknown', amount, txn_id))
            conn.commit()
            print(f"[MANUAL] Recorded direct payment ${amount}")
        
        conn.close()
    
    # Show current stats
    stats = catalog.get_revenue_stats()
    print(f"\n[REVENUE STATS]")
    print(f"  Total Revenue: ${stats['total_revenue']:.2f}")
    print(f"  Completed Orders: {stats['completed_orders']}")
    print(f"  Pending Orders: {stats['pending_orders']}")


def main():
    import argparse
    parser = argparse.ArgumentParser(description='Eden PayPal IPN Handler')
    parser.add_argument('--server', action='store_true', help='Run IPN server')
    parser.add_argument('--port', type=int, default=8765, help='Server port')
    parser.add_argument('--manual', action='store_true', help='Manual payment entry')
    parser.add_argument('--txn', type=str, help='Transaction ID')
    parser.add_argument('--amount', type=float, help='Payment amount')
    parser.add_argument('--email', type=str, help='Payer email')
    parser.add_argument('--stats', action='store_true', help='Show revenue stats')
    
    args = parser.parse_args()
    
    if args.server:
        run_ipn_server(args.port)
    elif args.manual or args.txn:
        check_manual_payment(args.txn, args.amount, args.email)
    elif args.stats:
        check_manual_payment()
    else:
        print("Eden PayPal IPN Handler")
        print("="*40)
        print(f"PayPal Email: {PAYPAL_EMAIL}")
        print(f"IPN Log: {IPN_LOG}")
        print()
        print("Usage:")
        print("  --server         Run IPN listener on port 8765")
        print("  --manual --txn X --amount Y   Record manual payment")
        print("  --stats          Show revenue statistics")
        print()
        print("To enable IPN in PayPal:")
        print("  1. Go to PayPal Business Settings")
        print("  2. Website Payments > Instant Payment Notifications")
        print("  3. Set URL to: http://YOUR_SERVER:8765/ipn")
        print()
        check_manual_payment()


if __name__ == "__main__":
    main()
