<?php

namespace _121Digital\Connect\Network\Models;

use InvalidArgumentException;

class SiteDTO
{
    public ?int $siteId = null;

    public ?string $siteName = null;

    public ?string $domain = null;

    public ?string $path = null;

    public ?string $adminEmail = null;

    public ?string $siteDescription = null;

    public ?string $language = null;

    public ?string $visibility = null; // blog_public: '1', '0', '-1', '-2'

    public ?bool $archived = null;

    public ?bool $spam = null;

    public ?bool $deleted = null;

    public ?bool $mature = null;

    public ?string $registered = null;

    public ?string $lastUpdated = null;

    public function __construct(
        ?int $siteId = null,
        ?string $siteName = null,
        ?string $domain = null,
        ?string $path = null,
        ?string $adminEmail = null,
        ?string $siteDescription = null,
        ?string $language = null,
        ?string $visibility = null,
        ?bool $archived = null,
        ?bool $spam = null,
        ?bool $deleted = null,
        ?bool $mature = null,
        ?string $registered = null,
        ?string $lastUpdated = null
    ) {
        if ($siteId !== null) {
            $this->validateAndSetSiteId($siteId);
        }
        if ($siteName !== null) {
            $this->validateAndSetSiteName($siteName);
        }
        if ($domain !== null) {
            $this->validateAndSetDomain($domain);
        }
        if ($path !== null) {
            $this->validateAndSetPath($path);
        }
        if ($adminEmail !== null) {
            $this->validateAndSetAdminEmail($adminEmail);
        }
        if ($siteDescription !== null) {
            $this->siteDescription = $siteDescription;
        }
        if ($language !== null) {
            $this->language = $language;
        }
        if ($visibility !== null) {
            $this->visibility = $visibility;
        }
        if ($archived !== null) {
            $this->archived = $archived;
        }
        if ($spam !== null) {
            $this->spam = $spam;
        }
        if ($deleted !== null) {
            $this->deleted = $deleted;
        }
        if ($mature !== null) {
            $this->mature = $mature;
        }
        if ($registered !== null) {
            $this->registered = $registered;
        }
        if ($lastUpdated !== null) {
            $this->lastUpdated = $lastUpdated;
        }
    }

    // Factory methods for common creation scenarios
    public static function fromArray(array $data): self
    {
        $dto = new self();

        if (isset($data['site_id']) || isset($data['siteId'])) {
            $dto->setSiteId($data['site_id'] ?? $data['siteId']);
        }
        if (isset($data['site_name']) || isset($data['siteName'])) {
            $dto->setSiteName($data['site_name'] ?? $data['siteName']);
        }
        if (isset($data['domain'])) {
            $dto->setDomain($data['domain']);
        }
        if (isset($data['path'])) {
            $dto->setPath($data['path']);
        }
        if (isset($data['admin_email']) || isset($data['adminEmail'])) {
            $dto->setAdminEmail($data['admin_email'] ?? $data['adminEmail']);
        }
        if (isset($data['site_description']) || isset($data['siteDescription'])) {
            $dto->siteDescription = $data['site_description'] ?? $data['siteDescription'];
        }
        if (isset($data['language'])) {
            $dto->language = $data['language'];
        }
        if (isset($data['visibility'])) {
            $dto->visibility = $data['visibility'];
        }
        if (isset($data['archived'])) {
            $dto->archived = (bool) $data['archived'];
        }
        if (isset($data['spam'])) {
            $dto->spam = (bool) $data['spam'];
        }
        if (isset($data['deleted'])) {
            $dto->deleted = (bool) $data['deleted'];
        }
        if (isset($data['mature'])) {
            $dto->mature = (bool) $data['mature'];
        }
        if (isset($data['registered'])) {
            $dto->registered = $data['registered'];
        }
        if (isset($data['last_updated']) || isset($data['lastUpdated'])) {
            $dto->lastUpdated = $data['last_updated'] ?? $data['lastUpdated'];
        }

        return $dto;
    }

    public static function fromWordPressSite(array $siteData): self
    {
        return new self(
            siteId: (int) $siteData['blog_id'],
            siteName: $siteData['blogname'] ?? '',
            domain: $siteData['domain'] ?? '',
            path: $siteData['path'] ?? '/',
            adminEmail: $siteData['admin_email'] ?? ''
        );
    }

    public static function create(int $siteId, string $siteName, string $domain, string $path = '/', string $adminEmail = ''): self
    {
        return new self(
            siteId: $siteId,
            siteName: $siteName,
            domain: $domain,
            path: $path,
            adminEmail: $adminEmail
        );
    }

    // Validation method to check if DTO is complete
    public function isValid(): bool
    {
        return isset($this->siteId) &&
               isset($this->siteName) &&
               isset($this->domain) &&
               isset($this->path) &&
               isset($this->adminEmail);
    }

    public function validate(): void
    {
        if (!isset($this->siteId)) {
            throw new InvalidArgumentException('Site ID is required');
        }
        if (!isset($this->siteName)) {
            throw new InvalidArgumentException('Site name is required');
        }
        if (!isset($this->domain)) {
            throw new InvalidArgumentException('Domain is required');
        }
        if (!isset($this->path)) {
            throw new InvalidArgumentException('Path is required');
        }
        if (!isset($this->adminEmail)) {
            throw new InvalidArgumentException('Admin email is required');
        }
    }

    public function toArray(): array
    {
        return [
          'site_id' => $this->siteId ?? null,
          'site_name' => $this->siteName ?? null,
          'domain' => $this->domain ?? null,
          'path' => $this->path ?? null,
          'admin_email' => $this->adminEmail ?? null,
          'site_description' => $this->siteDescription ?? null,
          'language' => $this->language ?? null,
          'visibility' => $this->visibility ?? null,
          'archived' => $this->archived ?? null,
          'spam' => $this->spam ?? null,
          'deleted' => $this->deleted ?? null,
          'mature' => $this->mature ?? null,
          'registered' => $this->registered ?? null,
          'last_updated' => $this->lastUpdated ?? null,
        ];
    }

    // Getters
    public function getSiteId(): ?int
    {
        return $this->siteId;
    }

    public function getSiteName(): ?string
    {
        return $this->siteName;
    }

    public function getDomain(): ?string
    {
        return $this->domain;
    }

    public function getPath(): ?string
    {
        return $this->path;
    }

    public function getAdminEmail(): ?string
    {
        return $this->adminEmail;
    }

    public function getSiteDescription(): ?string
    {
        return $this->siteDescription;
    }

    public function getLanguage(): ?string
    {
        return $this->language;
    }

    public function getVisibility(): ?string
    {
        return $this->visibility;
    }

    public function isArchived(): ?bool
    {
        return $this->archived;
    }

    public function isSpam(): ?bool
    {
        return $this->spam;
    }

    public function isDeleted(): ?bool
    {
        return $this->deleted;
    }

    public function isMature(): ?bool
    {
        return $this->mature;
    }

    public function getRegistered(): ?string
    {
        return $this->registered;
    }

    public function getLastUpdated(): ?string
    {
        return $this->lastUpdated;
    }

    // Setters with validation
    public function setSiteId(int $siteId): void
    {
        $this->validateAndSetSiteId($siteId);
    }

    public function setSiteName(string $siteName): void
    {
        $this->validateAndSetSiteName($siteName);
    }

    public function setDomain(string $domain): void
    {
        $this->validateAndSetDomain($domain);
    }

    public function setPath(string $path): void
    {
        $this->validateAndSetPath($path);
    }

    public function setAdminEmail(string $adminEmail): void
    {
        $this->validateAndSetAdminEmail($adminEmail);
    }

    public function setSiteDescription(?string $siteDescription): void
    {
        $this->siteDescription = $siteDescription;
    }

    public function setLanguage(?string $language): void
    {
        $this->language = $language;
    }

    public function setVisibility(?string $visibility): void
    {
        $this->visibility = $visibility;
    }

    public function setArchived(?bool $archived): void
    {
        $this->archived = $archived;
    }

    public function setSpam(?bool $spam): void
    {
        $this->spam = $spam;
    }

    public function setDeleted(?bool $deleted): void
    {
        $this->deleted = $deleted;
    }

    public function setMature(?bool $mature): void
    {
        $this->mature = $mature;
    }

    public function setRegistered(?string $registered): void
    {
        $this->registered = $registered;
    }

    public function setLastUpdated(?string $lastUpdated): void
    {
        $this->lastUpdated = $lastUpdated;
    }

    // Private validation methods
    private function validateAndSetSiteId(int $siteId): void
    {
        if ($siteId <= 0) {
            throw new InvalidArgumentException('Site ID must be a positive integer');
        }
        $this->siteId = $siteId;
    }

    private function validateAndSetSiteName(string $siteName): void
    {
        $trimmedName = trim($siteName);
        if (empty($trimmedName)) {
            throw new InvalidArgumentException('Site name cannot be empty');
        }
        if (strlen($trimmedName) > 255) {
            throw new InvalidArgumentException('Site name cannot exceed 255 characters');
        }
        $this->siteName = $trimmedName;
    }

    private function validateAndSetDomain(string $domain): void
    {
        $trimmedDomain = trim($domain);
        if (empty($trimmedDomain)) {
            throw new InvalidArgumentException('Domain cannot be empty');
        }

        // Basic domain validation
        // if (!preg_match('/^[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/', $trimmedDomain)) {
        //   throw new InvalidArgumentException('Invalid domain format');
        // }

        if (strlen($trimmedDomain) > 253) {
            throw new InvalidArgumentException('Domain cannot exceed 253 characters');
        }

        $this->domain = strtolower($trimmedDomain);
    }

    private function validateAndSetPath(string $path): void
    {
        $trimmedPath = trim($path);
        if (empty($trimmedPath)) {
            $trimmedPath = '/';
        }

        // Ensure path starts with /
        if (!str_starts_with($trimmedPath, '/')) {
            $trimmedPath = '/' . $trimmedPath;
        }

        // Basic path validation - no invalid characters
        if (preg_match('/[<>"|?*]/', $trimmedPath)) {
            throw new InvalidArgumentException('Path contains invalid characters');
        }

        if (strlen($trimmedPath) > 500) {
            throw new InvalidArgumentException('Path cannot exceed 500 characters');
        }

        $this->path = $trimmedPath;
    }

    private function validateAndSetAdminEmail(string $adminEmail): void
    {
        $trimmedEmail = trim($adminEmail);
        if (empty($trimmedEmail)) {
            throw new InvalidArgumentException('Admin email cannot be empty');
        }

        if (!filter_var($trimmedEmail, \FILTER_VALIDATE_EMAIL)) {
            throw new InvalidArgumentException('Invalid email format');
        }

        if (strlen($trimmedEmail) > 320) {
            throw new InvalidArgumentException('Email cannot exceed 320 characters');
        }

        $this->adminEmail = strtolower($trimmedEmail);
    }
}
