<?php

namespace App\Domains\Tenant\Requests;

use App\Domains\Catalog\Enums\GroupLayout;
use App\Domains\Catalog\Enums\ProductLayout;
use App\Domains\Shared\Rules\ImageOrBase64Rule;
use App\Domains\Tenant\Enums\CartEditingPolicy;
use App\Domains\Tenant\Models\Tenant;
use App\Domains\Tenant\Support\TenantDomainNormalizer;
use Closure;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;

class UpdateTenantRequest extends FormRequest
{
    protected bool $hasInvalidDomain = false;

    protected bool $hasInvalidBasePath = false;

    public function authorize(): bool
    {
        return true;
    }

    protected function prepareForValidation(): void
    {
        if ($this->has('dominio')) {
            $rawDomain = $this->input('dominio');
            $normalizedDomain = TenantDomainNormalizer::normalize($rawDomain);
            $embeddedBasePath = TenantDomainNormalizer::pathFromDomain($rawDomain);

            $this->hasInvalidDomain = TenantDomainNormalizer::hasValue($rawDomain)
                && ($normalizedDomain === null || $embeddedBasePath === null);

            $this->merge([
                'dominio' => $normalizedDomain,
            ]);

            if (! $this->has('base_path') && $embeddedBasePath !== null && $embeddedBasePath !== '/') {
                $this->merge(['base_path' => $embeddedBasePath]);
            }
        }

        if ($this->has('base_path')) {
            $rawBasePath = $this->input('base_path');
            $normalizedBasePath = TenantDomainNormalizer::normalizePath($rawBasePath);

            $this->hasInvalidBasePath = ! is_string($rawBasePath)
                || $normalizedBasePath === null;

            $this->merge(['base_path' => $normalizedBasePath]);
        }
    }

    /**
     * @return array<string, mixed>
     */
    public function rules(): array
    {
        /** @var Tenant|null $tenant */
        $tenant = $this->route('tenant');
        $domain = $this->input('dominio', $tenant?->dominio);
        $basePath = $this->input('base_path', $tenant?->base_path ?? '/');

        $logoRule = ['nullable', new ImageOrBase64Rule];

        return [
            'client_id' => ['sometimes', 'integer', Rule::exists('clients', 'id')],
            'codigo' => [
                'nullable',
                'string',
                'max:255',
                Rule::unique('tenants', 'codigo')->ignore($tenant?->id),
            ],
            'nombre' => ['nullable', 'string', 'max:255'],
            'dominio' => [
                'bail',
                function (string $attribute, mixed $value, Closure $fail): void {
                    if ($this->hasInvalidDomain) {
                        $fail("The {$attribute} field must contain a valid domain or URL.");
                    }
                },
                'nullable',
                'string',
                'max:255',
                Rule::unique('tenants', 'dominio')
                    ->where('base_path', $basePath)
                    ->ignore($tenant?->id),
            ],
            'base_path' => [
                'bail',
                function (string $attribute, mixed $value, Closure $fail): void {
                    if ($this->hasInvalidBasePath) {
                        $fail("The {$attribute} field must contain a valid URL path.");
                    }
                },
                'nullable',
                'string',
                'max:255',
                Rule::unique('tenants', 'base_path')
                    ->where('dominio', $domain)
                    ->ignore($tenant?->id),
            ],
            'site_title' => ['sometimes', 'nullable', 'string', 'max:255'],
            'address' => ['sometimes', 'nullable', 'string', 'max:255'],
            'phone' => ['sometimes', 'nullable', 'string', 'max:255'],
            'primary_color' => ['nullable', 'string', 'regex:/^#([a-fA-F0-9]{3,4}|[a-fA-F0-9]{6}|[a-fA-F0-9]{8})$/'],
            'secondary_color' => ['nullable', 'string', 'regex:/^#([a-fA-F0-9]{3,4}|[a-fA-F0-9]{6}|[a-fA-F0-9]{8})$/'],
            'danger_color' => ['nullable', 'string', 'regex:/^#([a-fA-F0-9]{3,4}|[a-fA-F0-9]{6}|[a-fA-F0-9]{8})$/'],
            'success_color' => ['nullable', 'string', 'regex:/^#([a-fA-F0-9]{3,4}|[a-fA-F0-9]{6}|[a-fA-F0-9]{8})$/'],
            'header_bg_color' => ['nullable', 'string', 'regex:/^#([a-fA-F0-9]{3,4}|[a-fA-F0-9]{6}|[a-fA-F0-9]{8})$/'],
            'footer_bg_color' => ['nullable', 'string', 'regex:/^#([a-fA-F0-9]{3,4}|[a-fA-F0-9]{6}|[a-fA-F0-9]{8})$/'],
            'header_logo' => $logoRule,
            'footer_logo' => $logoRule,
            'favicon' => ['sometimes', 'nullable', new ImageOrBase64Rule],
            'header_bg_image' => ['sometimes', 'nullable', new ImageOrBase64Rule],
            'footer_bg_image' => ['sometimes', 'nullable', new ImageOrBase64Rule],
            'social_media' => ['sometimes', 'array'],
            'social_media.*.code' => [
                'required',
                'string',
                'distinct',
                Rule::exists('social_media', 'code'),
            ],
            'social_media.*.url' => ['required', 'url', 'max:2048'],
            'social_media.*.orden' => ['sometimes', 'integer', 'min:0', 'distinct'],
            'search_product_layout' => ['sometimes', Rule::enum(ProductLayout::class)],
            'search_group_layout' => ['sometimes', Rule::enum(GroupLayout::class)],
            'search_items_per_page' => ['sometimes', 'integer', 'min:4', 'max:48'],
            'display_categories' => ['sometimes', 'boolean'],
            'display_seach_bar' => ['sometimes', 'boolean'],
            'display_cart' => ['sometimes', 'boolean'],
            'cart_editing_policy' => ['sometimes', Rule::enum(CartEditingPolicy::class)],
            'checkout_editing_policy' => [
                'sometimes',
                Rule::in([CartEditingPolicy::Disabled->value]),
            ],
            'display_cart_item_images' => ['sometimes', 'boolean'],
            'scanner_category_validation_enabled' => ['sometimes', 'boolean'],
        ];
    }
}
