<?php

declare(strict_types=1);

namespace App\Http\Requests\Academy;

use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Arr;
use Illuminate\Validation\Rule;

class UpsertAcademyLessonRequest extends FormRequest
{
    public function authorize(): bool
    {
        return (bool) $this->user()?->hasStaffAccess();
    }

    protected function prepareForValidation(): void
    {
        $blocks = collect($this->input('blocks', []))
            ->filter(static fn ($block): bool => is_array($block))
            ->map(function (array $block): array {
                $payload = Arr::wrap($block['payload'] ?? []);
                $criteria = collect($payload['criteria'] ?? [])
                    ->map(static fn ($criterion) => trim((string) $criterion))
                    ->filter(static fn (string $criterion): bool => $criterion !== '')
                    ->values()
                    ->all();

                $results = collect($block['comparison_results'] ?? [])
                    ->filter(static fn ($result): bool => is_array($result))
                    ->map(function (array $result): array {
                        return [
                            'id' => filled($result['id'] ?? null) ? (int) $result['id'] : null,
                            'provider' => $result['provider'] ?? null,
                            'model_name' => $result['model_name'] ?? null,
                            'image_path' => $result['image_path'] ?? null,
                            'thumb_path' => $result['thumb_path'] ?? null,
                            'settings' => $result['settings'] ?? null,
                            'strengths' => $result['strengths'] ?? null,
                            'weaknesses' => $result['weaknesses'] ?? null,
                            'best_for' => $result['best_for'] ?? null,
                            'score' => filled($result['score'] ?? null) ? (int) $result['score'] : null,
                            'sort_order' => filled($result['sort_order'] ?? null) ? (int) $result['sort_order'] : 0,
                            'active' => filter_var($result['active'] ?? true, FILTER_VALIDATE_BOOL, FILTER_NULL_ON_FAILURE) ?? true,
                        ];
                    })
                    ->values()
                    ->all();

                return [
                    'id' => filled($block['id'] ?? null) ? (int) $block['id'] : null,
                    'type' => (string) ($block['type'] ?? 'ai_comparison'),
                    'title' => $block['title'] ?? null,
                    'payload' => [
                        'title' => $payload['title'] ?? null,
                        'intro' => $payload['intro'] ?? null,
                        'prompt' => $payload['prompt'] ?? null,
                        'negative_prompt' => $payload['negative_prompt'] ?? null,
                        'aspect_ratio' => $payload['aspect_ratio'] ?? null,
                        'criteria' => $criteria,
                    ],
                    'sort_order' => filled($block['sort_order'] ?? null) ? (int) $block['sort_order'] : 0,
                    'active' => filter_var($block['active'] ?? true, FILTER_VALIDATE_BOOL, FILTER_NULL_ON_FAILURE) ?? true,
                    'comparison_results' => $results,
                ];
            })
            ->values()
            ->all();

        $this->merge([
            'lesson_number' => $this->filled('lesson_number') ? (int) $this->input('lesson_number') : null,
            'course_order' => $this->filled('course_order') ? (int) $this->input('course_order') : null,
            'content_source' => in_array((string) $this->input('content_source'), ['html', 'markdown'], true)
                ? (string) $this->input('content_source')
                : ($this->filled('content_markdown') ? 'markdown' : 'html'),
            'course_ids' => collect($this->input('course_ids', []))
                ->filter(static fn ($courseId): bool => filled($courseId))
                ->map(static fn ($courseId): int => (int) $courseId)
                ->unique()
                ->values()
                ->all(),
            'tags' => array_values(array_filter((array) $this->input('tags', []))),
            'reading_minutes' => $this->filled('reading_minutes') ? (int) $this->input('reading_minutes') : 5,
            'featured' => $this->boolean('featured'),
            'active' => $this->boolean('active', true),
            'blocks' => $blocks,
        ]);
    }

    public function rules(): array
    {
        $lessonId = $this->route('academyLesson')?->id;

        return [
            'category_id' => ['nullable', 'integer', 'exists:academy_categories,id'],
            'title' => ['required', 'string', 'max:180'],
            'slug' => ['required', 'string', 'max:180', Rule::unique('academy_lessons', 'slug')->ignore($lessonId)],
            'lesson_number' => ['nullable', 'integer', 'min:1'],
            'course_order' => ['nullable', 'integer', 'min:1'],
            'course_ids' => ['nullable', 'array'],
            'course_ids.*' => ['integer', 'exists:academy_courses,id'],
            'series_name' => ['nullable', 'string', 'max:120'],
            'excerpt' => ['nullable', 'string'],
            'content' => ['nullable', 'string'],
            'content_markdown' => ['nullable', 'string'],
            'content_source' => ['required', 'string', Rule::in(['html', 'markdown'])],
            'difficulty' => ['required', 'string', Rule::in((array) config('academy.difficulty_levels', []))],
            'access_level' => ['required', 'string', Rule::in(['free', 'creator', 'pro'])],
            'lesson_type' => ['required', 'string', 'max:80'],
            'cover_image' => ['nullable', 'string', 'max:2048'],
            'article_cover_image' => ['nullable', 'string', 'max:2048'],
            'tags' => ['nullable', 'array'],
            'tags.*' => ['string', 'max:200'],
            'video_url' => ['nullable', 'string', 'max:2048'],
            'reading_minutes' => ['required', 'integer', 'min:1', 'max:999'],
            'featured' => ['required', 'boolean'],
            'active' => ['required', 'boolean'],
            'published_at' => ['nullable', 'date'],
            'seo_title' => ['nullable', 'string', 'max:180'],
            'seo_description' => ['nullable', 'string', 'max:255'],
            'blocks' => ['nullable', 'array'],
            'blocks.*.id' => ['nullable', 'integer', 'exists:academy_lesson_blocks,id'],
            'blocks.*.type' => ['required', 'string', Rule::in(['ai_comparison'])],
            'blocks.*.title' => ['nullable', 'string', 'max:255'],
            'blocks.*.payload' => ['nullable', 'array'],
            'blocks.*.payload.title' => ['nullable', 'string', 'max:255'],
            'blocks.*.payload.intro' => ['nullable', 'string'],
            'blocks.*.payload.prompt' => ['nullable', 'string'],
            'blocks.*.payload.negative_prompt' => ['nullable', 'string'],
            'blocks.*.payload.aspect_ratio' => ['nullable', 'string', 'max:20'],
            'blocks.*.payload.criteria' => ['nullable', 'array'],
            'blocks.*.payload.criteria.*' => ['nullable', 'string', 'max:100'],
            'blocks.*.sort_order' => ['required', 'integer', 'min:0'],
            'blocks.*.active' => ['required', 'boolean'],
            'blocks.*.comparison_results' => ['nullable', 'array'],
            'blocks.*.comparison_results.*.id' => ['nullable', 'integer', 'exists:academy_ai_comparison_results,id'],
            'blocks.*.comparison_results.*.provider' => ['nullable', 'string', 'max:100'],
            'blocks.*.comparison_results.*.model_name' => ['nullable', 'string', 'max:150'],
            'blocks.*.comparison_results.*.image_path' => ['required', 'string', 'max:500'],
            'blocks.*.comparison_results.*.thumb_path' => ['nullable', 'string', 'max:500'],
            'blocks.*.comparison_results.*.settings' => ['nullable', 'string'],
            'blocks.*.comparison_results.*.strengths' => ['nullable', 'string'],
            'blocks.*.comparison_results.*.weaknesses' => ['nullable', 'string'],
            'blocks.*.comparison_results.*.best_for' => ['nullable', 'string'],
            'blocks.*.comparison_results.*.score' => ['nullable', 'integer', 'min:1', 'max:10'],
            'blocks.*.comparison_results.*.sort_order' => ['required', 'integer', 'min:0'],
            'blocks.*.comparison_results.*.active' => ['required', 'boolean'],
        ];
    }
}
