<?php
/**
 * @copyright (c) Kufer Software GmbH, Loisachstrasse 4, D-84453 Mühldorf
 */

declare(strict_types = 1);

namespace Kufer\Web\Classes\CronJob\ReplikatUebertragung;

use Kufer\Web\Classes\CronJob\CronJobStorage;


class ReplikatUebertragungDbGruppeCronJob implements \Kufer\Web\Classes\CronJob\ICronJob
{
  
  private $replikatDbId;
  private $startId = -1;
  
  private $fnNichtUebertrageneGruppen;
  
  private $fnDatengruppeWirdWiederUebertragen;

  
  public function __construct(int $replikatDbId, $fnNichtUebertrageneGruppen, $fnDatengruppeWirdWiederUebertragen)
  {
    assert($replikatDbId >= 1 && $replikatDbId <= 12);
    $this->replikatDbId = $replikatDbId;
    $this->fnNichtUebertrageneGruppen = $fnNichtUebertrageneGruppen;
    $this->fnDatengruppeWirdWiederUebertragen = $fnDatengruppeWirdWiederUebertragen;
  }

  
  private function getTimeAtLeastPastSinceLastReplication(): ?int
  {
    $allgSettings = \ToolSettingsAPI::getToolSettings(0);
    $interval = $allgSettings->{'cronjobReplikatCheckDb' . $this->replikatDbId} ?? null;
    if (empty($interval)) {
      return null;
    }

    return (int)$interval;
  }

  public function getTimeInterval(CronJobStorage $storage): ?int
  {
    $timeAtLeastPast = $this->getTimeAtLeastPastSinceLastReplication();
    if (is_null($timeAtLeastPast)) {
      return null;
    }

    
    
    return (int)($timeAtLeastPast / 3);
  }

  public function execute(CronJobStorage $storage): void
  {
    $dbwWebReplikatSettings = \DBWorkWebReplikatSettings::getDefaultInstance();
    $replicatedAt = $dbwWebReplikatSettings->getReplicatedAt($this->replikatDbId);
    
    if (empty($replicatedAt->value)) {
      $this->sendWarning($storage, null);

      return;
    }

    $replicatedAt = \DateTimeOperations::getValidDateTimeString($replicatedAt->value);
    $replicatedAtTSM = (int)(\DateTimeOperations::getTimestampByDateTimeString($replicatedAt, true) / 60);
    $nowTSM = (int)(\DateTimeOperations::getTimestampNow() / 60);
    $minDuration = $this->getTimeAtLeastPastSinceLastReplication();
    if (is_null($minDuration)) {
      return;
    }

    
    $diff = $nowTSM - $replicatedAtTSM;
    if ($diff >= $minDuration) {
      $this->sendWarning($storage, $replicatedAt);

      return;
    }

    
    
    if ($diff < -61) {
      $this->sendWarning($storage, $replicatedAt);

      return;
    }

    
    if ($this->hasAlreadySendWarning($storage)) {
      
      call_user_func($this->fnDatengruppeWirdWiederUebertragen, $this->replikatDbId, $replicatedAt);

      
      $storage->saveJobData($this->getId(), new class() {
      });
    }
  }

  
  private function hasAlreadySendWarning(CronJobStorage $storage): bool
  {
    $data = $storage->loadJobData($this->getId());
    if (!is_null($data)) {
      $lastReplicatedAt = $data->last_warning_for_replicated_at ?? null;
      if (!is_null($lastReplicatedAt)) {
        return true;
      }
    }

    return false;
  }

  private function sendWarning(CronJobStorage $storage, ?string $replicatedAt): void
  {
    if ($this->hasAlreadySendWarning($storage)) {
      return; 
    }

    $obj = new class() {
      public $last_warning_for_replicated_at;
    };
    $obj->last_warning_for_replicated_at = $replicatedAt ?? (DEFAULTDATE . ' ' . DEFAULTTIME);

    $storage->saveJobData($this->getId(), $obj);
    call_user_func($this->fnNichtUebertrageneGruppen, $this->replikatDbId, $replicatedAt);
  }

  public function getName(): string
  {
    return 'Prüfe Replikatsübertragung DG ' . $this->replikatDbId;
  }

  public function getId(): ?int
  {
    return $this->startId + $this->replikatDbId;
  }
}