<?php

namespace MintyPHP\Module\Notifications\Service;

final class NotificationMessage
{
    /**
     * @param array<string, mixed> $data
     * @param list<scalar|null> $titleParams
     * @param list<scalar|null> $bodyParams
     */
    public function __construct(
        private readonly string $type,
        private readonly string $title,
        private readonly ?string $body = null,
        private readonly ?string $link = null,
        private readonly array $data = [],
        private readonly ?string $titleKey = null,
        private readonly array $titleParams = [],
        private readonly ?string $bodyKey = null,
        private readonly array $bodyParams = []
    ) {
    }

    /**
     * @param array<string, mixed> $data
     */
    public static function plain(
        string $type,
        string $title,
        ?string $body = null,
        ?string $link = null,
        array $data = []
    ): self {
        return new self($type, $title, $body, $link, $data);
    }

    /**
     * Creates a locale-neutral notification message while still storing a translated fallback.
     *
     * @param list<scalar|null> $titleParams
     * @param list<scalar|null> $bodyParams
     * @param array<string, mixed> $data
     */
    public static function localized(
        string $type,
        string $titleKey,
        array $titleParams = [],
        ?string $bodyKey = null,
        array $bodyParams = [],
        ?string $link = null,
        array $data = []
    ): self {
        $resolvedTitle = self::translate($titleKey, $titleParams);
        $resolvedBody = $bodyKey !== null && $bodyKey !== '' ? self::translate($bodyKey, $bodyParams) : null;

        return new self(
            $type,
            $resolvedTitle,
            $resolvedBody,
            $link,
            $data,
            $titleKey,
            self::normalizeParams($titleParams),
            $bodyKey !== null && $bodyKey !== '' ? $bodyKey : null,
            self::normalizeParams($bodyParams)
        );
    }

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

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

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

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

    /**
     * @return array<string, mixed>
     */
    public function data(): array
    {
        return $this->data;
    }

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

    /**
     * @return list<scalar|null>
     */
    public function titleParams(): array
    {
        return $this->titleParams;
    }

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

    /**
     * @return list<scalar|null>
     */
    public function bodyParams(): array
    {
        return $this->bodyParams;
    }

    /**
     * @param array<mixed> $params
     * @return list<scalar|null>
     */
    private static function normalizeParams(array $params): array
    {
        $normalized = [];
        foreach ($params as $value) {
            if (is_scalar($value) || $value === null) {
                $normalized[] = $value;
            }
        }

        return $normalized;
    }

    /**
     * @param array<mixed> $params
     */
    private static function translate(string $key, array $params): string
    {
        $normalized = self::normalizeParams($params);
        return (string) t($key, ...$normalized);
    }
}
