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

namespace Kufer\KuferTools\Basis\Kursdetails\DetailsReiter\Termine\TerminVerlaengernDialog;

use Kufer\KuferTools\Utils\StatusMessages\StatusMessage;
use Kufer\KuferTools\Firma\KursUebersicht\KursUebersicht\Detailsreiter\Termine\TerminStornierenDialog\TerminStornierenUtils;

abstract class TerminVerlaengernAbsendenUseCase extends \Kufer\KuferTools\Basis\UseCase\ToolUseCase
{
  protected $statusMessageContainer;
  protected $kurstageNeuId = array();
  protected $kurstageNeu = array();

  protected $dbwKurstage;

  public function __construct($request)
  {
    parent::__construct($request, new TerminVerlaengernAbsendenResponse());
    $this->statusMessageContainer = \Kufer\KuferTools\Utils\StatusMessages\StatusMessageContainer::getSharedInstance();
    $this->dbwKurstage = $this->getDbwKurstage();
  }

  public function hasAccess($pToolSectionId = null)
  {
    if (!parent::hasAccess($pToolSectionId)) {
      return false;
    }
    if (!\DBWorkBASysSettings::isInlinguaMuenchen()) {
      return false;
    }
    if (!$this->request->isXsrfOk && !$this->request->isRefresh) {
      return false;
    }
    if (!$this->hasAccessToKurstag()) {
      return false;
    }
    if (!TerminStornierenUtils::canAutoCreateNewKurstag(
      $this->dbwKurstage,
      $this->request->knr
    )) {
      return false;
    }
    if (isset($this->request->kurstage) && (!\is_numeric($this->request->kurstage) || $this->request->kurstage <= 0)) {
      return false;
    }

    return true;
  }

  public function action()
  {
    if (!isset($this->request->kurstage)) {
      $this->response->isAbweichendeKurstage = false;
      $this->request->kurstage = TerminStornierenUtils::countOriginalKurstage($this->dbwKurstage, $this->request->knr);
    } else {
      
      $this->response->isAbweichendeKurstage = $this->request->kurstage != TerminStornierenUtils::countOriginalKurstage($this->dbwKurstage, $this->request->knr);
      $this->request->kurstage = (int)$this->request->kurstage;
    }

    if (!$this->request->isRefresh) {
      $kurs = $this->getKurs($this->request->knr);
      $isDmzBetrieb = \SessionOperations::isDmzBetrieb();
      try {
        $result = $this->erstelleTermineDirekt();
        if ($result) {
          if ($isDmzBetrieb) {
            $this->erstelleTerminDMZ();
          }

          try {
            
            
            

            $this->sendeBenachrichtigungen($kurs, $this->kurstageNeu);
          } catch (\Exception $e) {
            
            \Logger::loggException($e, 200);
          }
        } else {
          $this->setStatusMessageAllgemeinerFehler();
        }
      } catch (\Exception $e) {
        $this->revertErstellenTerminDirekt($isDmzBetrieb);
        $this->setStatusMessageAllgemeinerFehler();
        \Logger::loggException($e, 200);
      }
    }

    return $this->getResponse();
  }

  
  protected function erstelleTermineDirekt(): bool
  {
    $dbwKurstage = $this->getDbwKurstage();

    $kurstage = TerminStornierenUtils::getDatumNeueKurstage($this->request->knr, $this->request->kurstage);
    if (empty($kurstage)) {
      return false;
    }

    foreach ($kurstage as $kurstagDatum) {
      $wochentagIntNeuerKurstag = \DateTimeOperations::getWeekDayFromDate($kurstagDatum);
      $kurstagGleicherWochentag = TerminStornierenUtils::getLetzterKurstagAm($wochentagIntNeuerKurstag, $this->request->knr);

      $kurstagNeu = clone($kurstagGleicherWochentag);
      $kurstagNeu->ausfall = 'Z';
      $kurstagNeu->setValue2Var('datum', $kurstagDatum);
      $kurstagNeu->anlage_kursverlaengerung = true;

      $id = $dbwKurstage->insertKurstag($kurstagNeu);
      $this->kurstageNeuId[] = $id;
      $this->kurstageNeu[$id] = $kurstagNeu;
    }

    $this->updateKursdaten($this->request->knr);

    return true;
  }

  
  protected function revertErstellenTerminDirekt($pIsDmzBetrieb)
  {
    $dbwKurstage = $this->getDbwKurstage();

    if (!empty($this->kurstageNeuId)) {
      foreach ($this->kurstageNeuId as $kurstagNeuId) {
        $dbwKurstage->deleteKurstag($kurstagNeuId);
      }
      $this->updateKursdaten($this->request->knr);
    }
  }

  
  protected function updateKursdaten($pKnr)
  {
    $nichtPassendeKursdaten = \PasstKursZuKurstageAPI::passenKursdatenZuKurstagen($pKnr);
    $kurs = $this->getKurs($pKnr);
    $data = $this->getKursData($kurs);

    $doUpdateKurs = false;
    foreach ($data as $field) {
      foreach ($nichtPassendeKursdaten as $kursdaten) {
        if ($kursdaten['name'] == $field->name) {
          $field->newvalue = $kursdaten['newvalue'];
          $doUpdateKurs = true;
        }
      }
    }

    if ($doUpdateKurs) {
      \PasstKursZuKurstageAPI::updateKurs($data, $kurs);
    }
  }

  
  protected function getDbwKurstage()
  {
    return \DBWorkKurseTage::getDefaultInstance(1, true);
  }

  
  protected function getDbwKurse()
  {
    return \DBWorkKurse::getDefaultInstance(1, true);
  }

  
  protected function getKurstag($pktid)
  {
    static $cache = array();
    if (!isset($cache[$pktid])) {
      $dbwkurstage = $this->getDbwKurstage();
      $cache[$pktid] = $dbwkurstage->getKurstag($pktid, true);
    }

    return $cache[$pktid];
  }

  protected function getKurs($pknr)
  {
    static $cache = array();
    if (!isset($cache[$pknr])) {
      $dbwkurse = $this->getDbwKurse();
      $cache[$pknr] = $dbwkurse->getKurs($pknr, true);
    }

    return $cache[$pknr];
  }

  
  private function getKursData($pKurs)
  {
    $data = array();

    $item = new \stdClass();
    $item->name = 'ende_dat';
    $item->newvalue = $pKurs->ende_dat;
    $item->checked = true;
    $data[] = $item;

    return $data;
  }

  protected function getResponse()
  {
    return $this->response;
  }

  protected function setStatusMessageAllgemeinerFehler()
  {
    $statusMeldung = 'Die Verlängerung des Kurses ist zurzeit nicht möglich. Versuchen Sie es später erneut oder wenden Sie sich an uns, falls dieses Problem länger bestehen bleiben sollte.';
    $this->statusMessageContainer->addStatusMessageObj(StatusMessage::getErrorMessageObj($statusMeldung));
  }

  

  protected function setStatusMessageTermineErstellenSuccess()
  {
    $statusMeldung = 'Der Kurs wurde erfolgreich verlängert';
    $this->statusMessageContainer->addStatusMessageObj(StatusMessage::getSuccessMessageObj($statusMeldung));
  }

  
  protected function sendeBenachrichtigungen($kurs, $kurstage): void
  {
    $emailRequest = new TerminVerlaengernAbsendenEMailRequest();
    $emailRequest->knr = $this->request->knr;
    $emailRequest->kurs = $kurs;
    $emailRequest->kurstage = $kurstage;
    $emailRequest->isAbweichendeKurstage = $this->response->isAbweichendeKurstage;

    $emailUsecase = $this->getEMailUseCase($emailRequest);
    $emailUsecase->action();

    $emailFirmendienstUseCase = $this->getEMailFirmendienstUseCase($emailRequest);
    $emailFirmendienstUseCase->action();
  }

  protected function erstelleTerminDMZ()
  {
    $kurskorrekturApi = new \KurskorrekturAPI();
    $kurskorrekturApi->correctKurstage(\array_map(function($ktId) {
      $kurstag = $this->getKurstag($ktId);

      return new \Tuple(
        $kurstag,
        \array_keys(\array_filter(\get_object_vars($kurstag)))
      );
    }, $this->kurstageNeuId), 'insert');
  }

  abstract protected function hasAccessToKurstag(): bool;

  abstract protected function getEMailUseCase($emailRequest);

  abstract protected function getEMailFirmendienstUseCase($emailRequest);
}

class TerminVerlaengernAbsendenRequest
{
  public $belegId;
  public $knr;
  public $isRefresh;
  public $isXsrfOk;
  public $kurstage;
}

class TerminVerlaengernAbsendenResponse extends \Kufer\KuferTools\Basis\UseCase\ToolResponse
{
  public $isAbweichendeKurstage;
}