<?php

namespace App\Domain\Subscription;

use App\Models\Dentist;
use App\Models\PatientFile;
use App\Models\Tenant;
use App\Models\UsageCounter;
use App\Models\User;
use Illuminate\Support\Facades\Storage;

/**
 * Soft usage limits. We count usage and surface warnings at 80% / 100%,
 * but never hard-block clinical work — clinics keep operating; the warning
 * nudges an upgrade conversation.
 */
class UsageService
{
    public const WARN_AT = 0.8;

    public function increment(Tenant $tenant, string $metric = 'wa_messages', int $by = 1): void
    {
        $counter = UsageCounter::firstOrCreate(
            ['tenant_id' => $tenant->id, 'metric' => $metric, 'period' => now()->format('Y-m')],
            ['used' => 0],
        );
        $counter->increment('used', $by);
    }

    public function used(Tenant $tenant, string $metric = 'wa_messages'): int
    {
        return (int) UsageCounter::where('tenant_id', $tenant->id)
            ->where('metric', $metric)
            ->where('period', now()->format('Y-m'))
            ->value('used');
    }

    public function limit(Tenant $tenant, string $metric = 'wa_messages'): ?int
    {
        $map = ['wa_messages' => 'wa_messages_month'];
        $key = $map[$metric] ?? null;

        return $key ? $tenant->subscription?->plan?->limit($key) : null;
    }

    /** @return array{used:int, limit:?int, ratio:float, level:string} */
    public function status(Tenant $tenant, string $metric = 'wa_messages'): array
    {
        $used = $this->used($tenant, $metric);
        $limit = $this->limit($tenant, $metric);
        $ratio = $limit ? $used / $limit : 0.0;

        $level = match (true) {
            $limit === null => 'none',
            $ratio >= 1.0 => 'over',
            $ratio >= self::WARN_AT => 'warn',
            default => 'ok',
        };

        return compact('used', 'limit', 'ratio', 'level');
    }

    /** Staff seats used vs the plan's limit (owner + dentists + receptionists). */
    public function staff(Tenant $tenant): array
    {
        $used = User::withoutGlobalScope('tenant')->where('tenant_id', $tenant->id)->count();
        $limit = $tenant->subscription?->plan?->limit('staff');

        return $this->shape($used, $limit);
    }

    /** Dentist seats used vs limit. */
    public function dentists(Tenant $tenant): array
    {
        $used = Dentist::withoutGlobalScope('tenant')->where('tenant_id', $tenant->id)->count();
        $limit = $tenant->subscription?->plan?->limit('dentists');

        return $this->shape($used, $limit);
    }

    /** Storage used (MB) vs the plan's GB limit, summed from patient files. */
    public function storage(Tenant $tenant): array
    {
        $bytes = (int) PatientFile::withoutGlobalScope('tenant')
            ->where('tenant_id', $tenant->id)->sum('size');
        $usedMb = (int) round($bytes / 1048576);
        $limitGb = $tenant->subscription?->plan?->limit('storage_gb');
        $limitMb = $limitGb !== null ? $limitGb * 1024 : null;

        return $this->shape($usedMb, $limitMb) + ['used_mb' => $usedMb, 'limit_gb' => $limitGb];
    }

    /** @return array{used:int, limit:?int, ratio:float, level:string} */
    protected function shape(int $used, ?int $limit): array
    {
        $ratio = $limit ? $used / $limit : 0.0;
        $level = match (true) {
            $limit === null => 'none',
            $ratio >= 1.0 => 'over',
            $ratio >= self::WARN_AT => 'warn',
            default => 'ok',
        };

        return compact('used', 'limit', 'ratio', 'level');
    }
}
