<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\EventPackage;
use App\Models\TenantPackage;
use App\Support\ApiError;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;

class TenantPackageController extends Controller
{
    public function index(Request $request): JsonResponse
    {
        $tenant = $request->attributes->get('tenant');

        if (! $tenant) {
            return ApiError::response(
                'tenant_not_found',
                'Tenant Not Found',
                'The authenticated tenant context could not be resolved.',
                Response::HTTP_NOT_FOUND
            );
        }

        $packages = TenantPackage::where('tenant_id', $tenant->id)
            ->with('package')
            ->orderBy('created_at', 'desc')
            ->get();

        $usageEventPackage = $this->resolveUsageEventPackage($tenant->id);

        $packages->each(function (TenantPackage $package) use ($usageEventPackage): void {
            $eventPackage = $package->active ? $usageEventPackage : null;
            $this->hydratePackageSnapshot($package, $eventPackage);
        });

        $activePackage = $tenant->activeResellerPackage?->load('package');

        if (! ($activePackage instanceof TenantPackage)) {
            $activePackage = $packages->firstWhere('active', true);
        } else {
            $this->hydratePackageSnapshot($activePackage, $usageEventPackage);
        }

        return response()->json([
            'data' => $packages,
            'active_package' => $activePackage,
            'message' => 'Tenant packages loaded successfully.',
        ]);
    }

    private function hydratePackageSnapshot(TenantPackage $package, ?EventPackage $eventPackage = null): void
    {
        $pkg = $package->package;

        $maxEvents = $pkg?->max_events_per_year;
        $package->remaining_events = $maxEvents === null ? null : max($maxEvents - $package->used_events, 0);
        $package->package_limits = array_merge(
            $pkg?->limits ?? [],
            $this->buildUsageSnapshot($eventPackage),
            [
                'included_package_slug' => $pkg?->included_package_slug,
                'branding_allowed' => $pkg?->branding_allowed,
                'watermark_allowed' => $pkg?->watermark_allowed,
                'features' => $pkg?->features ?? [],
            ]
        );
    }

    /**
     * @return Collection<int, EventPackage>
     */
    private function resolveUsageEventPackage(int $tenantId): ?EventPackage
    {
        $baseQuery = EventPackage::query()
            ->whereHas('event', fn ($query) => $query->where('tenant_id', $tenantId))
            ->with('package')
            ->orderByDesc('purchased_at')
            ->orderByDesc('created_at');

        $activeEventPackage = (clone $baseQuery)
            ->whereNotNull('gallery_expires_at')
            ->where('gallery_expires_at', '>=', now())
            ->first();

        return $activeEventPackage ?? $baseQuery->first();
    }

    private function buildUsageSnapshot(?EventPackage $eventPackage): array
    {
        if (! $eventPackage) {
            return [];
        }

        $limits = $eventPackage->effectiveLimits();
        $maxPhotos = $this->normalizeLimit($limits['max_photos'] ?? null);
        $maxGuests = $this->normalizeLimit($limits['max_guests'] ?? null);
        $galleryDays = $this->normalizeLimit($limits['gallery_days'] ?? null);

        $usedPhotos = (int) $eventPackage->used_photos;
        $usedGuests = (int) $eventPackage->used_guests;

        $remainingPhotos = $maxPhotos === null ? null : max(0, $maxPhotos - $usedPhotos);
        $remainingGuests = $maxGuests === null ? null : max(0, $maxGuests - $usedGuests);

        $remainingGalleryDays = null;
        $usedGalleryDays = null;
        if ($galleryDays !== null && $eventPackage->gallery_expires_at) {
            $remainingGalleryDays = max(0, now()->diffInDays($eventPackage->gallery_expires_at, false));
            $usedGalleryDays = max(0, $galleryDays - $remainingGalleryDays);
        }

        return array_filter([
            'used_photos' => $maxPhotos === null ? null : $usedPhotos,
            'remaining_photos' => $remainingPhotos,
            'used_guests' => $maxGuests === null ? null : $usedGuests,
            'remaining_guests' => $remainingGuests,
            'used_gallery_days' => $usedGalleryDays,
            'remaining_gallery_days' => $remainingGalleryDays,
        ], static fn ($value) => $value !== null);
    }

    private function normalizeLimit(?int $value): ?int
    {
        if ($value === null) {
            return null;
        }

        $value = (int) $value;

        if ($value <= 0) {
            return null;
        }

        return $value;
    }
}
