<?php

declare(strict_types=1);

namespace App\Http\Requests\Settings;

use App\Models\HomepageAnnouncement;
use App\Services\HomepageAnnouncementSanitizer;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;

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

    protected function prepareForValidation(): void
    {
        $this->merge([
            'is_active' => $this->boolean('is_active'),
            'is_dismissible' => $this->boolean('is_dismissible', true),
            'remove_background_image' => $this->boolean('remove_background_image'),
            'priority' => $this->filled('priority') ? (int) $this->input('priority') : 0,
            'dismiss_version' => $this->filled('dismiss_version') ? (int) $this->input('dismiss_version') : 1,
            'overlay_opacity' => $this->filled('overlay_opacity') ? (int) $this->input('overlay_opacity') : 55,
        ]);
    }

    public function rules(): array
    {
        return [
            'title' => ['required', 'string', 'max:180'],
            'subtitle' => ['nullable', 'string', 'max:255'],
            'badge_text' => ['nullable', 'string', 'max:100'],
            'content_html' => ['nullable', 'string'],
            'type' => ['required', 'string', Rule::in(HomepageAnnouncement::types())],
            'status' => ['required', 'string', Rule::in(HomepageAnnouncement::statuses())],
            'is_active' => ['required', 'boolean'],
            'starts_at' => ['nullable', 'date'],
            'ends_at' => ['nullable', 'date', 'after_or_equal:starts_at'],
            'priority' => ['required', 'integer', 'min:-9999', 'max:9999'],
            'is_dismissible' => ['required', 'boolean'],
            'dismiss_version' => ['required', 'integer', 'min:1', 'max:999999'],
            'gradient_preset' => ['nullable', 'string', Rule::in(HomepageAnnouncement::gradientPresets())],
            'theme_preset' => ['nullable', 'string', 'max:80'],
            'placement' => ['required', 'string', Rule::in(HomepageAnnouncement::placements())],
            'text_color' => ['nullable', 'string', 'max:32'],
            'overlay_opacity' => ['nullable', 'integer', 'min:0', 'max:100'],
            'background_image' => ['nullable', 'string', 'max:2048'],
            'background_image_file' => ['nullable', 'file', 'image', 'mimes:jpeg,jpg,png,webp', 'max:5120'],
            'remove_background_image' => ['nullable', 'boolean'],

            'primary_link_label' => ['nullable', 'string', 'max:80'],
            'primary_link_type' => ['nullable', 'string', Rule::in(HomepageAnnouncement::linkTypes())],
            'primary_link_url' => ['nullable', 'string', 'max:2048'],
            'primary_link_target_id' => ['nullable', 'integer', 'min:1'],

            'secondary_link_label' => ['nullable', 'string', 'max:80'],
            'secondary_link_type' => ['nullable', 'string', Rule::in(HomepageAnnouncement::linkTypes())],
            'secondary_link_url' => ['nullable', 'string', 'max:2048'],
            'secondary_link_target_id' => ['nullable', 'integer', 'min:1'],
        ];
    }

    public function withValidator($validator): void
    {
        $validator->after(function ($validator): void {
            $sanitizer = app(HomepageAnnouncementSanitizer::class);

            foreach (['primary', 'secondary'] as $prefix) {
                $type = (string) ($this->input($prefix . '_link_type') ?: HomepageAnnouncement::LINK_TYPE_NONE);
                $label = trim((string) $this->input($prefix . '_link_label', ''));
                $url = trim((string) $this->input($prefix . '_link_url', ''));
                $targetId = (int) $this->input($prefix . '_link_target_id', 0);

                if ($url !== '' && ! $sanitizer->isSafeCustomUrl($url)) {
                    $validator->errors()->add($prefix . '_link_url', 'Use a relative path starting with / or an https:// URL. Unsafe protocols are not allowed.');
                }

                if ($type !== HomepageAnnouncement::LINK_TYPE_NONE && $label === '') {
                    $validator->errors()->add($prefix . '_link_label', 'Provide a CTA label when this link is enabled.');
                }

                if ($type === HomepageAnnouncement::LINK_TYPE_CUSTOM_URL && $url === '') {
                    $validator->errors()->add($prefix . '_link_url', 'Provide a URL for custom links.');
                }

                if (! in_array($type, [HomepageAnnouncement::LINK_TYPE_NONE, HomepageAnnouncement::LINK_TYPE_CUSTOM_URL, HomepageAnnouncement::LINK_TYPE_EXPLORE, HomepageAnnouncement::LINK_TYPE_UPLOAD], true)
                    && $url === ''
                    && $targetId < 1) {
                    $validator->errors()->add($prefix . '_link_target_id', 'Provide a target id or a fallback URL for this CTA type.');
                }
            }
        });
    }
}