<?php
/**
 * Plan Limits Manager
 * 
 * Handles checking and enforcing subscription plan limits for workspaces.
 * Limits are stored in the subscription_plans.limits JSON column.
 * 
 * Default limits structure:
 * {
 *   "users": 3,           // Max team members (including owner)
 *   "clients": 25,        // Max clients
 *   "templates": 10,      // Max templates
 *   "storage_mb": 1000,   // Max storage in MB
 *   "proposals_per_month": 50  // Max proposals per month
 * }
 * 
 * A value of -1 means unlimited.
 */

declare(strict_types=1);

require_once __DIR__ . '/../db.php';

class PlanLimits
{
    private static array $cache = [];

    /**
     * Get limits for a workspace based on their subscription plan
     */
    public static function getLimits(int $companyId): array
    {
        if (isset(self::$cache[$companyId])) {
            return self::$cache[$companyId];
        }

        $pdo = getPDO();
        
        // Get company's plan
        $stmt = $pdo->prepare("
            SELECT sp.limits 
            FROM companies c
            LEFT JOIN subscription_plans sp ON c.plan_id = sp.id
            WHERE c.id = ?
        ");
        $stmt->execute([$companyId]);
        $result = $stmt->fetch();

        $defaultLimits = [
            'users' => 3,
            'clients' => 25,
            'templates' => 10,
            'storage_mb' => 1000,
            'proposals_per_month' => 50,
            'contracts_per_month' => 50,
            'invoices_per_month' => 50,
        ];

        if ($result && $result['limits']) {
            $limits = json_decode($result['limits'], true) ?? [];
            $limits = array_merge($defaultLimits, $limits);
        } else {
            $limits = $defaultLimits;
        }

        self::$cache[$companyId] = $limits;
        return $limits;
    }

    /**
     * Get current usage for a workspace
     */
    public static function getUsage(int $companyId): array
    {
        $pdo = getPDO();

        // Count members from user_company_access
        $stmt = $pdo->prepare("SELECT COUNT(*) as count FROM user_company_access WHERE company_id = ?");
        $stmt->execute([$companyId]);
        $members = (int)($stmt->fetch()['count'] ?? 0);

        // Count clients
        $stmt = $pdo->prepare("SELECT COUNT(*) as count FROM clients WHERE company_id = ?");
        $stmt->execute([$companyId]);
        $clients = (int)($stmt->fetch()['count'] ?? 0);

        // Count templates
        $stmt = $pdo->prepare("SELECT COUNT(*) as count FROM templates WHERE company_id = ?");
        $stmt->execute([$companyId]);
        $templates = (int)($stmt->fetch()['count'] ?? 0);

        // Count proposals this month
        $stmt = $pdo->prepare("
            SELECT COUNT(*) as count FROM proposals 
            WHERE company_id = ? 
            AND created_at >= DATE_FORMAT(NOW(), '%Y-%m-01')
        ");
        $stmt->execute([$companyId]);
        $proposalsThisMonth = (int)($stmt->fetch()['count'] ?? 0);

        // Count contracts this month
        $stmt = $pdo->prepare("
            SELECT COUNT(*) as count FROM contracts 
            WHERE company_id = ? 
            AND created_at >= DATE_FORMAT(NOW(), '%Y-%m-01')
        ");
        $stmt->execute([$companyId]);
        $contractsThisMonth = (int)($stmt->fetch()['count'] ?? 0);

        // Count invoices this month
        $stmt = $pdo->prepare("
            SELECT COUNT(*) as count FROM invoices 
            WHERE company_id = ? 
            AND created_at >= DATE_FORMAT(NOW(), '%Y-%m-01')
        ");
        $stmt->execute([$companyId]);
        $invoicesThisMonth = (int)($stmt->fetch()['count'] ?? 0);

        return [
            'users' => $members,
            'clients' => $clients,
            'templates' => $templates,
            'proposals_per_month' => $proposalsThisMonth,
            'contracts_per_month' => $contractsThisMonth,
            'invoices_per_month' => $invoicesThisMonth,
        ];
    }

    /**
     * Check if a specific limit has been reached
     * Returns true if limit is NOT reached (can proceed)
     * Returns false if limit IS reached (cannot proceed)
     */
    public static function canAdd(int $companyId, string $limitKey): bool
    {
        $limits = self::getLimits($companyId);
        $usage = self::getUsage($companyId);

        $limit = $limits[$limitKey] ?? -1;
        $current = $usage[$limitKey] ?? 0;

        // -1 means unlimited
        if ($limit === -1) {
            return true;
        }

        return $current < $limit;
    }

    /**
     * Get remaining count for a limit
     * Returns -1 if unlimited
     */
    public static function getRemaining(int $companyId, string $limitKey): int
    {
        $limits = self::getLimits($companyId);
        $usage = self::getUsage($companyId);

        $limit = $limits[$limitKey] ?? -1;
        $current = $usage[$limitKey] ?? 0;

        if ($limit === -1) {
            return -1; // Unlimited
        }

        return max(0, $limit - $current);
    }

    /**
     * Get a formatted limit display string
     */
    public static function formatLimit(int $limit): string
    {
        return $limit === -1 ? 'Unlimited' : (string)$limit;
    }

    /**
     * Get usage percentage for a limit
     */
    public static function getUsagePercentage(int $companyId, string $limitKey): float
    {
        $limits = self::getLimits($companyId);
        $usage = self::getUsage($companyId);

        $limit = $limits[$limitKey] ?? -1;
        $current = $usage[$limitKey] ?? 0;

        if ($limit === -1 || $limit === 0) {
            return 0;
        }

        return min(100, ($current / $limit) * 100);
    }

    /**
     * Get all limits and usage for display
     */
    public static function getSummary(int $companyId): array
    {
        $limits = self::getLimits($companyId);
        $usage = self::getUsage($companyId);

        $summary = [];
        foreach ($limits as $key => $limit) {
            $current = $usage[$key] ?? 0;
            $summary[$key] = [
                'limit' => $limit,
                'current' => $current,
                'remaining' => $limit === -1 ? -1 : max(0, $limit - $current),
                'percentage' => $limit === -1 || $limit === 0 ? 0 : min(100, ($current / $limit) * 100),
                'is_unlimited' => $limit === -1,
                'is_at_limit' => $limit !== -1 && $current >= $limit,
            ];
        }

        return $summary;
    }

    /**
     * Clear cache for a company
     */
    public static function clearCache(?int $companyId = null): void
    {
        if ($companyId) {
            unset(self::$cache[$companyId]);
        } else {
            self::$cache = [];
        }
    }
}
