<?php

namespace Opentalent\OtAdmin\Domain\Entity;

/**
 * Status of a website as returned by SiteController->getSiteStatusAction()
 */
class SiteStatus
{
    // Websites statuses
    const STATUS_UNKNOWN = 0;
    const STATUS_NO_SUCH_WEBSITE = -1;
    const STATUS_EXISTING = 5;
    const STATUS_EXISTING_DELETED = 2;
    const STATUS_EXISTING_HIDDEN = 3;
    const STATUS_EXISTING_WITH_WARNINGS = 4;
    const STATUS_EXISTING_WITH_CRITICAL_ERRORS = 1;

    const STATUSES = [
        self::STATUS_UNKNOWN => 'Unknown',
        self::STATUS_NO_SUCH_WEBSITE => 'Does not exist',
        self::STATUS_EXISTING => 'Existing',
        self::STATUS_EXISTING_DELETED => 'Existing, deleted',
        self::STATUS_EXISTING_HIDDEN => 'Existing, hidden',
        self::STATUS_EXISTING_WITH_WARNINGS => 'Existing with warnings',
        self::STATUS_EXISTING_WITH_CRITICAL_ERRORS => 'Existing with critical error(s)',
    ];

    /**
     * Id of the organization owning the website
     * @var int
     */
    protected int $organizationId;

    /**
     * Status-code of the website
     * @var int
     */
    protected int $statusCode = self::STATUS_UNKNOWN;

    /**
     * SiteInfos of the website
     *
     * @var SiteInfos | null
     */
    protected ?SiteInfos $siteInfos = null;

    /**
     * Optional list of warnings
     *
     * @var array|null
     */
    protected ?array $warnings = null;

    public function __construct(
        int $organizationId,
        int $statusCode = null,
        ?SiteInfos $siteInfos = null,
        ?array $warnings = null
    )
    {
        $this->organizationId = $organizationId;
        if ($statusCode !== null) {
            $this->setStatusCode($statusCode);
        }
        if ($siteInfos !== null) {
            $this->setSiteInfos($siteInfos);
        }
        if ($warnings !== null) {
            $this->setWarnings($warnings);
        }
    }

    /**
     * Return the site status as a serializable array
     *
     * @return array
     */
    public function toArray(): array
    {
        $infos = [
            "Organization Id" => $this->getOrganizationId(),
            "Status" => $this->getStatusLabel(),
            "Message" => $this->getMessage()
        ];

        if ($this->getStatusCode() > 0 && $this->getSiteInfos()) {
            $infos["Root Uid"] = $this->getSiteInfos()->getRootUid();
            $infos["Site's title"] = $this->getSiteInfos()->getSiteTitle();
            $infos["Base Url"] = $this->getSiteInfos()->getBaseUrl();
            $infos["Deleted"] = (int)$this->getSiteInfos()->isDeleted();
            $infos["Hidden or restricted"] = (int)$this->getSiteInfos()->isHiddenOrRestricted();
            $infos["Premium"] = (int)$this->getSiteInfos()->isPremium();
            $infos["Template"] = $this->getSiteInfos()->getTemplate();
            $infos["Preferences"] = $this->getSiteInfos()->getPreferences();
            $infos["Matomo id"] = $this->getSiteInfos()->getMatomoId() ?? "-";
            $infos["Mounted for user(s): "] = $this->getSiteInfos()->getMountedForBeUsers();
            $infos["Mounted for group(s): "] = $this->getSiteInfos()->getMountedForBeGroups();

            if ($this->useWarnings()) {
                $infos["Warnings"] = $this->getWarnings();
            }
        }
        return $infos;
    }

    /**
     * @return int
     */
    public function getOrganizationId(): int
    {
        return $this->organizationId;
    }

    /**
     * @return int
     */
    public function getStatusCode(): int
    {
        return $this->statusCode;
    }

    /**
     * @return string
     */
    public function getStatusLabel(): string
    {
        return self::STATUSES[$this->statusCode];
    }

    /**
     * @return string
     */
    public function getMessage(): string
    {
        if($this->getStatusCode() == self::STATUS_NO_SUCH_WEBSITE) {
            return 'No website were found for organization ' . $this->getOrganizationId();
        }
        elseif ($this->getStatusCode() == self::STATUS_EXISTING) {
            return 'A website exists for organization ' . $this->getOrganizationId();
        }
        elseif ($this->getStatusCode() == self::STATUS_EXISTING_DELETED) {
            return 'A website exists for organization ' . $this->getOrganizationId() . ', but has been deleted';
        }
        elseif ($this->getStatusCode() == self::STATUS_EXISTING_HIDDEN) {
            return 'A website exists for organization ' . $this->getOrganizationId() . ', but is hidden or has a restricted access';
        } elseif ($this->getStatusCode() == self::STATUS_EXISTING_WITH_WARNINGS) {
            return 'A website exists for organization ' . $this->getOrganizationId() . ', but warnings were raised';
        }

        return 'Unknown status';
    }

    /**
     * @param int $statusCode
     */
    public function setStatusCode(int $statusCode): void
    {
        if (!isset(self::STATUSES[$statusCode])) {
            throw new \InvalidArgumentException('Invalid status code : ' . $statusCode);
        }
        $this->statusCode = $statusCode;
    }

    /**
     * @return SiteInfos|null
     */
    public function getSiteInfos(): SiteInfos | null
    {
        return $this->siteInfos;
    }

    /**
     * @param SiteInfos $siteInfos
     */
    public function setSiteInfos(SiteInfos $siteInfos): void
    {
        $this->siteInfos = $siteInfos;
    }

    /**
     * @return array|null
     */
    public function getWarnings(): ?array
    {
        return $this->warnings;
    }

    /**
     * @param array $warnings
     */
    public function setWarnings(array $warnings): void
    {
        $this->warnings = $warnings;
    }

    /**
     * Warnings have been scanned (the warnings array still can be empty)
     */
    public function useWarnings(): bool
    {
        return $this->warnings !== null;
    }

    /**
     * Warnings have been logged
     */
    public function hasWarnings(): bool
    {
        return count($this->warnings) > 0;
    }

    /**
     * @param string $warning
     */
    public function addWarnings(string $warning): void
    {
        $this->warnings[] = $warning;
    }
}
