<?php
declare(strict_types=1);

namespace FreshCloud\Mail\Compose;

/**
 * Represents one row in PocketBase `email_drafts` table.
 * Per FvW v8 §38 finalized shape (this is the running code; formation §4 was the intent).
 */
class Draft
{
    public string $id = '';
    public string $userId = '';
    public string $accountId = '';
    public string $mode = 'new';
    public ?string $replyToMsgId = null;
    public ?string $forwardOfMsgId = null;
    public array $to = [];
    public array $cc = [];
    public array $bcc = [];
    public string $subject = '';
    public string $bodyHtml = '';
    public string $bodyText = '';
    public array $attachmentIds = [];
    public string $status = 'draft';
    public \DateTimeImmutable $createdAt;
    public \DateTimeImmutable $updatedAt;
    public ?string $lastError = null;

    public function __construct()
    {
        $this->createdAt = new \DateTimeImmutable();
        $this->updatedAt = new \DateTimeImmutable();
    }

    public static function fromArray(array $row): self
    {
        $draft = new self();
        $draft->id = (string) ($row['id'] ?? '');
        $draft->userId = (string) ($row['user_id'] ?? '');
        $draft->accountId = (string) ($row['account_id'] ?? '');
        $draft->mode = (string) ($row['mode'] ?? 'new');
        $draft->replyToMsgId = $row['reply_to_msg_id'] ?? null;
        $draft->forwardOfMsgId = $row['forward_of_msg_id'] ?? null;
        $draft->to = self::decodeJsonArray($row['to_json'] ?? '[]');
        $draft->cc = self::decodeJsonArray($row['cc_json'] ?? '[]');
        $draft->bcc = self::decodeJsonArray($row['bcc_json'] ?? '[]');
        $draft->subject = (string) ($row['subject'] ?? '');
        $draft->bodyHtml = (string) ($row['body_html'] ?? '');
        $draft->bodyText = (string) ($row['body_text'] ?? '');
        $draft->attachmentIds = self::decodeJsonArray($row['attachment_ids_json'] ?? '[]');
        $draft->status = (string) ($row['status'] ?? 'draft');
        $draft->lastError = $row['last_error'] ?? null;
        if (!empty($row['created_at'])) {
            $draft->createdAt = new \DateTimeImmutable((string) $row['created_at']);
        }
        if (!empty($row['updated_at'])) {
            $draft->updatedAt = new \DateTimeImmutable((string) $row['updated_at']);
        }
        return $draft;
    }

    public function toArray(): array
    {
        return [
            'id' => $this->id,
            'user_id' => $this->userId,
            'account_id' => $this->accountId,
            'mode' => $this->mode,
            'reply_to_msg_id' => $this->replyToMsgId,
            'forward_of_msg_id' => $this->forwardOfMsgId,
            'to_json' => json_encode($this->to, JSON_UNESCAPED_SLASHES),
            'cc_json' => json_encode($this->cc, JSON_UNESCAPED_SLASHES),
            'bcc_json' => json_encode($this->bcc, JSON_UNESCAPED_SLASHES),
            'subject' => $this->subject,
            'body_html' => $this->bodyHtml,
            'body_text' => $this->bodyText,
            'attachment_ids_json' => json_encode($this->attachmentIds, JSON_UNESCAPED_SLASHES),
            'status' => $this->status,
            'last_error' => $this->lastError,
            'created_at' => $this->createdAt->format(\DateTimeInterface::ATOM),
            'updated_at' => $this->updatedAt->format(\DateTimeInterface::ATOM),
        ];
    }

    public function toRequest(): ComposeRequest
    {
        return new ComposeRequest(
            mode: $this->mode,
            to: $this->to,
            cc: $this->cc,
            bcc: $this->bcc,
            subject: $this->subject,
            bodyHtml: $this->bodyHtml,
            bodyText: $this->bodyText,
            attachmentIds: $this->attachmentIds,
            accountId: $this->accountId,
            draftId: $this->id,
            saveAsDraft: $this->status !== 'sent',
            replyToMsgId: $this->replyToMsgId,
            forwardOfMsgId: $this->forwardOfMsgId,
        );
    }

    private static function decodeJsonArray(string $json): array
    {
        $val = json_decode($json, true);
        return is_array($val) ? $val : [];
    }
}
