<?php

namespace DMD\LaLigaApi\Dto;

use DMD\LaLigaApi\Entity\Game;

class GameDto
{
    public int $id;
    public TeamDto $homeTeamDto;
    public TeamDto $awayTeamDto;
    public \DateTime $plannedDate;
    public \DateTime $gameDateTime;
    public string $notes;
    public array $fileDtoList;
    public SeasonDto $seasonDto;
    public FacilityDto $facilityDto;
    public int $pointsHome;
    public int $pointsAway;
    public \DateTimeImmutable $createdAt;
    public \DateTimeImmutable $updatedAt;
    public array $validationErrors;

    public function toArray(): array
    {
        $cleanResponseArray = [];
        $responseArray = [
            'id' => $this->id ?? null,
            'homeTeam' => $this->homeTeamDto->toArray() ?? [],
            'awayTeam' => $this->awayTeamDto->toArray() ?? [],
            'plannedDate' => !empty($this->plannedDate) ? $this->plannedDate->format('Y-m-d H:i:s') : null,
            'gameDateTime' => !empty($this->gameDateTime) ? $this->gameDateTime->format('Y-m-d H:i:s') : null,
            'season' => $this->seasonDto->createSeasonArray() ?? [],
            'notes' => $this->notes ?? null,
            'facility' => $this->facilityDto->toArray() ?? [],
            'pointsHome' => $this->pointsHome ?? 0,
            'pointsAway' => $this->pointsAway ?? 0,
            'createdAt' => !empty($this->createdAt) ? $this->createdAt->format('Y-m-d H:i:s') : null,
            'updatedAt' => !empty($this->updatedAt) ? $this->updatedAt->format('Y-m-d H:i:s') : null
        ];
        foreach ($responseArray as $key => $value)
        {
            if ($value !== null)
            {
                $cleanResponseArray[$key] = $value;
            }
        }
        return $cleanResponseArray;
    }

    public function fillFromArray(array $dataList): void
    {
        if (!empty($dataList['id']))
        {
            $this->id = $dataList['id'];
        }
        if (!empty($dataList['plannedDate']))
        {
            $this->plannedDate = new \DateTime($dataList['plannedDate']);
        }
        if (!empty($dataList['gameDateTime']))
        {
            $this->gameDateTime = new \DateTime($dataList['gameDateTime']);
        }
        if (!empty($dataList['notes']))
        {
            $this->notes = $dataList['notes'];
        }
        if (!empty($dataList['pointsHome']))
        {
            $this->pointsHome = $dataList['pointsHome'];
        }
        if (!empty($dataList['pointsAway']))
        {
            $this->pointsAway = $dataList['pointsAway'];
        }
        if (!empty($dataList['createdAt']))
        {
            $this->createdAt = new \DateTimeImmutable($dataList['createdAt'], new \DateTimeZone('Europe/Madrid'));
        }
        if (!empty($dataList['updatedAt']))
        {
            $this->updatedAt = new \DateTimeImmutable($dataList['updatedAt'], new \DateTimeZone('Europe/Madrid'));
        }
    }

    public function fillFromObject(Game $gameEntity): void
    {
        if ($gameEntity->getId() !== null)
        {
            $this->id = $gameEntity->getId();
        }
        if ($gameEntity->getSeason() !== null)
        {
            $seasonDto = new SeasonDto();
            $seasonDto->fillFromObject($gameEntity->getSeason());
            $this->seasonDto = $seasonDto;
        }
        if ($gameEntity->getFacility() !== null)
        {
            $facilityDto = new FacilityDto();
            $facilityDto->fillFromObject($gameEntity->getFacility());
            $this->facilityDto = $facilityDto;
        }
        if ($gameEntity->getHomeTeam() !== null)
        {
            $teamDto = new TeamDto();
            $teamDto->fillFromObject($gameEntity->getHomeTeam());
            $this->homeTeamDto = $teamDto;
        }
        if ($gameEntity->getAwayTeam() !== null)
        {
            $teamDto = new TeamDto();
            $teamDto->fillFromObject($gameEntity->getAwayTeam());
            $this->awayTeamDto = $teamDto;
        }
        if ($gameEntity->getFiles() !== null)
        {
            $fileIterator = $gameEntity->getFiles()->getIterator();
            foreach ($fileIterator as $fileEntity)
            {
                $fileDto = new FileDto();
                $fileDto->fillFromObject($fileEntity);
                $this->fileDtoList[] = $fileDto;
            }
        }
        if ($gameEntity->getGameDateTime() !== null)
        {
            $this->gameDateTime = new \DateTime($gameEntity->getGameDateTime()->format('Y-m-d H:i:s'));
        }
        if ($gameEntity->getCreatedAt() !== null)
        {
            $this->createdAt = $gameEntity->getCreatedAt();
        }
        if ($gameEntity->getUpdatedAt() !== null)
        {
            $this->createdAt = $gameEntity->getUpdatedAt();
        }
        if ($gameEntity->getPlannedDate() !== null)
        {
            $this->plannedDate = new \DateTime($gameEntity->getPlannedDate()->format('Y-m-d H:i:s'));
        }
        if ($gameEntity->getNotes() !== null)
        {
            $this->notes = $gameEntity->getNotes();
        }
        if ($gameEntity->getNotes() !== null)
        {
            $this->notes = $gameEntity->getNotes();
        }
        if ($gameEntity->getPointsAway() !== null)
        {
            $this->pointsAway = $gameEntity->getPointsAway();
        }
        if ($gameEntity->getPointsHome() !== null)
        {
            $this->pointsAway = $gameEntity->getPointsHome();
        }
    }

    public function validate(): void
    {
        if (empty($this->name))
        {
            $this->validationErrors[] = 'El nombre no puede estar vacío.';
        }
        if (
            empty($this->pointsPerWin)
        )
        {
            $this->validationErrors[] = 'Los puntos por partido ganado no pueden estar vacíos.';
        }
        if (
            isset($this->pointsPerDraw, $this->pointsPerWin, $this->pointsPerLoss) &&
            (($this->pointsPerWin <= $this->pointsPerDraw) ||
            ($this->pointsPerWin <= $this->pointsPerLoss))
        )
        {
            $this->validationErrors[] = 'Los puntos por partido ganado deben ser superiores a los puntos por empate y por perdida.';
        }
        if (($this->pointsPerDraw > $this->pointsPerWin))
        {
            $this->validationErrors[] = 'Los puntos por empate deben ser inferiores a los puntos por partido ganado.';
        }
        if (($this->pointsPerDraw < $this->pointsPerLoss))
        {
            $this->validationErrors[] = 'Los puntos por empate deben ser superiores a los puntos por partido perdido.';
        }
        if ($this->pointsPerWin + $this->pointsPerDraw + $this->pointsPerLoss > 20)
        {
            $this->validationErrors[] = 'La suma de los puntos por partidos ganados, perdidos y empatados no puede ser superior a 20.';
        }
    }
}