<?php

namespace Daylight\Core\Http\Requests\Content\Pages;

use Daylight\Core\Http\Requests\Concerns\HandlesSeoRequest;
use Daylight\Core\Modules\Multilingualism\Multilingualism;
use Daylight\Core\Modules\PageBuilder\Concerns\InteractsWithPageBuilder;
use Daylight\Core\Modules\PageBuilder\Contracts\HasPageBuilder;
use Daylight\Core\Modules\PageBuilder\Registries\ComponentRegistry;
use Daylight\Core\Modules\PageBuilder\Registries\TemplateRegistry;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;

class StorePageRequest extends FormRequest implements HasPageBuilder
{
    use HandlesSeoRequest;
    use InteractsWithPageBuilder;

    public function authorize(): bool
    {
        return auth()->check() && auth()->user()->can('create:pages');
    }

    public function rules(): array
    {
        $templates = app(TemplateRegistry::class)->all();

        return [
            'locale' => ['required', 'string', Rule::in(Multilingualism::getAvailableLocales())],
            'name' => ['required', 'string', 'max:255'],
            'slug' => ['required', 'string', 'max:255'],
            ...$templates->isNotEmpty()
                ? ['template' => ['required', 'string', Rule::in($templates->keys())]]
                : ['template' => ['nullable', 'string']],
            ...$this->getPageBuilderRules(),
            ...$this->getSeoRules(),
        ];
    }

    public function messages(): array
    {
        $messages = [
            'components.required' => __('At least one component is required.'),
            'components.*.type.required' => __('Component type is required.'),
            'components.*.data.required' => __('Component data is required.'),
        ];

        // Generate messages for component fields dynamically
        $registry = app(ComponentRegistry::class);
        $components = $this->input('components', []);

        if (is_string($components)) {
            $components = json_decode($components, true) ?: [];
        }

        foreach ($components as $index => $component) {
            if (! isset($component['type']) || ! is_array($component)) {
                continue;
            }

            $definition = $registry->getDefinition($component['type']);
            if (! $definition) {
                continue;
            }

            $componentName = $definition->name();

            foreach ($definition->fields() as $field) {
                $fieldPath = "components.{$index}.data.{$field->name}";
                $fieldLabel = $field->label;

                // Required messages
                $messages["{$fieldPath}.required"] = __('The :field field in component \':component\' (:index) is required.', [
                    'field' => strtolower($fieldLabel),
                    'component' => $componentName,
                    'index' => $index + 1,
                ]);

                // Type-specific messages
                switch ($field->type) {
                    case 'media':
                        $messages["{$fieldPath}.min"] = __('The :field field in component \':component\' (:index) must have at least (.min) item(s).', [
                            'field' => strtolower($fieldLabel),
                            'component' => $componentName,
                            'min' => 1,
                            'index' => $index + 1,
                        ]);
                        $messages["{$fieldPath}.*.id.required"] = __('The :field field in component \':component\' (:index) contains invalid media.', [
                            'field' => strtolower($fieldLabel),
                            'component' => $componentName,
                            'index' => $index + 1,
                        ]);
                        $messages["{$fieldPath}.*.id.exists"] = __('The :field field in component \':component\' (:index) contains invalid media.', [
                            'field' => strtolower($fieldLabel),
                            'component' => $componentName,
                            'index' => $index + 1,
                        ]);
                        break;

                    case 'related':
                        $messages["{$fieldPath}.*.id.required"] = __('The :field field in component :\'component\' (:index) is invalid.', [
                            'field' => strtolower($fieldLabel),
                            'component' => $componentName,
                            'index' => $index + 1,
                        ]);
                        $messages["{$fieldPath}.*.id.integer"] = __('The :field field in component \':component\' (:index) must be valid.', [
                            'field' => strtolower($fieldLabel),
                            'component' => $componentName,
                            'index' => $index + 1,
                        ]);
                        break;

                    case 'repeater':
                        foreach ($field->items as $subField) {
                            $subFieldPath = "{$fieldPath}.*.{$subField->name}";
                            $subFieldLabel = $subField->label;

                            $messages["{$subFieldPath}.required"] = __('The :field field in component \':component\' (:index) row is required.', [
                                'field' => strtolower($subFieldLabel),
                                'component' => $componentName,
                                'index' => $index + 1,
                            ]);

                            if ($subField->type === 'media') {
                                $messages["{$subFieldPath}.*.id.required"] = __('The :field field in component \':component\' (:index) row contains invalid media.', [
                                    'field' => strtolower($subFieldLabel),
                                    'component' => $componentName,
                                    'index' => $index + 1,
                                ]);
                                $messages["{$subFieldPath}.*.id.exists"] = __('The :field field in component \':component\' (:index) row contains invalid media.', [
                                    'field' => strtolower($subFieldLabel),
                                    'component' => $componentName,
                                    'index' => $index + 1,
                                ]);
                            }
                        }
                        break;
                }
            }
        }

        return $messages;
    }

    public function attributes(): array
    {
        $attributes = [
            'locale' => __('Locale'),
            'name' => __('Name'),
            'slug' => __('Slug'),
            'template' => __('Template'),
            'components' => __('Components'),
        ];

        // Generate friendly attribute names for component fields
        $registry = app(ComponentRegistry::class);
        $components = $this->input('components', []);

        if (is_string($components)) {
            $components = json_decode($components, true) ?: [];
        }

        foreach ($components as $index => $component) {
            if (! isset($component['type']) || ! is_array($component)) {
                continue;
            }

            $definition = $registry->getDefinition($component['type']);
            if (! $definition) {
                continue;
            }

            $componentName = $definition->name();

            foreach ($definition->fields() as $field) {
                $fieldPath = "components.{$index}.data.{$field->name}";
                $attributes[$fieldPath] = "{$field->label} ({$componentName})";

                // Handle nested fields (buttons, repeaters, etc.)
                if ($field->type === 'button') {
                    $attributes["{$fieldPath}.url"] = "{$field->label} - " . __('URL');
                    $attributes["{$fieldPath}.label"] = "{$field->label} - " . __('Label');
                }

                if ($field->type === 'repeater') {
                    foreach ($field->items as $subField) {
                        $subFieldPath = "{$fieldPath}.*.{$subField->name}";
                        $attributes[$subFieldPath] = "{$field->label} - {$subField->label} ({$componentName})";
                    }
                }
            }
        }

        return $attributes;
    }
}
