<?php
/**
 * Quota Enforcement Middleware
 * 
 * Checks tenant subscription limits before allowing resource creation.
 * Automatically resets monthly counters when the billing period rolls over.
 */

declare(strict_types=1);

namespace App\Middleware;

use App\Core\Database;

final class QuotaMiddleware
{
    /**
     * Check if the tenant can upload more invoices this month.
     * Automatically resets the counter if the billing period has ended.
     * 
     * @return array The current subscription data (for UI display)
     */
    public static function checkInvoiceQuota(string $tenantId): array
    {
        $db = Database::getInstance();

        // Fetch subscription with plan info
        $stmt = $db->prepare("
            SELECT s.*, sp.name_ar as plan_name, sp.ai_features, sp.jofotara_enabled
            FROM subscriptions s
            LEFT JOIN subscription_plans sp ON s.plan_id = sp.id
            WHERE s.tenant_id = ?
        ");
        $stmt->execute([$tenantId]);
        $sub = $stmt->fetch();

        if (!$sub) {
            json_error('لا يوجد اشتراك فعّال لهذا المكتب. يرجى التواصل مع الإدارة.', 403);
        }

        // Check subscription status
        if ($sub['status'] === 'cancelled') {
            json_error('تم إلغاء اشتراكك. يرجى تجديد الاشتراك للمتابعة.', 403);
        }

        if ($sub['status'] === 'past_due') {
            json_error('اشتراكك متأخر الدفع. يرجى تسوية المبلغ المستحق للمتابعة.', 403);
        }

        // Auto-reset monthly counter if billing period has ended
        if (!empty($sub['current_period_end']) && strtotime($sub['current_period_end']) < time()) {
            $newStart = date('Y-m-d H:i:s');
            $newEnd   = date('Y-m-d H:i:s', strtotime('+30 days'));

            $resetStmt = $db->prepare("
                UPDATE subscriptions 
                SET invoices_used_this_month = 0,
                    current_period_start = ?,
                    current_period_end = ?,
                    updated_at = NOW()
                WHERE tenant_id = ?
            ");
            $resetStmt->execute([$newStart, $newEnd, $tenantId]);

            $sub['invoices_used_this_month'] = 0;
            $sub['current_period_start'] = $newStart;
            $sub['current_period_end'] = $newEnd;

            error_log("QuotaMiddleware: Auto-reset monthly counter for tenant {$tenantId}");
        }

        // Check invoice quota
        $used  = (int)$sub['invoices_used_this_month'];
        $limit = (int)$sub['max_invoices_per_month'];

        if ($used >= $limit) {
            json_error('لقد وصلت للحد الأقصى من الفواتير المسموحة هذا الشهر (' . $limit . ' فاتورة). يرجى ترقية باقتك.', 429, [
                'quota_type'  => 'invoices',
                'used'        => $used,
                'limit'       => $limit,
                'plan'        => $sub['plan_id'] ?? 'free',
                'plan_name'   => $sub['plan_name'] ?? 'مجانية',
                'period_end'  => $sub['current_period_end'],
            ]);
        }

        return $sub;
    }

    /**
     * Increment the monthly invoice counter after a successful upload.
     */
    public static function incrementInvoiceUsage(string $tenantId): void
    {
        $db = Database::getInstance();
        $stmt = $db->prepare("
            UPDATE subscriptions 
            SET invoices_used_this_month = invoices_used_this_month + 1,
                updated_at = NOW()
            WHERE tenant_id = ?
        ");
        $stmt->execute([$tenantId]);
    }

    /**
     * Check if the tenant can add more companies.
     */
    public static function checkCompanyQuota(string $tenantId): array
    {
        $db = Database::getInstance();

        // Get subscription
        $stmt = $db->prepare("
            SELECT s.*, sp.name_ar as plan_name
            FROM subscriptions s
            LEFT JOIN subscription_plans sp ON s.plan_id = sp.id
            WHERE s.tenant_id = ?
        ");
        $stmt->execute([$tenantId]);
        $sub = $stmt->fetch();

        if (!$sub) {
            json_error('لا يوجد اشتراك فعّال لهذا المكتب.', 403);
        }

        // Count current active companies
        $countStmt = $db->prepare("
            SELECT COUNT(*) FROM companies 
            WHERE tenant_id = ? AND (deleted_at IS NULL)
        ");
        $countStmt->execute([$tenantId]);
        $currentCount = (int)$countStmt->fetchColumn();

        $limit = (int)$sub['max_companies'];

        if ($currentCount >= $limit) {
            json_error('لقد وصلت للحد الأقصى من الشركات المسموحة (' . $limit . ' شركة). يرجى ترقية باقتك.', 429, [
                'quota_type' => 'companies',
                'used'       => $currentCount,
                'limit'      => $limit,
                'plan'       => $sub['plan_id'] ?? 'free',
                'plan_name'  => $sub['plan_name'] ?? 'مجانية',
            ]);
        }

        return $sub;
    }

    /**
     * Check if the tenant can add more users.
     */
    public static function checkUserQuota(string $tenantId): array
    {
        $db = Database::getInstance();

        // Get subscription
        $stmt = $db->prepare("
            SELECT s.*, sp.name_ar as plan_name
            FROM subscriptions s
            LEFT JOIN subscription_plans sp ON s.plan_id = sp.id
            WHERE s.tenant_id = ?
        ");
        $stmt->execute([$tenantId]);
        $sub = $stmt->fetch();

        if (!$sub) {
            json_error('لا يوجد اشتراك فعّال لهذا المكتب.', 403);
        }

        // Count current active users in this tenant
        $countStmt = $db->prepare("
            SELECT COUNT(*) FROM users 
            WHERE tenant_id = ? AND (deleted_at IS NULL) AND is_active = 1
        ");
        $countStmt->execute([$tenantId]);
        $currentCount = (int)$countStmt->fetchColumn();

        $maxUsers = (int)($sub['max_users'] ?? 999);

        if ($currentCount >= $maxUsers) {
            json_error('لقد وصلت للحد الأقصى من المستخدمين المسموحين (' . $maxUsers . ' مستخدم). يرجى ترقية باقتك.', 429, [
                'quota_type' => 'users',
                'used'       => $currentCount,
                'limit'      => $maxUsers,
                'plan'       => $sub['plan_id'] ?? 'free',
                'plan_name'  => $sub['plan_name'] ?? 'مجانية',
            ]);
        }

        return $sub;
    }

    /**
     * Get usage summary for a tenant (for dashboard display).
     */
    public static function getUsageSummary(string $tenantId): array
    {
        $db = Database::getInstance();

        // Get subscription
        $stmt = $db->prepare("
            SELECT s.*, sp.name_ar as plan_name, sp.name_en as plan_name_en,
                   sp.ai_features, sp.jofotara_enabled, sp.price_jod as plan_price
            FROM subscriptions s
            LEFT JOIN subscription_plans sp ON s.plan_id = sp.id
            WHERE s.tenant_id = ?
        ");
        $stmt->execute([$tenantId]);
        $sub = $stmt->fetch();

        if (!$sub) {
            return [
                'has_subscription' => false,
                'plan'             => 'none',
            ];
        }

        // Count companies
        $compStmt = $db->prepare("SELECT COUNT(*) FROM companies WHERE tenant_id = ? AND deleted_at IS NULL");
        $compStmt->execute([$tenantId]);
        $companiesUsed = (int)$compStmt->fetchColumn();

        // Count users
        $userStmt = $db->prepare("SELECT COUNT(*) FROM users WHERE tenant_id = ? AND (deleted_at IS NULL) AND is_active = 1");
        $userStmt->execute([$tenantId]);
        $usersUsed = (int)$userStmt->fetchColumn();

        $invoicesUsed  = (int)$sub['invoices_used_this_month'];
        $invoicesLimit = (int)$sub['max_invoices_per_month'];
        $companiesLimit = (int)$sub['max_companies'];
        $usersLimit     = (int)($sub['max_users'] ?? 999);

        return [
            'has_subscription'  => true,
            'plan_id'           => $sub['plan_id'] ?? 'free',
            'plan_name'         => $sub['plan_name'] ?? 'مجانية',
            'plan_name_en'      => $sub['plan_name_en'] ?? 'Free',
            'plan_price'        => (float)($sub['plan_price'] ?? 0),
            'status'            => $sub['status'],
            'ai_features'       => (bool)($sub['ai_features'] ?? false),
            'jofotara_enabled'  => (bool)($sub['jofotara_enabled'] ?? false),

            'invoices' => [
                'used'    => $invoicesUsed,
                'limit'   => $invoicesLimit,
                'percent' => $invoicesLimit > 0 ? round(($invoicesUsed / $invoicesLimit) * 100) : 0,
                'warning' => $invoicesLimit > 0 && ($invoicesUsed / $invoicesLimit) >= 0.9,
            ],
            'companies' => [
                'used'    => $companiesUsed,
                'limit'   => $companiesLimit,
                'percent' => $companiesLimit > 0 ? round(($companiesUsed / $companiesLimit) * 100) : 0,
                'warning' => $companiesLimit > 0 && ($companiesUsed / $companiesLimit) >= 0.9,
            ],
            'users' => [
                'used'    => $usersUsed,
                'limit'   => $usersLimit,
                'percent' => $usersLimit > 0 ? round(($usersUsed / $usersLimit) * 100) : 0,
                'warning' => $usersLimit > 0 && ($usersUsed / $usersLimit) >= 0.9,
            ],

            'period_start' => $sub['current_period_start'],
            'period_end'   => $sub['current_period_end'],
            'trial_ends_at' => $sub['trial_ends_at'],
            'days_remaining' => !empty($sub['current_period_end'])
                ? max(0, (int)ceil((strtotime($sub['current_period_end']) - time()) / 86400))
                : null,
        ];
    }
}
