<?php
// app/Controllers/SubscriptionController.php

class SubscriptionController {
    private function requireAdmin() {
        if (!isset($_SESSION['user_id']) || $_SESSION['role'] !== 'admin') {
            header('Location: /login'); exit;
        }
    }

    public function index() {
        $this->requireAdmin();
        $db = getDB();
        $rest_id = $_SESSION['restaurant_id'];

        $pageTitle = 'Subscription & Billing';

        // Get the restaurant's currency
        $currency = FeatureGate::currency($rest_id);
        
        // Map BDT / USD to symbols
        $searchCurrency = '$';
        if (strcasecmp($currency, '৳') === 0 || strcasecmp($currency, 'BDT') === 0) {
            $searchCurrency = '৳';
        } elseif (strcasecmp($currency, '$') === 0 || strcasecmp($currency, 'USD') === 0) {
            $searchCurrency = '$';
        } else {
            $searchCurrency = $currency;
        }

        // Get standard active packages (exclude trial/free from customer self-purchase)
        $stmt = $db->prepare('
            SELECT * FROM packages 
            WHERE status = "active" 
              AND currency = ? 
              AND name NOT LIKE "%trial%" 
              AND name NOT LIKE "%free%" 
            ORDER BY price ASC
        ');
        $stmt->execute([$searchCurrency]);
        $packages = $stmt->fetchAll();

        // Fallback to USD packages if no packages found for custom currency
        if (empty($packages)) {
            $stmt = $db->prepare('
                SELECT * FROM packages 
                WHERE status = "active" 
                  AND currency = "$" 
                  AND name NOT LIKE "%trial%" 
                  AND name NOT LIKE "%free%" 
                ORDER BY price ASC
            ');
            $stmt->execute([]);
            $packages = $stmt->fetchAll();
        }

        // Get current subscription status via FeatureGate
        $gate = FeatureGate::check($rest_id);

        // Sort packages so the current plan is first in the list (highlighted)
        if ($gate['package_name']) {
            usort($packages, function($a, $b) use ($gate) {
                if ($a['name'] === $gate['package_name']) {
                    return -1;
                }
                if ($b['name'] === $gate['package_name']) {
                    return 1;
                }
                return $a['price'] <=> $b['price'];
            });
        }

        // Get subscription history (limit to 10)
        $history = $db->prepare('
            SELECT s.*, p.name AS package_name
            FROM subscriptions s
            JOIN packages p ON p.id = s.package_id
            WHERE s.restaurant_id = ?
            ORDER BY s.id DESC
            LIMIT 10
        ');
        $history->execute([$rest_id]);
        $history = $history->fetchAll();

        // Get pending subscription request
        $pendingSub = $db->prepare('
            SELECT s.*, p.name AS package_name
            FROM subscriptions s
            JOIN packages p ON p.id = s.package_id
            WHERE s.restaurant_id = ? AND s.status = "pending"
            LIMIT 1
        ');
        $pendingSub->execute([$rest_id]);
        $pendingSub = $pendingSub->fetch();

        ob_start();
        require 'app/Views/admin/subscription/index.php';
        $content = ob_get_clean();
        require 'app/Views/layouts/admin.php';
    }

    public function purchase() {
        $this->requireAdmin();
        $db = getDB();
        $rest_id = $_SESSION['restaurant_id'];
        $pkg_id = $_POST['package_id'] ?? null;

        if (!$pkg_id) {
            header('Location: /admin/subscription?error=Invalid+package+selected'); exit;
        }

        // Fetch package details
        $stmt = $db->prepare('SELECT * FROM packages WHERE id = ? AND status = "active"');
        $stmt->execute([$pkg_id]);
        $pkg = $stmt->fetch();

        if (!$pkg) {
            header('Location: /admin/subscription?error=Package+not+found+or+inactive'); exit;
        }

        // Check if there is already a pending subscription request
        $checkPending = $db->prepare('SELECT id FROM subscriptions WHERE restaurant_id = ? AND status = "pending" LIMIT 1');
        $checkPending->execute([$rest_id]);
        if ($checkPending->fetch()) {
            header('Location: /admin/subscription?error=' . urlencode('You already have a subscription request pending approval.')); exit;
        }

        // Store package ID in session
        $_SESSION['checkout_package_id'] = $pkg_id;
        header('Location: /admin/subscription/payment');
        exit;
    }

    public function payment() {
        $this->requireAdmin();
        $db = getDB();
        $rest_id = $_SESSION['restaurant_id'];
        $pkg_id = $_SESSION['checkout_package_id'] ?? $_GET['package_id'] ?? null;

        if (!$pkg_id) {
            header('Location: /admin/subscription?error=No+package+selected+for+checkout'); exit;
        }

        $stmt = $db->prepare('SELECT * FROM packages WHERE id = ? AND status = "active"');
        $stmt->execute([$pkg_id]);
        $pkg = $stmt->fetch();

        if (!$pkg) {
            header('Location: /admin/subscription?error=Package+not+found+or+inactive'); exit;
        }

        $pageTitle = 'Subscription Checkout';
        
        ob_start();
        require 'app/Views/admin/subscription/payment.php';
        $content = ob_get_clean();
        require 'app/Views/layouts/admin.php';
    }

    public function submitPayment() {
        $this->requireAdmin();
        $db = getDB();
        $rest_id = $_SESSION['restaurant_id'];
        $pkg_id = $_POST['package_id'] ?? null;
        $payment_method = $_POST['payment_method'] ?? '';
        $trans_ref = $_POST['transaction_reference'] ?? '';

        if (!$pkg_id) {
            header('Location: /admin/subscription?error=Invalid+checkout+request'); exit;
        }

        if (empty($payment_method) || empty($trans_ref)) {
            header('Location: /admin/subscription/payment?package_id=' . $pkg_id . '&error=Payment+method+and+reference+are+required'); exit;
        }

        // Fetch package details
        $stmt = $db->prepare('SELECT * FROM packages WHERE id = ? AND status = "active"');
        $stmt->execute([$pkg_id]);
        $pkg = $stmt->fetch();

        if (!$pkg) {
            header('Location: /admin/subscription?error=Package+not+found+or+inactive'); exit;
        }

        $db->beginTransaction();
        try {
            // Check if there is already a pending subscription request
            $checkPending = $db->prepare('SELECT id FROM subscriptions WHERE restaurant_id = ? AND status = "pending" LIMIT 1');
            $checkPending->execute([$rest_id]);
            if ($checkPending->fetch()) {
                throw new \Exception('You already have a subscription request pending approval.');
            }

            // Get current active ends_at to resolve standard end_date
            $remainingDays = 0;
            $stmt_ends = $db->prepare('SELECT subscription_ends_at FROM restaurants WHERE id = ?');
            $stmt_ends->execute([$rest_id]);
            $ends_at = $stmt_ends->fetchColumn();

            if ($ends_at) {
                $expiry = strtotime($ends_at);
                $now = time();
                if ($expiry > $now) {
                    $todayDate = date('Y-m-d');
                    $endDateStr = date('Y-m-d', $expiry);
                    if ($endDateStr >= $todayDate) {
                        $remainingDays = (int)((strtotime($endDateStr) - strtotime($todayDate)) / 86400);
                    }
                }
            }

            // Features check if lifetime
            $features = json_decode($pkg['features'] ?? '{}', true) ?: [];
            $isLifetime = !empty($features['is_lifetime']);

            $total_duration = $isLifetime ? 36500 : ($pkg['duration_days'] + $remainingDays); // ~100 years for lifetime
            $new_end = $isLifetime ? '2099-12-31' : date('Y-m-d', strtotime('+' . $total_duration . ' days'));

            // Insert new subscription record with status pending, payment pending
            $details = [
                'transaction_ref' => $trans_ref,
                'submitted_at' => date('Y-m-d H:i:s'),
                'account_name' => $_POST['account_name'] ?? '',
                'sender_number' => $_POST['sender_number'] ?? ''
            ];

            $coupon_code = !empty($_POST['coupon_code']) ? strtoupper(trim($_POST['coupon_code'])) : null;
            $final_amount = $pkg['price'];
            if ($coupon_code) {
                $cStmt = $db->prepare('SELECT * FROM coupons WHERE code = ? AND status = "active" LIMIT 1');
                $cStmt->execute([$coupon_code]);
                $coupon = $cStmt->fetch();
                if ($coupon && strtotime($coupon['expiry_date']) >= strtotime(date('Y-m-d')) && ($coupon['usage_limit'] === null || $coupon['used_count'] < $coupon['usage_limit'])) {
                    $discount = 0;
                    if ($coupon['type'] === 'percentage') {
                        $discount = floatval($pkg['price']) * (floatval($coupon['value']) / 100);
                    } else {
                        $discount = floatval($coupon['value']);
                    }
                    $discount = min($discount, floatval($pkg['price']));
                    $final_amount = max(0, floatval($pkg['price']) - $discount);
                } else {
                    $coupon_code = null;
                }
            }

            $db->prepare('
                INSERT INTO subscriptions (restaurant_id, package_id, start_date, end_date, amount, payment_status, payment_method, payment_details, coupon_code, status)
                VALUES (?, ?, CURDATE(), ?, ?, "pending", ?, ?, ?, "pending")
            ')->execute([$rest_id, $pkg_id, $new_end, $final_amount, $payment_method, json_encode($details), $coupon_code]);

            $db->commit();
            
            // Clear checkout session
            unset($_SESSION['checkout_package_id']);
            
            header('Location: /admin/subscription?msg=Payment+submitted+successfully.+Pending+Super+Admin+approval.'); exit;
        } catch (\Exception $e) {
            $db->rollBack();
            header('Location: /admin/subscription/payment?package_id=' . $pkg_id . '&error=' . urlencode($e->getMessage())); exit;
        }
    }

    public function invoice() {
        $this->requireAdmin();
        $db = getDB();
        $rest_id = $_SESSION['restaurant_id'];
        $sub_id = $_GET['id'] ?? null;

        if (!$sub_id) {
            echo 'Invoice not found'; exit;
        }

        // Fetch subscription details (must belong to this restaurant)
        $stmt = $db->prepare('
            SELECT s.*, p.name AS package_name, p.price AS package_price, p.duration_days, p.features AS package_features
            FROM subscriptions s
            JOIN packages p ON p.id = s.package_id
            WHERE s.id = ? AND s.restaurant_id = ?
        ');
        $stmt->execute([$sub_id, $rest_id]);
        $sub = $stmt->fetch();

        if (!$sub) {
            echo 'Invoice not found'; exit;
        }

        // Fetch restaurant details
        $rStmt = $db->prepare('SELECT * FROM restaurants WHERE id = ?');
        $rStmt->execute([$rest_id]);
        $restaurant = $rStmt->fetch();

        // Render printable/downloadable invoice sheet
        require 'app/Views/admin/subscription/invoice.php';
        exit;
    }

    public function allInvoices() {
        $this->requireAdmin();
        $db = getDB();
        $rest_id = $_SESSION['restaurant_id'];
        $pageTitle = 'All Invoices';

        $history = $db->prepare('
            SELECT s.*, p.name AS package_name
            FROM subscriptions s
            JOIN packages p ON p.id = s.package_id
            WHERE s.restaurant_id = ?
            ORDER BY s.id DESC
        ');
        $history->execute([$rest_id]);
        $invoices = $history->fetchAll();

        ob_start();
        require 'app/Views/admin/subscription/all_invoices.php';
        $content = ob_get_clean();
        require 'app/Views/layouts/admin.php';
    }

    public function validateCoupon() {
        header('Content-Type: application/json');
        $this->requireAdmin();
        $db = getDB();

        $code = strtoupper(trim($_POST['code'] ?? ''));
        $pkg_id = intval($_POST['package_id'] ?? 0);

        if (!$code) {
            echo json_encode(['success' => false, 'message' => 'Please enter a coupon code.']);
            exit;
        }

        // Fetch package details to check price
        $pkgStmt = $db->prepare('SELECT price FROM packages WHERE id = ? AND status = "active"');
        $pkgStmt->execute([$pkg_id]);
        $pkgPrice = $pkgStmt->fetchColumn();

        if ($pkgPrice === false) {
            echo json_encode(['success' => false, 'message' => 'Invalid package selected.']);
            exit;
        }

        $stmt = $db->prepare('SELECT * FROM coupons WHERE code = ? AND status = "active" LIMIT 1');
        $stmt->execute([$code]);
        $coupon = $stmt->fetch();

        if (!$coupon) {
            echo json_encode(['success' => false, 'message' => 'Coupon code is invalid.']);
            exit;
        }

        // Check expiry
        if (strtotime($coupon['expiry_date']) < strtotime(date('Y-m-d'))) {
            echo json_encode(['success' => false, 'message' => 'Coupon code has expired.']);
            exit;
        }

        // Check usage limit
        if ($coupon['usage_limit'] !== null && $coupon['used_count'] >= $coupon['usage_limit']) {
            echo json_encode(['success' => false, 'message' => 'Coupon usage limit reached.']);
            exit;
        }

        // Calculate discount
        $discount = 0;
        if ($coupon['type'] === 'percentage') {
            $discount = floatval($pkgPrice) * (floatval($coupon['value']) / 100);
        } else {
            $discount = floatval($coupon['value']);
        }

        // Ensure discount is not greater than the price
        $discount = min($discount, floatval($pkgPrice));
        $newPrice = max(0, floatval($pkgPrice) - $discount);

        echo json_encode([
            'success' => true,
            'code' => $coupon['code'],
            'type' => $coupon['type'],
            'value' => floatval($coupon['value']),
            'discount' => $discount,
            'new_price' => $newPrice,
            'message' => 'Coupon applied successfully!'
        ]);
        exit;
    }
}
