<?php

declare(strict_types=1);

namespace Drupal\migrate_leshed\Plugin\migrate\process;

use Drupal\migrate\Attribute\MigrateProcess;
use Drupal\migrate\MigrateExecutableInterface;
use Drupal\migrate\ProcessPluginBase;
use Drupal\migrate\Row;

/**
 * Converts Google Sheet project dates to 'Y-m-d'.
 *
 * Accepted inputs:
 * - 'd/m/Y' (e.g. "19/09/2015"),
 * - a bare year (e.g. "2016"), converted to the first day of the year, or
 *   to the last day when 'end_of_year: true' is set in the configuration.
 *
 * When the value is empty or invalid and 'fallback_source' is set in the
 * configuration, the named source property is converted instead. This is
 * used to default the end date to the start date, since the daterange
 * field requires a non-null end value.
 *
 * Invalid or unparseable values return NULL and are logged in the
 * migration messages instead of failing the whole row.
 */
#[MigrateProcess(id: 'leshed_date')]
final class LeshedDate extends ProcessPluginBase {

  /**
   * {@inheritdoc}
   */
  public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property): ?string {
    $result = $this->convert($value, $migrate_executable, $destination_property);

    if ($result === NULL && !empty($this->configuration['fallback_source'])) {
      $fallback = $row->getSourceProperty($this->configuration['fallback_source']);
      $result = $this->convert($fallback, $migrate_executable, $destination_property);
    }

    return $result;
  }

  /**
   * Converts a single raw value to 'Y-m-d', or NULL if not parseable.
   */
  private function convert(mixed $value, MigrateExecutableInterface $migrate_executable, string $destination_property): ?string {
    if (!is_string($value)) {
      return NULL;
    }
    $value = trim($value);
    if ($value === '') {
      return NULL;
    }

    // Bare year: "2016".
    if (preg_match('/^\d{4}$/', $value)) {
      return empty($this->configuration['end_of_year'])
        ? $value . '-01-01'
        : $value . '-12-31';
    }

    // Full date: "19/09/2015".
    $date = \DateTime::createFromFormat('!d/m/Y', $value);
    $errors = \DateTime::getLastErrors();
    if ($date === FALSE || ($errors && ($errors['warning_count'] || $errors['error_count']))) {
      $migrate_executable->saveMessage(
        sprintf('Date invalide "%s" pour la propriété "%s".', $value, $destination_property)
      );
      return NULL;
    }

    return $date->format('Y-m-d');
  }

}
