<?php

declare(strict_types=1);

namespace App\Domain\Reseller\Services;

use App\Domain\Package\Models\Package;
use App\Domain\Reseller\Models\ResellerSubPackage;
use App\Models\User;
use Illuminate\Support\Collection;
use Illuminate\Support\Str;
use Illuminate\Validation\ValidationException;

/**
 * Alt-paket (reseller sub-package) yönetimi.
 *
 * Her alt-paket bir üst pakete bağlıdır; limitleri üst paketi aşamaz.
 */
class SubPackageManager
{
    /**
     * Yeni alt-paket oluşturur.
     *
     * @param  array{name:string, slug?:string, limits:array, reseller_price_try?:float, is_active?:bool, display_order?:int}  $data
     */
    public function createSubPackage(User $reseller, Package $parent, array $data): ResellerSubPackage
    {
        $slug = $data['slug'] ?? Str::slug($data['name']);
        $limits = $this->validateLimits($parent, $data['limits']);

        return ResellerSubPackage::create([
            'reseller_user_id' => $reseller->id,
            'parent_package_id' => $parent->id,
            'name' => $data['name'],
            'slug' => $slug,
            'limits' => $limits,
            'reseller_price_try' => $data['reseller_price_try'] ?? null,
            'is_active' => $data['is_active'] ?? true,
            'display_order' => $data['display_order'] ?? 0,
        ]);
    }

    /**
     * Mevcut alt-paketi günceller.
     *
     * @param  array{name?:string, slug?:string, limits?:array, reseller_price_try?:float, is_active?:bool, display_order?:int}  $data
     */
    public function updateSubPackage(ResellerSubPackage $sub, array $data): void
    {
        if (isset($data['limits'])) {
            $data['limits'] = $this->validateLimits($sub->parentPackage, $data['limits']);
        }

        $sub->update($data);
    }

    /**
     * Alt-paket limitlerinin üst paketi aşmadığını doğrular.
     *
     * Null (unlimited) değer üst pakette varsa alt-paket de null kullanabilir.
     * Alt-paket hiçbir zaman üst paketten daha yüksek bir sayısal değer alamaz.
     *
     * @param  array<string, mixed>  $childLimits
     * @return array<string, mixed>
     *
     * @throws ValidationException
     */
    public function validateLimits(Package $parent, array $childLimits): array
    {
        $parentLimits = $parent->limits ?? [];
        $errors = [];

        foreach ($childLimits as $key => $childValue) {
            $parentValue = $parentLimits[$key] ?? null;

            // Parent sınırsız (null) → çocuk da sınırsız veya sayısal olabilir
            if ($parentValue === null) {
                continue;
            }

            // Çocuk da null (sınırsız) istemiş ama parent kısıtlı → izin verme
            if ($childValue === null) {
                $errors[$key] = "Üst paket {$key} için sınır tanımlıyor ({$parentValue}); alt-paket sınırsız olamaz.";

                continue;
            }

            // Sayısal değerler için kontrol
            if (is_numeric($childValue) && is_numeric($parentValue)) {
                if ((float) $childValue > (float) $parentValue) {
                    $errors[$key] = "{$key} değeri ({$childValue}) üst paketteki sınırı ({$parentValue}) aşıyor.";
                }
            }
        }

        if (! empty($errors)) {
            throw ValidationException::withMessages($errors);
        }

        return $childLimits;
    }

    /**
     * Alt-paketi siler.
     */
    public function deleteSubPackage(ResellerSubPackage $sub): void
    {
        $sub->delete();
    }

    /**
     * Belirtilen reseller'ın tüm alt-paketlerini döndürür.
     */
    public function listForReseller(User $reseller): Collection
    {
        return ResellerSubPackage::where('reseller_user_id', $reseller->id)
            ->with('parentPackage:id,name,slug')
            ->orderBy('display_order')
            ->orderBy('name')
            ->get();
    }
}
