<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Jobs\TranslateCreationJob;
use App\Models\Category;
use App\Models\Creation;
use App\Models\Translation;
use App\Models\TranslationKey;
use App\Rules\ImageValidationRule;
use App\Services\UploadedFilesService;
use Exception;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
use Illuminate\Validation\Rule;
use Illuminate\Validation\Rules\File;
use Illuminate\View\View;

class CreationController extends Controller
{
    protected array $headerRoutes = [
        [
            'route' => 'admin.creations.index',
            'label' => 'Liste des créations',
            'icon' => 'list',
        ],
        [
            'route' => 'admin.creations.create',
            'label' => 'Créer une création',
            'icon' => 'plus',
        ],
    ];

    public function __construct(protected UploadedFilesService $uploadedFilesService) {}

    public function listPage(): View
    {
        $creations = Creation::with(['nameTranslationKey', 'category'])
            ->orderBy('is_highlighted', 'desc')
            ->orderBy('id', 'desc')
            ->get();

        return view('admin.creations.index', [
            'headerRoutes' => $this->headerRoutes,
            'creations' => $creations,
        ]);
    }

    public function createPage(): View
    {
        $categories = Category::with('nameTranslationKey.translations')
            ->get()
            ->mapWithKeys(function ($category) {
                $name = $category->nameTranslationKey->translations->firstWhere('locale', 'fr')->text ?? 'N/A';

                return [$category->id => $name];
            });

        return view('admin.creations.edit', [
            'title' => 'Créer une création',
            'headerRoutes' => $this->headerRoutes,
            'categories' => $categories,
        ]);
    }

    public function editPage(Request $request, int $id): View
    {
        $request->validate([
            'lang' => 'sometimes|string|in:fr,en',
        ]);

        $lang = $request->input('lang', 'fr');
        $creation = Creation::findOrFail($id)->load(['nameTranslationKey.translations', 'shortDescriptionTranslationKey.translations', 'descriptionTranslationKey.translations', 'coverUploadedPicture', 'creationPictures']);
        $name = $creation->nameTranslationKey->getTranslation($lang);
        $shortDescription = $creation->shortDescriptionTranslationKey?->getTranslation($lang) ?? '';
        $description = $creation->descriptionTranslationKey?->getTranslation($lang) ?? '';

        $categories = Category::with('nameTranslationKey.translations')
            ->get()
            ->mapWithKeys(function ($category) {
                $name = $category->nameTranslationKey->translations->firstWhere('locale', 'fr')->text ?? 'N/A';

                return [$category->id => $name];
            });

        return view('admin.creations.edit', [
            'title' => 'Modifier une création',
            'headerRoutes' => $this->headerRoutes,
            'creation' => $creation,
            'name' => $name,
            'shortDescription' => $shortDescription,
            'description' => $description,
            'lang' => $request->input('lang', 'fr'),
            'categories' => $categories,
        ]);
    }

    public function store(Request $request): RedirectResponse
    {
        $request->validate([
            'lang' => 'required|string|in:fr,en',
            'name' => 'required|string',
            'slug' => 'required|string',
            'category_id' => 'required|exists:categories,id',
            'short_description' => 'sometimes|nullable|string',
            'description' => 'sometimes|nullable|string',
            'completion_date_start' => 'sometimes|nullable|date_format:Y',
            'completion_date_end' => 'sometimes|nullable|date_format:Y',
            'tags' => 'sometimes|nullable|string',
            'cover_image' => [
                'required',
                new ImageValidationRule,
            ],
            'additional_images' => 'sometimes|array',
            'additional_images.*' => File::image()
                ->max('50mb')
                ->dimensions(Rule::dimensions()->maxWidth(config('app.imagick.max_width'))->maxHeight(config('app.imagick.max_height'))),
            'is_highlighted' => 'sometimes|accepted',
        ]);

        $slug = Str::slug($request->input('slug'));

        if (Creation::where('slug', $slug)->exists()) {
            return redirect()->route('admin.creations.create')
                ->withInput()
                ->with('error', 'Un élément avec ce slug existe déjà.');
        }

        $shortDescription = ! empty($request->input('short_description')) ? $request->input('short_description') : '';
        $description = ! empty($request->input('description')) ? $request->input('description') : '';

        $nameTranslationKey = TranslationKey::create([
            'key' => 'creation_'.Str::uuid(),
        ]);

        $shortDescriptionTranslationKey = TranslationKey::create([
            'key' => 'creation_short_description_'.Str::uuid(),
        ]);

        $descriptionTranslationKey = TranslationKey::create([
            'key' => 'creation_description_'.Str::uuid(),
        ]);

        Translation::create([
            'translation_key_id' => $nameTranslationKey->id,
            'locale' => $request->input('lang'),
            'text' => $request->input('name'),
        ]);

        Translation::create([
            'translation_key_id' => $shortDescriptionTranslationKey->id,
            'locale' => $request->input('lang'),
            'text' => $shortDescription,
        ]);

        Translation::create([
            'translation_key_id' => $descriptionTranslationKey->id,
            'locale' => $request->input('lang'),
            'text' => $description,
        ]);

        try {
            $coverUploadedPicture = $this->uploadedFilesService->storeAndOptimizeUploadedPicture($request->file('cover_image'));
        } catch (Exception $e) {
            Log::error('Error while storing uploaded picture', [
                'exception' => $e,
            ]);

            return redirect()->route('admin.creations.create')
                ->withInput()
                ->with('error', 'Une erreur est survenue lors de l\'enregistrement de l\'image.');
        }

        $additionalUploadedPictures = [];

        if ($request->hasFile('additional_images')) {
            foreach ($request->file('additional_images') as $additionalImage) {
                try {
                    $additionalUploadedPictures[] = $this->uploadedFilesService->storeAndOptimizeUploadedPicture($additionalImage);
                } catch (Exception $e) {
                    Log::error('Error while storing uploaded picture', [
                        'exception' => $e,
                    ]);

                    return redirect()->route('admin.creations.create')->withInput()
                        ->with('error', 'Une erreur est survenue lors de l\'enregistrement de l\'image.');
                }
            }
        }

        $creation = Creation::create([
            'slug' => $slug,
            'category_id' => $request->input('category_id'),
            'name_translation_key_id' => $nameTranslationKey->id,
            'short_desc_translation_key_id' => $shortDescriptionTranslationKey->id,
            'desc_translation_key_id' => $descriptionTranslationKey->id,
            'cover_uploaded_picture_id' => $coverUploadedPicture->id,
            'completion_date_start' => $request->input('completion_date_start'),
            'completion_date_end' => $request->input('completion_date_end'),
            'tags' => $request->input('tags'),
            'is_highlighted' => $request->boolean('is_highlighted', false),
        ]);

        $creation->creationPictures()->attach($additionalUploadedPictures);

        return redirect()->route('admin.creations.edit', [
            'creation' => $creation->id,
            'lang' => $request->input('lang'),
        ])->with('success', 'Création créée avec succès.');
    }

    public function update(Request $request, int $id): RedirectResponse
    {
        $request->validate([
            'lang' => 'required|string|in:fr,en',
            'name' => 'required|string',
            'slug' => 'required|string',
            'category_id' => 'required|exists:categories,id',
            'short_description' => 'sometimes|nullable|string',
            'description' => 'sometimes|nullable|string',
            'completion_date_start' => 'sometimes|nullable|date_format:Y',
            'completion_date_end' => 'sometimes|nullable|date_format:Y',
            'tags' => 'sometimes|nullable|string',
            'cover_image' => [
                'sometimes',
                'nullable',
                new ImageValidationRule,
            ],
            'additional_images' => 'sometimes|array',
            'additional_images.*' => File::image()
                ->max('50mb')
                ->dimensions(Rule::dimensions()->maxWidth(config('app.imagick.max_width'))->maxHeight(config('app.imagick.max_height'))),
            'is_highlighted' => 'sometimes|accepted',
        ]);

        $creation = Creation::findOrFail($id);
        $slug = Str::slug($request->input('slug'));

        if (Creation::where('slug', $slug)->where('id', '!=', $id)->exists()) {
            return redirect()->route('admin.creations.edit', [
                'creation' => $creation->id,
                'lang' => $request->input('lang'),
            ])
                ->withInput()
                ->with('error', 'Un élément avec ce slug existe déjà.');
        }

        $shortDescription = ! empty($request->input('short_description')) ? $request->input('short_description') : '';
        $description = ! empty($request->input('description')) ? $request->input('description') : '';

        $nameTranslationKeyId = $creation->nameTranslationKey->id;
        $shortDescriptionTranslationKeyId = $creation->shortDescriptionTranslationKey->id;
        $descriptionTranslationKeyId = $creation->descriptionTranslationKey->id;

        Translation::updateOrCreate([
            'translation_key_id' => $nameTranslationKeyId,
            'locale' => $request->input('lang'),
        ], [
            'text' => $request->input('name'),
        ]);

        Translation::updateOrCreate([
            'translation_key_id' => $shortDescriptionTranslationKeyId,
            'locale' => $request->input('lang'),
        ], [
            'text' => $shortDescription,
        ]);

        Translation::updateOrCreate([
            'translation_key_id' => $descriptionTranslationKeyId,
            'locale' => $request->input('lang'),
        ], [
            'text' => $description,
        ]);

        if ($request->hasFile('cover_image')) {
            try {
                $coverUploadedPicture = $this->uploadedFilesService->storeAndOptimizeUploadedPicture($request->file('cover_image'));
            } catch (Exception $e) {
                Log::error('Error while storing uploaded picture', [
                    'exception' => $e,
                ]);

                return redirect()->route('admin.creations.edit', [
                    'creation' => $creation->id,
                    'lang' => $request->input('lang'),
                ])
                    ->withInput()
                    ->with('error', 'Une erreur est survenue lors de l\'enregistrement de l\'image.');
            }

            $creation->coverUploadedPicture()->associate($coverUploadedPicture);
        }

        if ($request->hasFile('additional_images')) {
            $additionalUploadedPictures = [];

            foreach ($request->file('additional_images') as $additionalImage) {
                try {
                    $additionalUploadedPictures[] = $this->uploadedFilesService->storeAndOptimizeUploadedPicture($additionalImage);
                } catch (Exception $e) {
                    Log::error('Error while storing uploaded picture', [
                        'exception' => $e,
                    ]);

                    return redirect()->route('admin.creations.edit', [
                        'creation' => $creation->id,
                        'lang' => $request->input('lang'),
                    ])
                        ->withInput()
                        ->with('error', 'Une erreur est survenue lors de l\'enregistrement de l\'image.');
                }
            }

            $creation->creationPictures()->attach($additionalUploadedPictures);
        }

        $creation->slug = $slug;
        $creation->category_id = $request->input('category_id');
        $creation->completion_date_start = $request->input('completion_date_start');
        $creation->completion_date_end = $request->input('completion_date_end');
        $creation->tags = $request->input('tags');
        $creation->is_highlighted = $request->boolean('is_highlighted', false);
        $creation->save();

        return redirect()->route('admin.creations.edit', [
            'creation' => $creation->id,
            'lang' => $request->input('lang')])
            ->with('success', 'Création mise à jour avec succès.');
    }

    public function delete(int $id): RedirectResponse
    {
        $creation = Creation::findOrFail($id);
        $creation->delete();

        return redirect()->route('admin.creations.index')
            ->with('success', 'Création supprimée avec succès.');
    }

    public function removeAdditionalImage(int $creationId, int $uploadedPictureId): JsonResponse
    {
        $creation = Creation::findOrFail($creationId);
        $creation->creationPictures()->detach($uploadedPictureId);

        return response()->json([
            'success' => true,
        ]);
    }

    public function translateWithAi(int $creationId): JsonResponse
    {
        $creation = Creation::findOrFail($creationId);
        $job = new TranslateCreationJob($creation);
        dispatch($job);

        return response()->json([
            'success' => true,
        ]);
    }
}