<?php

namespace App\Http\Requests;

use App\Rules\PublicFileExists;
use App\Rules\XfUserExists;
use Illuminate\Contracts\Validation\ValidationRule;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Str;

class StoreEntryRequest extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     */
    public function authorize(): bool
    {
        $entry = $this->route('entry');
        if( $entry )
            return $this->user()->can('update', $entry);

        return $this->user()->can('create', '\App\Models\Entry');
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array<string, ValidationRule|array<mixed>|string>
     */
    public function prepareForValidation(): void
    {

        $newGameTitle = trim((string) $this->input('new-game-title', ''));
        $newGamePlatform = $this->input('new-game-platform');
        $newGameGenre = $this->input('new-game-genre');

        $this->merge([
            'game_id' => $this->input('game_id') !== '' ? $this->input('game_id') : null,
            'new-game-title' => $newGameTitle !== '' ? $newGameTitle : null,
            'new-game-platform' => $newGamePlatform !== '' ? $newGamePlatform : null,
            'new-game-genre' => $newGameGenre !== '' ? $newGameGenre : null,
            'gallery' => $this->input('gallery') !== '' ? $this->input('gallery') : null,
        ]);
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array<string, ValidationRule|array<mixed>|string>
     */
    public function rules(): array
    {

        $isEdit = (bool) $this->route('entry');

        $rules = [];
        $section = $this->route('section');

        $rules['files_uuid'] = 'array|required|min:1';
        $rules['files_uuid.*'] = 'string';

        if( $isEdit ){
            $rules['files_state'] = 'array|required|min:1';
            $rules['files_state.*'] = 'string|in:public,private,archived';
        }

        if( section_must_not_be( ['translations','homebrew'], $section ) ){
            $rules['entry_title'] = "required|string|max:255";
        } else {
            $rules['entry_title'] = "nullable|string|max:255";
        }

        if( section_must_be( ['romhacks', 'lua-scripts'], $section ) ){
            $rules['modifications'] = 'array|required|min:1';
            $rules['modifications.*'] = 'integer|exists:modifications,id';
        } else if( section_must_be( ['utilities','documents'], $section ) ){
            $rules['categories'] = 'array|required|min:1';
            $rules['categories.*'] = 'integer|exists:categories,id';
        }

        if( section_must_be( 'utilities', $section ) ){
            $rules['systems'] = 'array|required|min:1';
            $rules['systems.*'] = 'integer|exists:systems,id';
        }

        $rules['version'] = 'required|string|max:50';
        $rules['release-date'] = 'required|date';
        if( section_must_not_be( ['utilities', 'documents'], $section ) ){
            $rules['status'] = 'required|integer|exists:statuses,id';
        } else {
            $rules['level'] = 'required|integer|exists:levels,id';
        }
        $rules['description'] = 'required|string';

        $rules['game_selection_mode'] = 'required|string|in:game,platform,none';
        $gameSelectionMode = $this->input('game_selection_mode') !== '' ? $this->input('game_selection_mode') : 'game';

        if( $gameSelectionMode === 'none' ){
            // ...
        } else if( $gameSelectionMode === 'platform' ){
            $rules['platform_only_id'] = 'required|integer|exists:platforms,id';
        } else {
            $rules['game_id'] = 'required_without:new-game-title|nullable|integer|exists:games,id';
            $rules['new-game-title'] = 'required_without:game_id|nullable|string|max:255';
            $rules['new-game-platform'] = 'required_with:new-game-title|nullable|integer|exists:platforms,id';
            $rules['new-game-genre'] = 'required_with:new-game-title|integer|nullable|exists:genres,id';
        }

        $bypassHashes = $isEdit && $this->user()->can('moderate', $this->route('entry') ) && ($this->input('bypass_hashes') !== null);

        if( section_must_be( ['translations', 'romhacks'], $section ) && !$bypassHashes ){
            $rules['hashes'] = 'array|required|min:1';
            $rules['hashes.*.filename'] = 'required|string|max:512';
            $rules['hashes.*.hash_crc32'] = 'required|string|max:512';
            $rules['hashes.*.hash_sha1'] = 'required|string|max:512';
            $rules['hashes.*.verified'] = 'required|string|max:512';
        }

        $rules['languages'] = 'array|required|min:1';
        $rules['languages.*'] = 'integer|exists:languages,id';

        $rules['main-image'] = [ 'required', 'string', new PublicFileExists ];
        $rules['gallery'] = 'array|required|min:1';
        $rules['gallery.*'] = [ 'string', new PublicFileExists ];

        $rules['authors'] = 'array|required_without:new-authors|min:1';
        $rules['authors.*'] = 'integer|exists:authors,id';
        $rules['new-authors'] = 'array|required_without:authors|min:1';
        $rules['new-authors.*'] = 'string|max:255';

        $rules['staff_credits'] = 'nullable|json';
        $rules['release_site'] = 'nullable|url|max:500';
        $rules['youtube_video'] = 'nullable|url|max:500';

        if( $isEdit ){
            $ss = 'draft,pending,published';
            if( \Auth::user()->can('moderate', $this->route('entry')) && \Auth::user()->can('view-hidden', $this->route('entry')) )
                $ss .= ',hidden';
            if(\Auth::user()->can('moderate', $this->route('entry')) && \Auth::user()->can('view-locked', $this->route('entry')) )
                $ss .= ',locked';
            $rules['submit-state'] = 'required|in:' . $ss;
        } else {
            $rules['nsfw-entry'] = 'nullable|boolean';
            if( $this->user()->can('skip-queue', '\App\Models\Entry') ){
                $rules['submit-state'] = 'required|string|in:draft,pending,published';
            } else {
                $rules['submit-state'] = 'required|string|in:draft,pending';
            }
        }

        if( $isEdit ){
            $rules['files_metadata'] = 'array|nullable';
            $rules['files_metadata.*.online_patcher'] = 'nullable|boolean';
            $rules['files_metadata.*.secondary_online_patcher'] = 'nullable|boolean|required_with:files_metadata.*.online_patcher';
            $rules['files_metadata.*.play_online'] = 'nullable|boolean';
            $rules['files_metadata.*.play_online_core'] = 'nullable|string';
            $rules['files_metadata.*.play_online_threads'] = 'nullable|boolean';
        }

        if( $isEdit && $this->user()->can('moderate', $this->route('entry') ) ){
            $rules['staff_comment'] = 'nullable|string';
            $rules['owner_user_id'] = [ 'required', 'integer', new XfUserExists ];
            $rules['comments_thread_id'] = 'nullable|integer';
            $rules['featured'] = 'nullable|boolean';
            $rules['refresh_created_at'] = 'nullable|boolean';
            $rules['nsfw-entry'] = 'nullable|boolean';
        }

        return $rules;
    }

    public function messages(): array
    {
        return [
            'files_uuid.required' => 'Please upload at least a file.',
            'files_state.required' => 'A file may be corrupted, please reupload it.',
            'files_state.*.in' => 'A file state doesn\'t have a standard value.',
            'entry_title.required' => 'Please enter a title.',
            'modifications.required' => 'Please select at least one modification.',
            'categories.required' => 'Please select at least one category.',
            'system.required' => 'Please select at least one system.',
            'version.required' => 'Please enter a version number.',
            'release-date.required' => 'Please enter a valid release date.',
            'status.required' => 'Please select a status.',
            'level.required' => 'Please select an experience level.',
            'description.required' => 'Please enter a description.',
            'game_selection_mode.required' => 'Please select a game selection mode.',
            'platform_only_id.required' => 'Please select a platform.',
            'game_id.required' => 'Please select a game.',
            'new-game-title.required' => 'Please enter a game title.',
            'new-game-platform.required' => 'Please select a game platform.',
            'new-game-genre.required' => 'Please select a game genre.',
            'hashes.required' => 'Please send at least one hash.',
            'languages.required' => 'Please select at least one language.',
            'main-image.required' => 'Please upload a main image.',
            'gallery.required' => 'Please upload at least one image for the gallery.',
            'authors.required' => 'Please select at least one author.',
            'new-authors.required' => 'Please select at least one author.',
            'submit-state.required' => 'Please select a submit state.',
        ];
    }
}
