<?php

namespace App\Services\Growth;

use Illuminate\Support\Facades\DB;
use Illuminate\Support\Carbon;

class QuotaService
{
    public function checkAndConsume(int $userId, string $key, string $period): bool
    {
        [$start, $end] = $this->getPeriodBounds($period);
        return DB::transaction(function () use ($userId, $key, $period, $start, $end) {
            $ents = app(EntitlementResolver::class)->getUserEntitlements($userId);
            $limitRaw = $ents[$key] ?? 0;
            if ($limitRaw === INF) {
                // Unlimited: allow without incrementing storage
                return true;
            }
            $limit = (int)$limitRaw;
            if ($limit <= 0) return false;

            $row = DB::table('user_quotas')
                ->where('user_id', $userId)
                ->where('key', $key)
                ->where('period', $period)
                ->where('period_start', $start)
                ->where('period_end', $end)
                ->lockForUpdate()
                ->first();

            $used = $row?->used ?? 0;
            if ($used >= $limit) return false;

            if ($row) {
                DB::table('user_quotas')->where('id', $row->id)->update(['used' => $used + 1, 'updated_at' => now()]);
            } else {
                DB::table('user_quotas')->insert([
                    'user_id' => $userId,
                    'key' => $key,
                    'period' => $period,
                    'used' => 1,
                    'period_start' => $start,
                    'period_end' => $end,
                    'created_at' => now(),
                    'updated_at' => now(),
                ]);
            }
            return true;
        });
    }

    public function getRemaining(int $userId, string $key, string $period): int
    {
        [$start, $end] = $this->getPeriodBounds($period);
        $ents = app(EntitlementResolver::class)->getUserEntitlements($userId);
        $limitRaw = $ents[$key] ?? 0;
        if ($limitRaw === INF) return PHP_INT_MAX;
        $limit = (int)$limitRaw;
        $used = (int) DB::table('user_quotas')
            ->where('user_id', $userId)
            ->where('key', $key)
            ->where('period', $period)
            ->where('period_start', $start)
            ->where('period_end', $end)
            ->value('used');
        return max(0, $limit - $used);
    }

    private function getPeriodBounds(string $period): array
    {
        $now = now();
        return match ($period) {
            'day' => [$now->copy()->startOfDay(), $now->copy()->endOfDay()],
            'month' => [$now->copy()->startOfMonth(), $now->copy()->endOfMonth()],
            default => [$now->copy()->startOfDay(), $now->copy()->endOfDay()],
        };
    }
}
