<?php

declare(strict_types=1);

namespace App\Framework\Mail;

use App\Framework\Core\ValueObjects\Byte;
use App\Framework\Filesystem\Storage;
use App\Framework\Http\MimeType;

final readonly class Attachment
{
    private function __construct(
        public string $content,
        public string $name,
        public MimeType $mimeType,
        public bool $isInline = false,
        public ?string $contentId = null,
    ) {
    }

    public static function fromFile(Storage $storage, string $filePath, ?string $name = null, ?MimeType $mimeType = null): self
    {
        if (! $storage->exists($filePath)) {
            throw new \InvalidArgumentException("File not found: {$filePath}");
        }

        if (! $storage->isReadable($filePath)) {
            throw new \InvalidArgumentException("File not readable: {$filePath}");
        }

        $content = $storage->get($filePath);
        $name ??= basename($filePath);

        // Try to determine mime type from file extension if not provided
        if ($mimeType === null) {
            $detectedMimeType = MimeType::fromFilePath($filePath);
            $mimeType = $detectedMimeType ?? MimeType::APPLICATION_OCTET_STREAM;
        }

        return new self(
            content: $content,
            name: $name,
            mimeType: $mimeType,
        );
    }

    public static function fromData(string $data, string $name, MimeType $mimeType = MimeType::APPLICATION_OCTET_STREAM): self
    {
        return new self(
            content: $data,
            name: $name,
            mimeType: $mimeType,
        );
    }

    public static function inline(string $content, string $contentId, MimeType $mimeType): self
    {
        return new self(
            content: $content,
            name: $contentId,
            mimeType: $mimeType,
            isInline: true,
            contentId: $contentId,
        );
    }

    public function getBase64Content(): string
    {
        return base64_encode($this->content);
    }

    public function getSize(): Byte
    {
        return Byte::fromBytes(strlen($this->content));
    }

    public function getSizeFormatted(): string
    {
        return $this->getSize()->toHumanReadable();
    }

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

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

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

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