<?php

namespace Velis\Dto\Validators;

use Attribute;
use DateMalformedStringException;
use DateTimeImmutable;
use DateTimeInterface;
use Exception;

/**
 * @author Szymon Janaczek <szymon.janaczek@singu.com>
 */
#[Attribute]
class DateAfterValidator extends BaseValidator
{
    public function __construct(
        public DateTimeInterface|string|array $after,
        public string $message = 'Date should be after %s.',
    ) {
    }

    /**
     * {@inheritDoc}
     */
    public function validate($value): bool
    {
        if (is_null($value)) {
            return true;
        }

        try {
            $passedDate = new DateTimeImmutable($value);
        } catch (Exception) {
            return false;
        }

        $after = $this->after;
        if (!is_array($after)) {
            $after = [$after];
        }

        foreach ($after as $dateOrField) {
            if ($dateOrField instanceof DateTimeInterface) {
                if ($passedDate < $dateOrField) {
                    $this->message = sprintf($this->message, $dateOrField->format('c'));
                    return false;
                }
                continue;
            }

            $referencedFieldValue = $this->dtoData[$dateOrField];
            if (!$referencedFieldValue) {
                continue;
            }

            try {
                $referencedFieldDate = new DateTimeImmutable($this->dtoData[$dateOrField]);
            } catch (DateMalformedStringException) {
                $this->message = sprintf('Invalid datetime value in referenced field: `%s`', $dateOrField);
                return false;
            }

            if ($passedDate < $referencedFieldDate) {
                $this->message = sprintf($this->message, $dateOrField);
                return false;
            }

            return true;
        }

        return true;
    }
}
