<?php
/**
 * Product Version Model
 *
 * @package Jeremias\WcLicensedProduct\Product
 */

declare(strict_types=1);

namespace Jeremias\WcLicensedProduct\Product;

/**
 * Product version entity model
 */
class ProductVersion
{
    private int $id;
    private int $productId;
    private string $version;
    private int $majorVersion;
    private int $minorVersion;
    private int $patchVersion;
    private ?string $releaseNotes;
    private ?string $downloadUrl;
    private ?int $attachmentId;
    private ?string $fileHash;
    private int $downloadCount;
    private bool $isActive;
    private \DateTimeInterface $releasedAt;
    private \DateTimeInterface $createdAt;

    /**
     * Create version from database row
     */
    public static function fromArray(array $data): self
    {
        $version = new self();
        $version->id = (int) $data['id'];
        $version->productId = (int) $data['product_id'];
        $version->version = $data['version'];
        $version->majorVersion = (int) $data['major_version'];
        $version->minorVersion = (int) $data['minor_version'];
        $version->patchVersion = (int) $data['patch_version'];
        $version->releaseNotes = $data['release_notes'] ?: null;
        $version->downloadUrl = $data['download_url'] ?: null;
        $version->attachmentId = !empty($data['attachment_id']) ? (int) $data['attachment_id'] : null;
        $version->fileHash = $data['file_hash'] ?? null;
        $version->downloadCount = (int) ($data['download_count'] ?? 0);
        $version->isActive = (bool) $data['is_active'];
        $version->releasedAt = new \DateTimeImmutable($data['released_at']);
        $version->createdAt = new \DateTimeImmutable($data['created_at']);

        return $version;
    }

    /**
     * Parse version string into components
     */
    public static function parseVersion(string $versionString): array
    {
        $parts = explode('.', $versionString);
        return [
            'major' => (int) ($parts[0] ?? 0),
            'minor' => (int) ($parts[1] ?? 0),
            'patch' => (int) ($parts[2] ?? 0),
        ];
    }

    /**
     * Extract version from filename
     *
     * Supports patterns like:
     * - product-name-v1.2.3.zip
     * - product-name-1.2.3.zip
     * - product_v1.2.3.zip
     * - v1.2.3.zip
     */
    public static function extractVersionFromFilename(string $filename): ?string
    {
        // Remove extension
        $basename = pathinfo($filename, PATHINFO_FILENAME);

        // Try various patterns
        $patterns = [
            '/[_-]v?(\d+\.\d+\.\d+)$/i',      // ends with -v1.2.3 or -1.2.3
            '/[_-]v?(\d+\.\d+\.\d+)[_-]/i',   // contains -v1.2.3- or -1.2.3-
            '/^v?(\d+\.\d+\.\d+)$/i',          // just version number
        ];

        foreach ($patterns as $pattern) {
            if (preg_match($pattern, $basename, $matches)) {
                return $matches[1];
            }
        }

        return null;
    }

    public function getId(): int
    {
        return $this->id;
    }

    public function getProductId(): int
    {
        return $this->productId;
    }

    public function getVersion(): string
    {
        return $this->version;
    }

    public function getMajorVersion(): int
    {
        return $this->majorVersion;
    }

    public function getMinorVersion(): int
    {
        return $this->minorVersion;
    }

    public function getPatchVersion(): int
    {
        return $this->patchVersion;
    }

    public function getReleaseNotes(): ?string
    {
        return $this->releaseNotes;
    }

    public function getDownloadUrl(): ?string
    {
        return $this->downloadUrl;
    }

    public function getAttachmentId(): ?int
    {
        return $this->attachmentId;
    }

    public function getFileHash(): ?string
    {
        return $this->fileHash;
    }

    public function getDownloadCount(): int
    {
        return $this->downloadCount;
    }

    /**
     * Get the download URL from attachment
     */
    public function getEffectiveDownloadUrl(): ?string
    {
        if ($this->attachmentId) {
            return wp_get_attachment_url($this->attachmentId) ?: null;
        }
        return null;
    }

    /**
     * Get the filename for download
     */
    public function getDownloadFilename(): ?string
    {
        if ($this->attachmentId) {
            return wp_basename(get_attached_file($this->attachmentId) ?: '');
        }
        return null;
    }

    public function isActive(): bool
    {
        return $this->isActive;
    }

    public function getReleasedAt(): \DateTimeInterface
    {
        return $this->releasedAt;
    }

    public function getCreatedAt(): \DateTimeInterface
    {
        return $this->createdAt;
    }

    /**
     * Convert to array
     */
    public function toArray(): array
    {
        return [
            'id' => $this->id,
            'product_id' => $this->productId,
            'version' => $this->version,
            'major_version' => $this->majorVersion,
            'minor_version' => $this->minorVersion,
            'patch_version' => $this->patchVersion,
            'release_notes' => $this->releaseNotes,
            'download_url' => $this->downloadUrl,
            'attachment_id' => $this->attachmentId,
            'file_hash' => $this->fileHash,
            'download_count' => $this->downloadCount,
            'is_active' => $this->isActive,
            'released_at' => $this->releasedAt->format('Y-m-d H:i:s'),
            'created_at' => $this->createdAt->format('Y-m-d H:i:s'),
        ];
    }
}
