<?php

namespace App\Actions\Games;

use App\Models\Game;
use App\Models\PlayerGameCharacter;
use App\Models\PlayerGamePlatform;
use App\Models\PlayerGameProfile;
use App\Models\PlayerGameRole;
use App\Models\PlayerProfile;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\ValidationException;

class CreatePlayerGameProfileAction
{
    use ValidatesGameCatalogSelections;

    public function execute(PlayerProfile $playerProfile, Game $game, array $data): PlayerGameProfile
    {
        $this->validateGameCatalogSelections($game, $data);

        if ($playerProfile->playerGameProfiles()->where('game_id', $game->id)->exists()) {
            throw ValidationException::withMessages([
                'game_id' => __('validation.duplicate_game_profile'),
            ]);
        }

        return DB::transaction(function () use ($playerProfile, $game, $data) {
            if ($data['is_primary_game'] ?? false) {
                $playerProfile->playerGameProfiles()->update(['is_primary_game' => false]);
            }

            $profile = $playerProfile->playerGameProfiles()->create([
                'game_id' => $game->id,
                'in_game_name' => $data['in_game_name'],
                'external_game_id' => $data['external_game_id'] ?? null,
                'current_rank_id' => $data['current_rank_id'] ?? null,
                'highest_rank_id' => $data['highest_rank_id'] ?? null,
                'primary_platform_id' => $data['primary_platform_id'] ?? null,
                'region_id' => $data['region_id'] ?? null,
                'server_id' => $data['server_id'] ?? null,
                'years_of_experience' => $data['years_of_experience'] ?? null,
                'skill_level' => $data['skill_level'] ?? null,
                'biography' => $data['biography'] ?? null,
                'is_primary_game' => (bool) ($data['is_primary_game'] ?? false),
                'is_public' => (bool) ($data['is_public'] ?? true),
            ]);

            $this->syncRelations($profile, $data);

            return $profile->fresh([
                'game',
                'currentRank',
                'highestRank',
                'primaryPlatform',
                'region',
                'server',
                'gameRoles.gameRole',
                'gameCharacters.gameCharacter',
                'gamePlatforms.gamePlatform',
            ]);
        });
    }

    private function syncRelations(PlayerGameProfile $profile, array $data): void
    {
        $this->syncRoles($profile, $data['role_ids'] ?? [], $data['primary_role_id'] ?? null);
        $this->syncCharacters($profile, $data['character_ids'] ?? []);
        $this->syncPlatforms($profile, $data['platform_ids'] ?? []);
    }

    private function syncRoles(PlayerGameProfile $profile, array $roleIds, ?int $primaryRoleId): void
    {
        $profile->gameRoles()->delete();

        foreach (collect($roleIds)->filter()->unique() as $roleId) {
            PlayerGameRole::create([
                'player_game_profile_id' => $profile->id,
                'game_role_id' => $roleId,
                'is_primary' => (int) $roleId === (int) $primaryRoleId,
            ]);
        }
    }

    private function syncCharacters(PlayerGameProfile $profile, array $characterIds): void
    {
        $profile->gameCharacters()->delete();

        foreach (collect($characterIds)->filter()->unique()->values() as $index => $characterId) {
            PlayerGameCharacter::create([
                'player_game_profile_id' => $profile->id,
                'game_character_id' => $characterId,
                'sort_order' => $index + 1,
            ]);
        }
    }

    private function syncPlatforms(PlayerGameProfile $profile, array $platformIds): void
    {
        $profile->gamePlatforms()->delete();

        foreach (collect($platformIds)->filter()->unique() as $platformId) {
            PlayerGamePlatform::create([
                'player_game_profile_id' => $profile->id,
                'game_platform_id' => $platformId,
            ]);
        }
    }
}
