<?php

declare(strict_types=1);

namespace App\Service;

use App\Dto\LimitCheckResult;
use App\Dto\UsageSummary;
use Doctrine\ORM\EntityManagerInterface;

/**
 * Enforces license limits: maxUsers, maxNews, maxStorageMb.
 * Reads limits from cached license API response via TenantContext.
 */
class LicenseEnforcementService
{
    private const GRACE_PERIOD_DAYS = 7;

    public function __construct(
        private readonly EntityManagerInterface $entityManager,
        private readonly TenantContext $tenantContext,
        private readonly PlanFeatureService $planFeatureService,
    ) {}

    public function checkUserLimit(): LimitCheckResult
    {
        $maxUsers = $this->getEffectiveLimit('maxUsers');
        if ($maxUsers <= 0) return LimitCheckResult::unlimited();

        $currentUsers = $this->countUsers();
        $percent = ($currentUsers / $maxUsers) * 100;

        return new LimitCheckResult(
            allowed: $currentUsers < $maxUsers,
            current: $currentUsers,
            max: $maxUsers,
            percentUsed: round($percent, 1),
            message: $currentUsers >= $maxUsers
                ? "Kullanıcı limiti doldu ({$currentUsers}/{$maxUsers})."
                : "Kullanıcı kullanımı: {$currentUsers}/{$maxUsers}",
        );
    }

    public function checkNewsLimit(): LimitCheckResult
    {
        $maxNews = $this->getEffectiveLimit('maxNews');
        if ($maxNews <= 0) return LimitCheckResult::unlimited();

        $currentNews = $this->countNews();
        $percent = ($currentNews / $maxNews) * 100;

        return new LimitCheckResult(
            allowed: $currentNews < $maxNews,
            current: $currentNews,
            max: $maxNews,
            percentUsed: round($percent, 1),
            message: $currentNews >= $maxNews
                ? "Haber limiti doldu ({$currentNews}/{$maxNews})."
                : "Haber kullanımı: {$currentNews}/{$maxNews}",
        );
    }

    public function checkStorageLimit(): LimitCheckResult
    {
        $maxStorageMb = $this->getEffectiveLimit('maxStorageMb');
        if ($maxStorageMb <= 0) return LimitCheckResult::unlimited();

        $currentStorageMb = $this->calculateStorageMb();
        $percent = ($currentStorageMb / $maxStorageMb) * 100;

        return new LimitCheckResult(
            allowed: $currentStorageMb < $maxStorageMb,
            current: $currentStorageMb,
            max: $maxStorageMb,
            percentUsed: round($percent, 1),
            message: $currentStorageMb >= $maxStorageMb
                ? "Depolama limiti doldu ({$currentStorageMb}MB / {$maxStorageMb}MB)."
                : "Depolama kullanımı: {$currentStorageMb}MB / {$maxStorageMb}MB",
        );
    }

    public function isInGracePeriod(): bool
    {
        if (!$this->tenantContext->isExpired()) return false;

        $days = $this->tenantContext->getDaysUntilExpiry();
        if ($days === null) return false;

        return $days >= -self::GRACE_PERIOD_DAYS && $days < 0;
    }

    public function isFullyExpired(): bool
    {
        if (!$this->tenantContext->isExpired()) return false;

        $days = $this->tenantContext->getDaysUntilExpiry();
        if ($days === null) return false;

        return $days < -self::GRACE_PERIOD_DAYS;
    }

    public function getUsageSummary(): UsageSummary
    {
        $daysUntilExpiry = $this->tenantContext->getDaysUntilExpiry();
        $plan = $this->tenantContext->getPlan();

        $licenseStatus = 'active';
        if ($this->tenantContext->isDemo()) {
            $licenseStatus = 'demo';
        } elseif (!$this->tenantContext->isLicenseValid()) {
            $licenseStatus = 'none';
        } elseif ($this->isFullyExpired()) {
            $licenseStatus = 'expired';
        } elseif ($this->isInGracePeriod()) {
            $licenseStatus = 'grace_period';
        }

        return new UsageSummary(
            users: $this->checkUserLimit(),
            news: $this->checkNewsLimit(),
            storage: $this->checkStorageLimit(),
            licenseStatus: $licenseStatus,
            daysUntilExpiry: $daysUntilExpiry,
            plan: $plan,
        );
    }

    private function getEffectiveLimit(string $key): int
    {
        // Cached limits from API response
        $cachedLimits = $this->tenantContext->getCachedLimits();
        $cachedValue = $cachedLimits[$key] ?? 0;

        if ($cachedValue > 0) {
            return $cachedValue;
        }

        // Fallback to plan defaults
        $plan = $this->tenantContext->getPlan();
        $planLimits = $this->planFeatureService->getDefaultLimits($plan);

        return $planLimits[$key] ?? 0;
    }

    private function countUsers(): int
    {
        try {
            return (int) $this->entityManager->getConnection()
                ->fetchOne('SELECT COUNT(*) FROM users WHERE is_active = 1');
        } catch (\Exception) { return 0; }
    }

    private function countNews(): int
    {
        try {
            return (int) $this->entityManager->getConnection()
                ->fetchOne('SELECT COUNT(*) FROM news');
        } catch (\Exception) { return 0; }
    }

    private function calculateStorageMb(): int
    {
        try {
            $bytes = (int) $this->entityManager->getConnection()
                ->fetchOne("SELECT COALESCE(SUM(file_size), 0) FROM media");
            return (int) ceil($bytes / (1024 * 1024));
        } catch (\Exception) { return 0; }
    }
}
