<?php

namespace App\Http\Controllers;

use App\Models\Game;
use App\Rules\GameReleaseDate;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
use Illuminate\Validation\Rule;

class GameController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        // Direct the user to the list of games.
        return view('pages.admin.games.index');
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create()
    {
        // Direct the user to the add game to database page.
        return view('pages.admin.games.create');
    }

    /**
     * Show the form for cloning a resource.
     *
     * @param   int    $gameId
     * @return \Illuminate\Http\Response
     */
    public function clone($gameId)
    {
        // Direct the user to the clone game page.
        $game = Game::findOrFail($gameId);
        return view('pages.admin.games.clone', compact('game'));
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        // Ensure the user has permission to add games into the database.
        $this->authorize('create', Game::class);

        // Validate the data from the request.
        $inputs = $this->validate($request, [
            'name' => 'string|required|max:255',
            'alt_titles' => 'string|nullable|max:255',
            'platform_id' => 'integer|required',
            'description' => 'string|nullable',
            'source' => 'url|nullable|max:255',
            'boxart' => 'image|nullable|max:512',
            'genre_ids' => 'array|nullable',
            'developers' => 'string|nullable|max:255',
            'publishers' => 'string|nullable|max:255',
            'composers' => 'string|nullable|max:255',
            'website' => 'url|nullable|max:255',
            'na_release_date' => [
                new GameReleaseDate(),
                'nullable'
            ],
            'jp_release_date' => [
                new GameReleaseDate(),
                'nullable'
            ],
            'eu_release_date' => [
                new GameReleaseDate(),
                'nullable'
            ],
            'aus_release_date' => [
                new GameReleaseDate(),
                'nullable'
            ],
            'esrb_rating' => [
                'string',
                'nullable',
                Rule::in(['Everyone', 'Everyone 10+', 'Teen', 'Mature 17+', 'Adults Only 18+', 'Rating Pending - Likely Mature 17+']) // phpcs:ignore
            ],
            'pegi_rating' => [
                'string',
                'nullable',
                Rule::in(['PEGI 3', 'PEGI 7', 'PEGI 12', 'PEGI 16', 'PEGI 18'])
            ],
            'cero_rating' => [
                'string',
                'nullable',
                Rule::in(['CERO A', 'CERO B', 'CERO C', 'CERO D', 'CERO Z'])
            ],
            'acb_rating' => [
                'string',
                'nullable',
                Rule::in(['E', 'G', 'PG', 'M', 'MA 15+', 'R 18+', 'X 18+'])
            ]
        ]);

        // Convert the genre_ids array into a comma separated string.
        if (isset($inputs['genre_ids'])) {
            $inputs['genre_ids'] = implode(',', $inputs['genre_ids']);
        }

        // Upload the boxart image as necessary.
        if ($request->hasFile('boxart')) {
            $path = $request->boxart->store('assets/boxart', 's3');
            $inputs['boxart'] = basename($path);
        }

        // Set the requested_by and added_by fields to the current user.
        $inputs['requested_by'] = auth()->user()->id;
        $inputs['added_by'] = auth()->user()->id;

        // Save the data to the database.
        $result = Game::create($inputs);

        // If the creation was successful go to the list of games.
        if ($result->exists) {
            return redirect('/admin/games')->with('create_success', str_replace('"', '', json_encode($inputs['name'])));
        } else { // If the creation failed, go back.
            return back();
        }
    }

    /**
     * Display the specified resource.
     *
     * @param  int  $gameId
     *
     * @return \Illuminate\Http\Response
     */
    public function show($gameId)
    {
        // Direct the user to the games profile page.
        $game = Game::findOrFail($gameId);
        return view('pages.game.index', compact('game'));
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  \App\Models\Game  $game
     * @return \Illuminate\Http\Response
     */
    public function edit(Game $game)
    {
        // Direct the user to the edit game page.
        $game = Game::findOrFail($game->id);
        return view('pages.admin.games.edit', compact('game'));
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \App\Models\Game  $game
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, Game $game)
    {
        // Ensure the user has permission to add games into the database.
        $this->authorize('update', Game::class);

        // Validate the data from the request.
        $inputs = $this->validate($request, [
            'name' => 'string|required|max:255',
            'alt_titles' => 'string|nullable|max:255',
            'platform_id' => 'integer|required',
            'description' => 'string|nullable',
            'source' => 'url|nullable|max:255',
            'boxart' => 'image|nullable|max:512',
            'genre_ids' => 'array|nullable',
            'developers' => 'string|nullable|max:255',
            'publishers' => 'string|nullable|max:255',
            'composers' => 'string|nullable|max:255',
            'website' => 'url|nullable|max:255',
            'na_release_date' => [
                new GameReleaseDate(),
                'nullable'
            ],
            'jp_release_date' => [
                new GameReleaseDate(),
                'nullable'
            ],
            'eu_release_date' => [
                new GameReleaseDate(),
                'nullable'
            ],
            'aus_release_date' => [
                new GameReleaseDate(),
                'nullable'
            ],
            'esrb_rating' => [
                'string',
                'nullable',
                Rule::in(['Everyone', 'Everyone 10+', 'Teen', 'Mature 17+', 'Adults Only 18+', 'Rating Pending - Likely Mature 17+']) // phpcs:ignore
            ],
            'pegi_rating' => [
                'string',
                'nullable',
                Rule::in(['PEGI 3', 'PEGI 7', 'PEGI 12', 'PEGI 16', 'PEGI 18'])
            ],
            'cero_rating' => [
                'string',
                'nullable',
                Rule::in(['CERO A', 'CERO B', 'CERO C', 'CERO D', 'CERO Z'])
            ],
            'acb_rating' => [
                'string',
                'nullable',
                Rule::in(['E', 'G', 'PG', 'M', 'MA 15+', 'R 18+', 'X 18+'])
            ]
        ]);

        // Convert the genre_ids array into a comma separated string.
        if (isset($inputs['genre_ids'])) {
            $inputs['genre_ids'] = implode(',', $inputs['genre_ids']);
            $game->genre_ids = $inputs['genre_ids'];
        }

        // Upload the new boxart image as necessary.
        if ($request->hasFile('boxart')) {
            // Get the current boxart image.
            $original_boxart = $game->boxart;

            // Delete the boxart image if a previous boxart image existed.
            if ($original_boxart) {
                $result = Storage::disk('s3')->delete('assets/boxart/' . $original_boxart);
            }

            // Upload the new boxart image.
            $path = $request->boxart->store('assets/boxart', 's3');
            $inputs['boxart'] = basename($path);
            $game->boxart = $inputs['boxart'];
        }

        // Set the values of the $game object to the new values.
        $game->name = $inputs['name'];
        $game->alt_titles = $inputs['alt_titles'];
        $game->platform_id = $inputs['platform_id'];
        $game->description = $inputs['description'];
        $game->source = $inputs['source'];
        $game->developers = $inputs['developers'];
        $game->publishers = $inputs['publishers'];
        $game->composers = $inputs['composers'];
        $game->website = $inputs['website'];
        $game->na_release_date = $inputs['na_release_date'];
        $game->jp_release_date = $inputs['jp_release_date'];
        $game->eu_release_date = $inputs['eu_release_date'];
        $game->aus_release_date = $inputs['aus_release_date'];
        $game->esrb_rating = $inputs['esrb_rating'];
        $game->pegi_rating = $inputs['pegi_rating'];
        $game->cero_rating = $inputs['cero_rating'];
        $game->acb_rating = $inputs['acb_rating'];

        // Save the data to the database.
        $result = $game->save();

        // If the update was successful show the user the updated game.
        if ($result === true) {
            return redirect('/admin/game/' . $game->id . '/edit')->with('edit_success', '1');
        } else { // If the update failed, go back.
            return back();
        }
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  \App\Models\Game  $game
     * @return \Illuminate\Http\Response
     */
    public function destroy(Game $game)
    {
        //
    }
}
