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

namespace Kufer\KuferTools\Allgemein\Raumreservierung\Reservierungsformular\SendeReservierung;

use Kufer\KuferTools\Allgemein\EinstellungenUser\AendereEinstellungen\AendereEinstellungenController;
use Kufer\KuferTools\Allgemein\Raumreservierung\Reservierungsformular\BasisRaumReservierungsformularRequest;
use Kufer\KuferTools\Allgemein\Raumreservierung\Reservierungsformular\BasisRaumReservierungsformularResponse;
use Kufer\KuferTools\Allgemein\Raumreservierung\Reservierungsformular\BasisRaumReservierungsformularUseCase;
use Kufer\KuferTools\Ausgaben\SammelEMail\AnDozenten\SammelEMailView;
use Kufer\Mail\EMail\EMailHTML;
use Kufer\Mail\Sender\EMailSenderFactory;

class SendeReservierungUseCase extends BasisRaumReservierungsformularUseCase
{
  public const RESERVIERUNG_ERFOLGREICH = 'reservierung_erfolgreich';
  public const RESERVIERUNG_ERFOLGREICH_EMAIL_FEHLER = 'reservierung_erfolgreich_email_fehler';
  public const RESERVIERUNG_TECHNISCHER_FEHLER = 'reservierung_technischer_fehler';
  public const RESERVIERUNG_EINGABEN_FEHLERHAFT = 'reservierung_eingaben_fehlerhaft';
  public const RESERVIERUNG_KEIN_ZUGRIFF_AUF_ORT = 'reservierung_kein_zugriff_auf_ort';
  public const RESERVIERUNG_ZEITBEREICH_NICHT_FREI = 'reservierung_zeitbereich_nicht_frei';
  public const RESERVIERUNG_ZEITBEREICH_IN_VERGANGENHEIT = 'reservierung_zeitbereich_in_vergangenheit';
  public const RESERVIERUNG_DOPPELT_ABGESENDET = 'reservierung_doppelt_abgesendet';

  public function __construct($request)
  {
    parent::__construct($request, new SendeReservierungResponse());
  }

  public static function getToolId(): int
  {
    return 66;
  }

  public static function getToolSectionId(): int
  {
    return 770;
  }

  public function hasAccess($pToolSectionId = null): bool
  {
    if (!parent::hasAccess()) {
      return false;
    } elseif (!$this->request->isXsrfOk && !$this->request->isRefresh) {
      return false;
    }

    if (!is_numeric($this->request->raum)) {
      return false; 
    }

    if (!\DateTimeOperations::isValidDate($this->request->datum)) {
      return false; 
    }

    

    return true;
  }

  public function action(): SendeReservierungResponse
  {
    $checkSperrzeitStatus = $this->checkSperrzeit($this->request->sperrzeit);
    if ($checkSperrzeitStatus !== self::RESERVIERUNG_ERFOLGREICH) {
      parent::action();

      return $this->getResponse($checkSperrzeitStatus);
    } else {
      $saveSperrzeitStatus = $this->saveSperrzeit($this->request->sperrzeit);
      parent::action(); 

      return $this->getResponse($saveSperrzeitStatus);
    }
  }

  private function checkSperrzeit(\Ortverf $pSperrzeit): string
  {
    if (!$this->isSperrzeitAnEinemTagValid($pSperrzeit)) {
      return self::RESERVIERUNG_EINGABEN_FEHLERHAFT;
    } elseif (!$this->isSperrzeitInZukunft($pSperrzeit)) {
      return self::RESERVIERUNG_ZEITBEREICH_IN_VERGANGENHEIT;
    } elseif (!$this->hatPersonZugriffAufDenOrt($pSperrzeit->ortnr)) {
      return self::RESERVIERUNG_KEIN_ZUGRIFF_AUF_ORT;
    } elseif (!$this->isZeitbereichFrei($pSperrzeit->ortnr, $pSperrzeit->vondat, $pSperrzeit->vonuhr, $pSperrzeit->bisuhr)) {
      return self::RESERVIERUNG_ZEITBEREICH_NICHT_FREI;
    } else {
      return self::RESERVIERUNG_ERFOLGREICH;
    }
  }

  private function isSperrzeitAnEinemTagValid(\Ortverf $pSperrzeit): bool
  {
    
    $ortnummerIstValide = is_numeric($pSperrzeit->ortnr) && $pSperrzeit->ortnr > 0;
    $vonUndBisDatumSindValide = \DateTimeOperations::isValidDate($pSperrzeit->vondat) && \DateTimeOperations::isValidDate($pSperrzeit->bisdat);
    $vonUndBisUhrzeitenSindValide = \DateTimeOperations::isValidTimeString($pSperrzeit->vonuhr) && \DateTimeOperations::isValidTimeString($pSperrzeit->bisuhr);

    
    $vonUndBisDatumSindGleich = $pSperrzeit->vondat === $pSperrzeit->bisdat;
    $vonUhrLiegtVorBisUhr = \DateTimeOperations::isDateTimeBefore('01.01.2001 ' . $pSperrzeit->vonuhr, '01.01.2001 ' . $pSperrzeit->bisuhr);

    return $ortnummerIstValide && $vonUndBisDatumSindValide && $vonUndBisUhrzeitenSindValide && $vonUndBisDatumSindGleich && $vonUhrLiegtVorBisUhr;
  }

  private function isSperrzeitInZukunft(\Ortverf $pSperrzeit): bool
  {
    $aktuellesDatum = \DateTimeOperations::getDateNow();
    
    if (\DateTimeOperations::isDatebeforeNow($pSperrzeit->vondat)) {
      return false;
    } elseif (\DateTimeOperations::isDateAfter($pSperrzeit->vondat, $aktuellesDatum)) {
      return true;
    } else { 
      
      
      

      return \DateTimeOperations::isDateTimeAfter($aktuellesDatum . ' ' . $pSperrzeit->bisuhr, \DateTimeOperations::getDateTimeNow());
    }
  }

  private function hatPersonZugriffAufDenOrt(int $pRaumId): bool
  {
    
    return true;
  }

  private function isZeitbereichFrei(int $pRaumId, string $pDatum, string $pUhrzeitVon, string $pUhrzeitBis): bool
  {
    if ($this->istDurchKurstagBelegt($pRaumId, $pDatum, $pUhrzeitVon, $pUhrzeitBis)) {
      return false;
    } elseif ($this->istDurchSperrzeitBelegt($pRaumId, $pDatum, $pUhrzeitVon, $pUhrzeitBis)) {
      return false;
    }

    return true;
    
  }

  private function istDurchKurstagBelegt(int $pRaumId, string $pDatum, string $pUhrzeitVon, string $pUhrzeitBis): bool
  {
    $dbworkKurstage = new \DBWorkKurseTageWT(1, true);
    $filter = \Kufer\Web\Classes\Dbfilter\KurstageSQLFilter::create();
    $filter->equalsDatum($pDatum);

    $filter->lessBeginnZeit($pUhrzeitBis);
    $filter->greaterEndeZeit($pUhrzeitVon);

    $filter->equalsOrtId($pRaumId);

    $filter->not(function($notFilter) {
      $notFilter->inStatus(array('A', 'X'));
    });

    $kurstage = $dbworkKurstage->findByFilter($filter);

    return count($kurstage) > 0;
  }

  private function istDurchSperrzeitBelegt(int $pRaumId, string $pDatum, string $pUhrzeitVon, string $pUhrzeitBis): bool
  {
    $dbwOrtVerf = new \DBWorkOrtVerf(1, true);
    $sperrzeiten = $dbwOrtVerf->getSperrzeitenFuerRaumInnerhalbZeitbereich($pRaumId, $pDatum, $pUhrzeitVon, $pUhrzeitBis);

    return count($sperrzeiten) > 0;
  }

  private function saveSperrzeit(\Ortverf $pSperrzeit): string
  {
    $pSperrzeit->kommentar = 'Reserviert in den ' . KUFERTOOLS . ' von ' . \SessionOperations::getCurrentWebToolsPerson()->getVarValue('name_ggf_vorname');
    $result = \SperrzeitAPI::insertSperrzeit($pSperrzeit);
    if ($result) {
      if ($this->toolSettings->emailAnEinrichtung) {
        return $this->sendeEMailAnEinrichtung($pSperrzeit) ? self::RESERVIERUNG_ERFOLGREICH : self::RESERVIERUNG_ERFOLGREICH_EMAIL_FEHLER;
      }
    }

    return $result ? self::RESERVIERUNG_ERFOLGREICH : self::RESERVIERUNG_TECHNISCHER_FEHLER;
  }

  protected function sendeEMailAnEinrichtung(\Ortverf $sperrzeit): bool
  {
    $emailViewModel = new ReservierungEMailViewModel();
    $emailViewModel->sperrzeit = $sperrzeit;
    $emailViewModel->raum = $this->getKursort();
    $emailBase = new ReservierungEMailPresenter($emailViewModel);
    $email = new EMailHTML($emailBase->getSubject(), $emailBase->getContent(), $emailBase->getAttachments());
    $email->addKuferToolsFooter($emailBase->getSubject(), $this->getUser(), $sperrzeit);
    $sender = EMailSenderFactory::createForToolsWithCustomAddress($this->toolSettings->emailAnEinrichtungCustom);

    try {
      return $sender->sendFromPersonToEinrichtung($email, \SessionOperations::getCurrentWebToolsPerson())->hasSentAnyMails();
    } catch (\Exception $ex) {
      return false;
    }
  }

  protected function getResponse(string $checkSperrzeitStatus): SendeReservierungResponse
  {
    $this->handleResponseStrategies();

    $this->response->status = $checkSperrzeitStatus;
    $this->response->kursort = $this->getKursort();
    $this->response->sperrzeit = $this->request->sperrzeit;

    return $this->response;
  }

  protected function getResponseStrategies(): array
  {
    return array(
        new \Kufer\KuferTools\Utils\ResponseStrategies\ResponseMitRahmen($this)
    );
  }
}

class SendeReservierungRequest extends BasisRaumReservierungsformularRequest
{
  public $sperrzeit;
}

class SendeReservierungResponse extends BasisRaumReservierungsformularResponse
{
}