<?php
// ─────────────────────────────────────────────────────────────
//  lib/StripeBooking.php — Stripe checkout + webhook handler
// ─────────────────────────────────────────────────────────────
if (!defined('DB_HOST')) require_once dirname(__DIR__) . '/lib.php';

class StripeBooking {
    private static function stripeConfig(): array {
        $mode = defined('STRIPE_MODE') ? strtolower((string)STRIPE_MODE) : 'test';
        if ($mode !== 'live') $mode = 'test';

        $legacySecret = defined('STRIPE_SECRET_KEY') ? (string)STRIPE_SECRET_KEY : '';
        $legacyPub    = defined('STRIPE_PUBLISHABLE_KEY') ? (string)STRIPE_PUBLISHABLE_KEY : '';
        $legacyWh     = defined('STRIPE_WEBHOOK_SECRET') ? (string)STRIPE_WEBHOOK_SECRET : '';

        $testSecret = defined('STRIPE_TEST_SECRET_KEY') ? (string)STRIPE_TEST_SECRET_KEY : '';
        $testPub    = defined('STRIPE_TEST_PUBLISHABLE_KEY') ? (string)STRIPE_TEST_PUBLISHABLE_KEY : '';
        $testWh     = defined('STRIPE_TEST_WEBHOOK_SECRET') ? (string)STRIPE_TEST_WEBHOOK_SECRET : '';

        $liveSecret = defined('STRIPE_LIVE_SECRET_KEY') ? (string)STRIPE_LIVE_SECRET_KEY : '';
        $livePub    = defined('STRIPE_LIVE_PUBLISHABLE_KEY') ? (string)STRIPE_LIVE_PUBLISHABLE_KEY : '';
        $liveWh     = defined('STRIPE_LIVE_WEBHOOK_SECRET') ? (string)STRIPE_LIVE_WEBHOOK_SECRET : '';

        // Backward-compatible fallbacks:
        // - If only legacy constants exist, infer test/live from key prefixes.
        // - If mode is test but legacy is test key, use it; same for live.
        if ($testSecret === '' && $legacySecret !== '' && str_starts_with($legacySecret, 'sk_test_')) $testSecret = $legacySecret;
        if ($liveSecret === '' && $legacySecret !== '' && str_starts_with($legacySecret, 'sk_live_')) $liveSecret = $legacySecret;
        if ($testPub === '' && $legacyPub !== '' && str_starts_with($legacyPub, 'pk_test_')) $testPub = $legacyPub;
        if ($livePub === '' && $legacyPub !== '' && str_starts_with($legacyPub, 'pk_live_')) $livePub = $legacyPub;
        if ($testWh === '' && $legacyWh !== '' && $mode === 'test') $testWh = $legacyWh;
        if ($liveWh === '' && $legacyWh !== '' && $mode === 'live') $liveWh = $legacyWh;

        // If mode-picked keys are empty but the legacy keys exist, use them as last resort.
        // This prevents "current mode" failures when the project is configured using only legacy constants.
        if ($mode === 'test' && $testSecret === '' && $legacySecret !== '' && str_starts_with($legacySecret, 'sk_')) $testSecret = $legacySecret;
        if ($mode === 'live' && $liveSecret === '' && $legacySecret !== '' && str_starts_with($legacySecret, 'sk_')) $liveSecret = $legacySecret;
        if ($mode === 'test' && $testPub === '' && $legacyPub !== '' && str_starts_with($legacyPub, 'pk_')) $testPub = $legacyPub;
        if ($mode === 'live' && $livePub === '' && $legacyPub !== '' && str_starts_with($legacyPub, 'pk_')) $livePub = $legacyPub;

        return [
            'mode' => $mode,
            'secret_key' => $mode === 'live' ? $liveSecret : $testSecret,
            'publishable_key' => $mode === 'live' ? $livePub : $testPub,
            'webhook_secret' => $mode === 'live' ? $liveWh : $testWh,
            'currency' => defined('STRIPE_CURRENCY') ? (string)STRIPE_CURRENCY : 'usd',
            'ready' => ($mode === 'live' ? $liveSecret : $testSecret) !== '',
        ];
    }

    public static function publicConfig(): array {
        $cfg = self::stripeConfig();
        return [
            'mode' => $cfg['mode'],
            'stripe_key' => $cfg['publishable_key'],
            'currency' => $cfg['currency'],
            'stripe_ready' => $cfg['ready'],
        ];
    }

    public static function createCheckout(
        int    $planId,
        string $email,
        string $name,
        string $successUrl,
        string $cancelUrl,
        float  $discountAmount = 0.0,
        array  $profile = []
    ): string {
        if (!class_exists('\\Stripe\\Stripe')) {
            throw new \Exception('Stripe SDK not installed. Run: composer require stripe/stripe-php');
        }

        $cfg = self::stripeConfig();
        if (!$cfg['secret_key']) {
            throw new \Exception('Stripe is not configured for current mode');
        }
        \Stripe\Stripe::setApiKey($cfg['secret_key']);

        // Get plan
        $plan = db()->prepare('SELECT * FROM bk_plans WHERE id=? AND is_active=1');
        $plan->execute([$planId]);
        $p = $plan->fetch();
        if (!$p) throw new \Exception('Plan not found');

        $unitAmount = (int)($p['price'] * 100);
        $productData = [
            'name' => $p['name'],
        ];
        $desc = trim((string)($p['description'] ?? ''));
        if ($desc !== '') {
            $productData['description'] = $desc;
        }
        $lineItems  = [[
            'price_data' => [
                'currency'     => $cfg['currency'],
                'unit_amount'  => $unitAmount,
                'product_data' => $productData,
            ],
            'quantity' => 1,
        ]];

        // Apply flat discount as a negative line item
        if ($discountAmount > 0.0) {
            $discountCents = (int)($discountAmount * 100);
            $lineItems[] = [
                'price_data' => [
                    'currency'     => $cfg['currency'],
                    'unit_amount'  => -min($discountCents, $unitAmount - 50),
                    'product_data' => ['name' => 'Promo Discount'],
                ],
                'quantity' => 1,
            ];
        }

        $session = \Stripe\Checkout\Session::create([
            'customer_email'         => $email,
            'payment_method_types'   => ['card'],
            'line_items'             => $lineItems,
            'mode'                   => 'payment',
            'success_url'            => $successUrl . (str_contains($successUrl, '?') ? '&' : '?') . 'session_id={CHECKOUT_SESSION_ID}',
            'cancel_url'             => $cancelUrl,
            'metadata'               => [
                'plan_id'         => $planId,
                'customer_email'  => $email,
                'customer_name'   => $name,
                'discount_amount' => $discountAmount,
                'phone'           => (string)($profile['phone'] ?? ''),
                'dob'             => (string)($profile['dob'] ?? ''),
                'gender'          => (string)($profile['gender'] ?? ''),
                'address_line1'   => (string)($profile['address_line1'] ?? ''),
                'city'            => (string)($profile['city'] ?? ''),
                'country'         => (string)($profile['country'] ?? ''),
                'emergency_contact_name'  => (string)($profile['emergency_contact_name'] ?? ''),
                'emergency_contact_phone' => (string)($profile['emergency_contact_phone'] ?? ''),
            ],
        ]);

        return $session->url;
    }

    public static function handleWebhook(string $payload, string $sigHeader): void {
        if (!class_exists('\Stripe\Stripe')) {
            throw new \Exception('Stripe SDK not installed');
        }

        $cfg = self::stripeConfig();
        if (!$cfg['secret_key']) {
            throw new \Exception('Stripe is not configured for current mode');
        }
        $secret = $cfg['webhook_secret'];
        \Stripe\Stripe::setApiKey($cfg['secret_key']);

        $event = \Stripe\Webhook::constructEvent($payload, $sigHeader, $secret);

        if ($event->type === 'checkout.session.completed') {
            $session = $event->data->object;
            $meta    = $session->metadata;
            $planId  = (int) $meta->plan_id;
            $email   = $meta->customer_email;
            $name    = $meta->customer_name;
            $phone   = trim((string)($meta->phone ?? ''));
            $dob     = trim((string)($meta->dob ?? ''));
            $gender  = trim((string)($meta->gender ?? ''));
            $addressLine1 = trim((string)($meta->address_line1 ?? ''));
            $city    = trim((string)($meta->city ?? ''));
            $country = trim((string)($meta->country ?? ''));
            $emergencyName  = trim((string)($meta->emergency_contact_name ?? ''));
            $emergencyPhone = trim((string)($meta->emergency_contact_phone ?? ''));

            // Get or create customer
            $custStmt = db()->prepare('SELECT id FROM bk_customers WHERE email=?');
            $custStmt->execute([$email]);
            $cust = $custStmt->fetch();
            if (!$cust) {
                db()->prepare(
                    'INSERT INTO bk_customers (email, name, phone, dob, gender, address_line1, city, country, emergency_contact_name, emergency_contact_phone)
                     VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'
                )->execute([
                    $email, $name, $phone ?: null, $dob ?: null, $gender ?: null,
                    $addressLine1 ?: null, $city ?: null, $country ?: null, $emergencyName ?: null, $emergencyPhone ?: null
                ]);
                $customerId = (int) db()->lastInsertId();
            } else {
                $customerId = (int) $cust['id'];
                db()->prepare(
                    'UPDATE bk_customers SET
                        name=COALESCE(NULLIF(?,\'\'),name),
                        phone=COALESCE(NULLIF(?,\'\'),phone),
                        dob=COALESCE(NULLIF(?,\'\'),dob),
                        gender=COALESCE(NULLIF(?,\'\'),gender),
                        address_line1=COALESCE(NULLIF(?,\'\'),address_line1),
                        city=COALESCE(NULLIF(?,\'\'),city),
                        country=COALESCE(NULLIF(?,\'\'),country),
                        emergency_contact_name=COALESCE(NULLIF(?,\'\'),emergency_contact_name),
                        emergency_contact_phone=COALESCE(NULLIF(?,\'\'),emergency_contact_phone)
                     WHERE id=?'
                )->execute([
                    $name, $phone, $dob, $gender, $addressLine1, $city, $country, $emergencyName, $emergencyPhone, $customerId
                ]);
            }

            // Get plan duration
            $planStmt = db()->prepare('SELECT * FROM bk_plans WHERE id=?');
            $planStmt->execute([$planId]);
            $plan = $planStmt->fetch();
            if (!$plan) return;

            $startsAt  = date('Y-m-d H:i:s');
            $validDays = (int)($plan['validity_days'] ?? 0);
            if ($validDays <= 0) $validDays = (int)($plan['duration_days'] ?? 30);
            $expiresAt = date('Y-m-d H:i:s', strtotime('+' . $validDays . ' days'));
            $sessionLimit = $plan['session_limit'] !== null ? (int)$plan['session_limit'] : null;

            db()->prepare(
                'INSERT INTO bk_memberships
                 (customer_id, plan_id, sessions_total, sessions_remaining, starts_at, expires_at, status,
                  stripe_payment_id, stripe_session_id, activated_by)
                 VALUES (?, ?, ?, ?, ?, ?, "active", ?, ?, "stripe")'
            )->execute([
                $customerId, $planId, $sessionLimit, $sessionLimit, $startsAt, $expiresAt,
                $session->payment_intent, $session->id,
            ]);

            // Send confirmation email
            $html = "<h2>Membership Activated — {$plan['name']}</h2>
                     <p>Hi {$name},</p>
                     <p>Your <strong>{$plan['name']}</strong> membership is now active.</p>
                     <p>Expires: <strong>{$expiresAt}</strong></p>
                     <p><a href=\"" . APP_URL . "/book.php\">Book an appointment now →</a></p>";
            $text = "Membership Active — {$plan['name']}\nExpires: {$expiresAt}\nBook: " . APP_URL . "/book.php";
            try {
                send_mail($email, $name, "Membership Active — {$plan['name']}", $html, $text);
            } catch (\Throwable $e) {
                error_log('Booking email error: ' . $e->getMessage());
            }
        }
    }
}
