<?php

namespace App\Game\Service;

use App\Game\Entity\Game;
use App\Game\Entity\Player;
use App\Game\Entity\SessionSetting;
use App\Game\Enum\SessionSettingType;
use App\Game\Enum\SessionStatus;
use App\Game\Repository\PlayerRepository;
use App\Game\Repository\SessionSettingRepository;
use App\Tech\Entity\User;
use Doctrine\ORM\EntityManagerInterface;

class PlayerService
{
    public function __construct(
        private PlayerRepository $playerRepository,
        private SessionSettingRepository $sessionSettingRepository,
        private EntityManagerInterface $entityManager,
    ) {
    }

    public function GetCurrentlyActiveAsPlayer(User $user): ?Player
    {
        $player = $this->playerRepository->createQueryBuilder('p')
            ->join('p.session', 's')
            ->where('p.user = :user')
            ->andWhere('s.status IN (:statuses)')
            ->setParameter('user', $user)
            ->setParameter('statuses', [
                SessionStatus::READY,
                SessionStatus::PLAYING,
            ])
            ->setMaxResults(1)
            ->getQuery()
            ->getOneOrNullResult();

        return $player;
    }

    public function getCurrentPwdOfPlayer(Player $player) : ?string {
        $settingName = SessionSettingType::tryFrom('PwdForPlayer' . $player->getScreen());

        if (!$settingName) {
            return null;
        }

        $setting = $this->sessionSettingRepository->getSetting($player->getSession(), $settingName, $player);
        return $setting?->getValue();
    }

    public function saveCurrentPwdOfPlayer(Player $player, string $newLocation)
    {
        $settingName = SessionSettingType::tryFrom('PwdForPlayer' . $player->getScreen());

        if (!$settingName) {
            return;
        }

        $setting = $this->sessionSettingRepository->getSetting($player->getSession(), $settingName, $player);
        $setting->setValue($newLocation);

        $this->entityManager->persist($setting);
        $this->entityManager->flush();
    }

    public function getDeletedFilesOfSession(Player $player): array
    {
        $setting = $this->sessionSettingRepository->getSetting($player->getSession(), SessionSettingType::SET_OF_DELETED_FILES);
        if (!$setting || !$setting->getValue()) {
            return [];
        }

        return json_decode($setting->getValue(), true) ?? [];
    }

    public function addDeletedFileToSession(Player $player, string $filename): void
    {
        $setting = $this->sessionSettingRepository->getSetting($player->getSession(), SessionSettingType::SET_OF_DELETED_FILES);
        if (!$setting) {
            $setting = new SessionSetting();
            $setting->setSession($player->getSession());
            $setting->setName(SessionSettingType::SET_OF_DELETED_FILES);
        }

        $deletedFiles = json_decode($setting->getValue() ?? '[]', true) ?? [];
        if (!in_array($filename, $deletedFiles)) {
            $deletedFiles[] = $filename;
            $setting->setValue(json_encode($deletedFiles));

            $this->entityManager->persist($setting);
            $this->entityManager->flush();
        }
    }

    public function removeDeletedFileFromSession(Player $player, string $filename): void
    {
        $setting = $this->sessionSettingRepository->getSetting($player->getSession(), SessionSettingType::SET_OF_DELETED_FILES);
        if (!$setting || !$setting->getValue()) {
            return;
        }

        $deletedFiles = json_decode($setting->getValue(), true) ?? [];
        $newDeletedFiles = array_values(array_diff($deletedFiles, [$filename]));

        if (count($newDeletedFiles) !== count($deletedFiles)) {
            $setting->setValue(json_encode($newDeletedFiles));
            $this->entityManager->persist($setting);
            $this->entityManager->flush();
        }
    }
}
