<?php

declare(strict_types=1);

namespace App\Domain\SmartLink\Entities;

use App\Domain\SmartLink\Enums\LinkStatus;
use App\Domain\SmartLink\Enums\LinkType;
use App\Domain\SmartLink\ValueObjects\LinkSettings;
use App\Domain\SmartLink\ValueObjects\LinkTitle;
use App\Domain\SmartLink\ValueObjects\ShortCode;
use App\Domain\SmartLink\ValueObjects\SmartLinkId;
use App\Framework\Core\ValueObjects\Timestamp;
use App\Framework\DateTime\Clock;

final readonly class SmartLink
{
    public function __construct(
        public SmartLinkId $id,
        public ShortCode $shortCode,
        public LinkType $type,
        public LinkTitle $title,
        public ?string $coverImageUrl,
        public LinkStatus $status,
        public ?string $userId,
        public LinkSettings $settings,
        public Timestamp $createdAt,
        public Timestamp $updatedAt
    ) {
    }

    public static function create(
        Clock $clock,
        ShortCode $shortCode,
        LinkType $type,
        LinkTitle $title,
        ?string $userId = null,
        ?string $coverImageUrl = null
    ): self {
        return new self(
            id: SmartLinkId::generate($clock),
            shortCode: $shortCode,
            type: $type,
            title: $title,
            coverImageUrl: $coverImageUrl,
            status: LinkStatus::DRAFT,
            userId: $userId,
            settings: LinkSettings::default(),
            createdAt: Timestamp::now(),
            updatedAt: Timestamp::now()
        );
    }

    public function withStatus(LinkStatus $status): self
    {
        if (! $this->status->canTransitionTo($status)) {
            throw new \DomainException(
                sprintf('Cannot transition from %s to %s', $this->status->value, $status->value)
            );
        }

        return new self(
            id: $this->id,
            shortCode: $this->shortCode,
            type: $this->type,
            title: $this->title,
            coverImageUrl: $this->coverImageUrl,
            status: $status,
            userId: $this->userId,
            settings: $this->settings,
            createdAt: $this->createdAt,
            updatedAt: Timestamp::now()
        );
    }

    public function withTitle(LinkTitle $title): self
    {
        return new self(
            id: $this->id,
            shortCode: $this->shortCode,
            type: $this->type,
            title: $title,
            coverImageUrl: $this->coverImageUrl,
            status: $this->status,
            userId: $this->userId,
            settings: $this->settings,
            createdAt: $this->createdAt,
            updatedAt: Timestamp::now()
        );
    }

    public function withSettings(LinkSettings $settings): self
    {
        return new self(
            id: $this->id,
            shortCode: $this->shortCode,
            type: $this->type,
            title: $this->title,
            coverImageUrl: $this->coverImageUrl,
            status: $this->status,
            userId: $this->userId,
            settings: $settings,
            createdAt: $this->createdAt,
            updatedAt: Timestamp::now()
        );
    }

    public function isActive(): bool
    {
        return $this->status === LinkStatus::ACTIVE;
    }

    public function canBeAccessed(): bool
    {
        return $this->status->isPublic();
    }

    public function isOwnedBy(?string $userId): bool
    {
        return $this->userId === $userId;
    }
}
