<?php

declare(strict_types=1);

require_once __DIR__ . '/app/database.php';
require_once __DIR__ . '/app/billing.php';
require_once __DIR__ . '/app/audit.php';

// Kein app_require_csrf()/saas_require_login(): Stripe ruft diesen
// Endpunkt unauthentifiziert von aussen auf. Die Echtheit wird
// ausschliesslich ueber die Signaturpruefung sichergestellt.

if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    http_response_code(405);
    exit('Nur POST erlaubt.');
}

$payload = file_get_contents('php://input') ?: '';
$signatureHeader = $_SERVER['HTTP_STRIPE_SIGNATURE'] ?? '';

if ($signatureHeader === '' || !stripe_verify_webhook_signature($payload, $signatureHeader, stripe_webhook_secret())) {
    http_response_code(400);
    exit('Ungültige Signatur.');
}

$event = stripe_parse_event($payload);
if ($event === null) {
    http_response_code(400);
    exit('Ungültiges Ereignis.');
}

$pdo = app_db_pdo();
$object = $event['data'];

switch ($event['type']) {
    case 'checkout.session.completed':
        $tenantId = isset($object['metadata']['tenant_id']) ? (int)$object['metadata']['tenant_id'] : null;
        $planCode = (string)($object['metadata']['plan_code'] ?? '');
        $knownPlans = billing_plans();
        if ($tenantId !== null && isset($object['customer'], $object['subscription']) && isset($knownPlans[$planCode])) {
            billing_update($pdo, $tenantId, [
                'plan_code' => $planCode,
                'subscription_status' => 'active',
                'stripe_customer_id' => (string)$object['customer'],
                'stripe_subscription_id' => (string)$object['subscription'],
            ]);
            app_audit_log($pdo, $tenantId, null, 'billing.subscription_started', 'tenant', $tenantId, ['plan_code' => $planCode]);
        }
        break;

    case 'customer.subscription.updated':
        $tenantId = isset($object['metadata']['tenant_id']) ? (int)$object['metadata']['tenant_id'] : null;
        $tenantId ??= billing_find_tenant_id_by_stripe_subscription($pdo, (string)($object['id'] ?? ''));
        if ($tenantId !== null) {
            $status = (string)($object['status'] ?? 'active');
            $periodEnd = isset($object['current_period_end'])
                ? date('Y-m-d H:i:s', (int)$object['current_period_end'])
                : null;
            billing_update($pdo, $tenantId, [
                'subscription_status' => $status,
                'current_period_end' => $periodEnd,
            ]);
            app_audit_log($pdo, $tenantId, null, 'billing.subscription_updated', 'tenant', $tenantId, ['status' => $status]);
        }
        break;

    case 'customer.subscription.deleted':
        $tenantId = isset($object['metadata']['tenant_id']) ? (int)$object['metadata']['tenant_id'] : null;
        $tenantId ??= billing_find_tenant_id_by_stripe_subscription($pdo, (string)($object['id'] ?? ''));
        if ($tenantId !== null) {
            billing_update($pdo, $tenantId, [
                'plan_code' => 'free',
                'subscription_status' => 'canceled',
            ]);
            app_audit_log($pdo, $tenantId, null, 'billing.subscription_canceled', 'tenant', $tenantId);
        }
        break;

    case 'invoice.payment_failed':
        $tenantId = billing_find_tenant_id_by_stripe_customer($pdo, (string)($object['customer'] ?? ''));
        if ($tenantId !== null) {
            billing_update($pdo, $tenantId, ['subscription_status' => 'past_due']);
            app_audit_log($pdo, $tenantId, null, 'billing.payment_failed', 'tenant', $tenantId);
        }
        break;

    case 'invoice.paid':
        $tenantId = billing_find_tenant_id_by_stripe_customer($pdo, (string)($object['customer'] ?? ''));
        if ($tenantId !== null) {
            app_audit_log($pdo, $tenantId, null, 'billing.invoice_paid', 'tenant', $tenantId, [
                'amount_paid_cents' => $object['amount_paid'] ?? null,
            ]);
            // Dolibarr-Rechnungssynchronisation folgt in Phase 3.
        }
        break;

    default:
        // Unbehandelte Ereignistypen werden bewusst ignoriert, aber mit 200
        // bestaetigt, damit Stripe sie nicht wiederholt zustellt.
        break;
}

http_response_code(200);
echo 'ok';
