<?php

namespace App\Actions\Records;

use App\Enums\ProfileVisibility;
use App\Enums\RecordType;
use App\Models\Game;
use App\Models\GameRank;
use App\Models\PlayerGameProfile;
use App\Models\PlayerRecord;
use App\Models\User;
use App\Services\ContentModerationService;
use App\Services\MediaUploadService;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\DB;
use InvalidArgumentException;

class CreatePlayerRecordAction
{
    public function __construct(
        private MediaUploadService $mediaUpload,
        private ContentModerationService $moderation,
    ) {}

    public function execute(User $user, array $data, array $screenshots = []): PlayerRecord
    {
        return DB::transaction(function () use ($user, $data, $screenshots) {
            $profile = $user->playerProfile;

            if ($profile === null) {
                throw new InvalidArgumentException(__('events.registration.profile_incomplete'));
            }

            $gameProfile = PlayerGameProfile::query()
                ->where('player_profile_id', $profile->id)
                ->whereKey($data['player_game_profile_id'])
                ->firstOrFail();

            if ((int) $gameProfile->game_id !== (int) $data['game_id']) {
                throw new InvalidArgumentException(__('validation.game_option_invalid'));
            }

            $game = Game::query()->findOrFail($data['game_id']);

            if (filled($data['rank_id'] ?? null)) {
                $rankBelongs = GameRank::query()
                    ->whereKey($data['rank_id'])
                    ->where('game_id', $game->id)
                    ->exists();

                if (! $rankBelongs) {
                    throw new InvalidArgumentException(__('validation.game_option_invalid'));
                }
            }

            $moderationStatus = $this->moderation->initialStatus();

            $record = PlayerRecord::query()->create([
                'player_profile_id' => $profile->id,
                'player_game_profile_id' => $gameProfile->id,
                'game_id' => $game->id,
                'title' => $data['title'],
                'description' => $data['description'] ?? null,
                'record_type' => RecordType::from($data['record_type']),
                'achievement_date' => $data['achievement_date'] ?? null,
                'result_text' => $data['result_text'] ?? null,
                'rank_id' => $data['rank_id'] ?? null,
                'visibility' => ProfileVisibility::from($data['visibility'] ?? ProfileVisibility::Public->value),
                'moderation_status' => $moderationStatus,
                'published_at' => $moderationStatus->value === 'approved' ? now() : null,
            ]);

            foreach ($screenshots as $index => $file) {
                if (! $file instanceof UploadedFile) {
                    continue;
                }

                $upload = $this->mediaUpload->uploadImage(
                    $file,
                    'records',
                    'records/'.$profile->id,
                    ['mimes' => ['jpg', 'jpeg', 'png', 'webp'], 'max_kb' => 4096],
                );

                $record->media()->create([
                    'file_path' => $upload['path'],
                    'original_name' => $upload['original_name'],
                    'mime_type' => $upload['mime_type'],
                    'size' => $upload['size'],
                    'checksum' => $upload['checksum'],
                    'sort_order' => $index,
                ]);
            }

            return $record->load(['game', 'media', 'rank']);
        });
    }
}
