<?php
/**
 * @copyright (c) Kufer Software GmbH, Oderstraße 7, D-84453 Mühldorf
 */

namespace Kufer\Web\KuferTools\Dozent\Anwesenheiten\AnwesenheitenSpeichern;

use Kufer\Web\KuferTools\Dozent\Anwesenheiten\Utils\AnwesenheitenUtils as AnwesenheitenUtils;
use Kufer\Web\KuferTools\Dozent\Anwesenheiten\Utils\KurstageUtils as KurstageUtils;
use Kufer\Web\Classes\Mail\Sender\Settings\RecipientEinrichtung\EMailEinrichtungRecipientToolsKursSettings;

class AnwesenheitenSpeichernUseCase extends \Kufer\Web\KuferTools\Basis\UseCase\ToolUseCase
{
  public const EINTRAGUNG_ERFOLGREICH = 'erfolgreich';
  public const SCHREIBEN_DEAKTIVIERT = 'deaktiviert';
  public const EINTRAGUNG_FEHLER = 'fehler';
  public const EINTRAGUNG_FEHLER_EXCEPTION = 'exceptionfault';
  public const EINTRAGUNG_KLASSENBUCH_ERFOLGREICH = 'klassenbuchsuccess';
  public const EINTRAGUNG_KLASSENBUCH_ERFOLGREICH_EMAIL_FEHLER = 'klassenbuchsuccessemailfehler';
  public const VERHALTENS_EINTRAEGEN_ERFOLGREICH = 'verhaltensuccess';
  public const VERHALTENS_EINTRAEGEN_FEHLER = 'verhaltenfailed';
  public const UNTERRICHTSMITTEL_EINTRAEGEN_ERFOLGREICH = 'unterrichtsmittelsuccess';

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

  public static function getToolId()
  {
    return 18;
  }

  public static function getToolSectionId()
  {
    return 274;
  }

  public function hasAccess($pToolSectionId = null)
  {
    if (!parent::hasAccess()) {
      return false;
    }
    if (!KurstageUtils::hasAccessToKurstag($this->request->kurstagId, $this->toolSettings)) {
      return false;
    }

    $kurstag = $this->getKurstag();
    if (!KurstageUtils::hasAccessToAnwesenheitenOfKurstag($kurstag->getKurs(), $kurstag, $this->toolSettings)) {
      return false;
    }
    if (!$this->request->isXsrfOk && !$this->request->isRefresh) {
      return false;
    }
    if (!$this->isRechtAllowed('273.0.3')) {
      return false;
    }
    if (!$this->hasAccessToAnwesenheiten($kurstag)) {
      return false;
    }
    if ($this->toolSettings->anwesenheitenMustSetAll && !$this->istAnwesenheitenReadonly($kurstag)) {
      
      foreach ($this->getAnwInfoFromRequest() as $anwInfo) {
        if ($anwInfo->astatus === '') {
          return false; 
        }
      }
    }

    if ($this->isReadOnly($kurstag)) {
      return false;
    }

    return true;
  }

  private function istAnwesenheitenReadonly(\Kurstag $kurstag) : bool
  {
    if ($this->toolSettings->anwesenheitenBamfNichtBearbeitbar && $kurstag->kurs->bamf) {
      return true;
    }

    return false;
  }

  private function isReadOnly(\Kurstag $kurstag) : bool
  {
    if ($this->isRechtAllowed('274.0.1')) { 
      $user = $this->getUser();
      if ($this->toolSettings->anwesenheitenNurEigeneKurseBearbeitbar && $kurstag->dnr != $user->dnr) {
        return true;
      }

      return false;
    } else {
      return true;
    }
  }

  private function hasAccessToAnwesenheiten(\Kurstag $kurstag): bool
  {
    $anwInfos = $this->getAnwInfoFromRequest();
    $dbwBelegung = new \DBWorkBelegung();
    foreach ($anwInfos as $anwInfo) {
      if (!$this->hasAccessToAnwesenheit($dbwBelegung, $kurstag, $anwInfo)) {
        return false;
      }
    }

    return true;
  }

  private function hasAccessToAnwesenheit(\DBWorkBelegung $dbwBelegung, \Kurstag $kurstag, \Anwesenheit $anw): bool
  {
    if ($anw->aktid != $this->request->kurstagId) {
      return false;
    }

    $belegung = $dbwBelegung->getBelegung($anw->abelegid);
    if ($belegung->knr != $kurstag->knr) {
      return false;
    }

    if (!\DateTimeOperations::isEmptyOrDefault($kurstag->datum)) {
      $restrictStatusByDate = \Kufer\Web\Classes\db\searchobject\BelegungToObjectStatusByDate::createFromSettings(
        \ToolSettingsAPI::getToolSettings(0),
        $kurstag->datum
      );

      if (!is_null($restrictStatusByDate) && !$restrictStatusByDate->isBelegungAllowed($belegung, $kurstag->datum)) {
        return false;
      }
    }

    return true;
  }

  private function getKurstag(): \Kurstag
  {
    $dbwKurstag = new \DBWorkKurseTageWT();

    return $dbwKurstag->getKurstag($this->request->kurstagId);
  }

  public function action()
  {
    
    $storeInfo = $this->speichern();

    $this->response->statusCode[] = $storeInfo['statusCode'];
    $this->response->anwExtraStoreAry = $storeInfo['anwExtraStoreAry'];

    return $this->response;
  }

  private function speichern()
  {
    $statusCode = array();

    $storeInfo = array('statusCode' => $statusCode, 'anwExtraStoreAry' => array());

    $dbwKurstage = KurstageUtils::getDbwKursTage($this->toolSettings);
    $kurstag = $dbwKurstage->getKurstag($this->request->kurstagId);
    try {
      
      $saveAnwResult = $this->saveAnwesenheiten($kurstag);
      $statusCode[] = $saveAnwResult['success'];

      $statusCode[] = $this->saveKurstag($kurstag);
      $statusCode[] = $this->saveUnterrichtsmittel($kurstag);
      $statusCode[] = $this->saveVerhaltenEntries();
    } catch (\Exception $e) {
      \Logger::logg('Anwesenheiten eintragen - folgende Exception ist aufgetreten: ' . $e->getMessage() . ' [' . $e->getTraceAsString() . ']', 200);
      $statusCode = self::EINTRAGUNG_FEHLER_EXCEPTION;
    }
    $storeInfo['statusCode'] = $statusCode;
    $anwExtraStoreAry = array();
    if (isset($saveAnwResult) && count($saveAnwResult['extraAnwIds']) > 0) {
      
      
      
      foreach ($saveAnwResult['extraAnwIds'] as $key => $extraAnwIdAry) {
        $anwStoreObj4ExtraAnw = new \stdClass();
        $anwStoreObj4ExtraAnw->id = $key;
        $anwStoreObj4ExtraAnw->extraAnwIds = $extraAnwIdAry;
        $anwExtraStoreAry[] = $anwStoreObj4ExtraAnw;
      } 
      $storeInfo['anwExtraStoreAry'] = $anwExtraStoreAry;
    } 

    return $storeInfo;
  }

  private function saveVerhaltenEntries()
  {
    $statusResult = '';
    $verhaltensEntries = unserialize(serialize($this->request->data->Verhaltenseintrag));
    if (count($verhaltensEntries) > 0) {
      $verhaltensApi = new \VerhaltenAPI($this->getUser()->getIdentifier(), $this->toolSettings->showVerhEntriesDays);
      
      
      
      $verhSuccess = $verhaltensApi->aktualisiereVerhalten($verhaltensEntries, true);

      if (!$verhSuccess) {
        $statusResult = self::VERHALTENS_EINTRAEGEN_FEHLER;
      } else {
        $statusResult = self::VERHALTENS_EINTRAEGEN_ERFOLGREICH;
      }
    }

    
    
    $this->response->verhaltensInfo = $verhaltensEntries;

    return $statusResult;
  }

  private function saveAnwesenheiten($kurstag)
  {
    $statusResult = '';
    $result = array('extraAnwIds' => array());
    $aenderungNoetig = false;

    
    
    $anwInfoDatamodul = $this->getAnwInfoFromRequest();
    $anwesenheitInfoFromDb = $this->getAnwInfoFromDb();
    
    
    
    
    if (count($anwInfoDatamodul) > 0 && $anwInfoDatamodul != $anwesenheitInfoFromDb) {
      
      $anwesenheitenDieGeaendertWurden = array();
      foreach ($anwInfoDatamodul as $anw) {
        $oldAnw = \NewAnwesenheitAPI::getAnwesenheit4Belegung($anwesenheitInfoFromDb, $anw->abelegid);
        if (false === $oldAnw || $oldAnw != $anw) {
          $anwesenheitenDieGeaendertWurden[] = $anw;
          $aenderungNoetig = true;
        }
      }
      if ($aenderungNoetig && $this->toolSettings->schreibeAnwesenheitenDurch) {
        $anwDruchschreibenObj = new \AnwesenheitenDurchschreibenAPI($this->getToolId());
        $kurstagOrig = clone $kurstag;
        $neueAnwesenheitenAndererKurstage = $anwDruchschreibenObj->getAnwFuerDurchgeschriebeneKurstage(
          $kurstagOrig,
          $anwesenheitenDieGeaendertWurden,
          \ToolSettingsAPI::getToolSettings(0)->showKinderInAnwesenheiten5
        );
        $anwesenheitenDieGeaendertWurden = array_merge($anwesenheitenDieGeaendertWurden, $neueAnwesenheitenAndererKurstage);
      }

      
      try {
        
        $result = \NewAnwesenheitAPI::anwesenheitenEintragen($anwesenheitenDieGeaendertWurden);
        if ($result['success'] instanceof \AbgleichApiResult) {
          if ($result['success']->code == \AbgleichApiResult::CODE_SUCCESS) {
            $statusResult = self::EINTRAGUNG_ERFOLGREICH;
          } elseif ($result['success']->code == \AbgleichApiResult::CODE_DISABLED) {
            $statusResult = self::SCHREIBEN_DEAKTIVIERT;
          } else {
            $statusResult = self::EINTRAGUNG_FEHLER;
          }
        } else {
          if (false === $result['success']) {
            $statusResult = self::SCHREIBEN_DEAKTIVIERT;
          } else {
            $statusResult = self::EINTRAGUNG_ERFOLGREICH;
          }
        }
      } catch (\Exception $e) {
        \Logger::logg('Anwesenheiten eintragen - folgende Exception ist aufgetreten: ' . $e->getMessage() . ' [' . $e->getTraceAsString() . ']', 200);
        $statusResult = self::EINTRAGUNG_FEHLER;
      }
    }

    return  array('success' => $statusResult, 'extraAnwIds' => $result['extraAnwIds'] ?? array());
    
  }

  
  private function saveKurstag($kurstag)
  {
    $statusResult = '';

    $veraenderteEigenschaften = array();

    if ($this->toolSettings->useLehrinhaltErf) {
      $klassenbuchtext = $this->request->data->Arbeitsbericht;
      if ($this->toolSettings->ueNichtErfassen) {
        $klassenbuchueok = $kurstag->klassenbuchueok;
        $klassenbuchabwue = $kurstag->klassenbuchabwue;
        $klassenbuchgrund = $kurstag->klassenbuchgrund;
      } else {
        $klassenbuchueok = ($this->request->data->UeGehalten === '1') ? 1 : 2;
        $klassenbuchabwue = $this->request->data->AbweichendeUe;
        $klassenbuchgrund = $this->request->data->AbweichendeUeGrund;
      }
      if ($klassenbuchtext != $kurstag->klassenbuchtext || $klassenbuchueok != $kurstag->klassenbuchueok
          || $klassenbuchgrund != $kurstag->klassenbuchgrund
          || \MathOperations::stringToFloat($klassenbuchabwue) != \MathOperations::stringToFloat($kurstag->klassenbuchabwue)) {
        $veraenderteEigenschaften['klassenbuchtext'] = $klassenbuchtext;
        $veraenderteEigenschaften['klassenbuchueok'] = $klassenbuchueok;
        $veraenderteEigenschaften['klassenbuchabwue'] = $klassenbuchabwue;
        $veraenderteEigenschaften['klassenbuchgrund'] = $klassenbuchgrund;
      }
    }

    
    if ($this->toolSettings->useBemerkungSlashLehrinhalt) {
      if ($kurstag->bemerkungen != $this->request->data->Lehrinhalt) {
        $veraenderteEigenschaften['bemerkungen'] = $this->request->data->Lehrinhalt;
      }
    }

    
    if ($this->toolSettings->useSprachschuldaten) {
      if ($kurstag->level != $this->request->data->Level) {
        $veraenderteEigenschaften['level'] = $this->request->data->Level;
      }
      if ($kurstag->unit != $this->request->data->Unit) {
        $veraenderteEigenschaften['unit'] = $this->request->data->Unit;
      }
      if ($kurstag->stufe != $this->request->data->Stufe) {
        $veraenderteEigenschaften['stufe'] = $this->request->data->Stufe;
      }
      if ($kurstag->keypoint != $this->request->data->Keypoint) {
        $veraenderteEigenschaften['keypoint'] = $this->request->data->Keypoint;
      }
      if ($kurstag->themen != $this->request->data->Themen) {
        $veraenderteEigenschaften['themen'] = $this->request->data->Themen;
      }
      if ($kurstag->hausarbeit != $this->request->data->Hausarbeit) {
        $veraenderteEigenschaften['hausarbeit'] = $this->request->data->Hausarbeit;
      }
      if ($kurstag->unterrichtsinhalt != $this->request->data->Unterrichtsinhalt) {
        $veraenderteEigenschaften['unterrichtsinhalt'] = $this->request->data->Unterrichtsinhalt;
      }
    }

    if ($this->toolSettings->status3gErfassen) {
      $veraenderteEigenschaften['geprueft_3g'] = $this->request->data->Geprueft3g ?? false;
    }

    if (count($veraenderteEigenschaften) == 0) {
      return ''; 
    }

    
    $updatedKtKBuch = \NewAnwesenheitAPI::updateKtKBuch($kurstag, $veraenderteEigenschaften);
    
    if ($updatedKtKBuch && !empty($veraenderteEigenschaften)) {
      $statusResult = $this->changedAnwesenheit($kurstag, $veraenderteEigenschaften);
    } elseif (!$updatedKtKBuch) {
      $statusResult = self::EINTRAGUNG_FEHLER;
    }

    return $statusResult;
  }

  
  protected function changedAnwesenheit(\Kurstag $newKurstag, array $veraenderteEigenschaften): string
  {
    if (array_key_exists('klassenbuchueok', $veraenderteEigenschaften) && $veraenderteEigenschaften['klassenbuchueok'] == 2 && $this->shouldSendToEinrichtungIfModifiedUE()) {
      $viewModel = new AnwesenheitenSpeichernAbweichendeUEEMailViewModel();
      $viewModel->kurstag = $newKurstag;
      $mailPresenter = new AnwesenheitenSpeichernAbweichendeUEEMailPresenter($viewModel);
      $mail = new \Kufer\Mail\EMail\EMailHTML($mailPresenter->getSubject(), $mailPresenter->getContent());
      $mail->addKuferToolsFooter('Abweichende UE bei Klassenbuch', $this->getUser(), $newKurstag);

      $sender = \Kufer\Mail\Sender\EMailSenderFactory::create();
      $recipientSettings = new EMailEinrichtungRecipientToolsKursSettings($newKurstag->kurs);
      $recipientSettings
        ->setSettingMailToPlanendenMitarbeiter($this->toolSettings->anwUeModifiedEMailToPlanenderMitarbeiter)
        ->setSettingMailToVerwaltendenMitarbeiter($this->toolSettings->anwUeModifiedEMailToVerwaltenderMitarbeiter)
        ->setSettingMailToVerantwortendenMitarbeiter($this->toolSettings->anwUeModifiedEMailToVerantwortenderMitarbeiter)
        ->setSettingsVhsEMail($this->toolSettings->anwUeModifiedEmailAnEinrichtungCustom ?? null);
      if (!$sender->sendFromPersonToEinrichtung($mail, \SessionOperations::getCurrentWebToolsPerson(), $recipientSettings)->hasSentAnyMails()) {
        return self::EINTRAGUNG_KLASSENBUCH_ERFOLGREICH_EMAIL_FEHLER;
      }
    }

    return self::EINTRAGUNG_KLASSENBUCH_ERFOLGREICH;
  }

  private function shouldSendToEinrichtungIfModifiedUE(): bool
  {
    return $this->toolSettings->anwUeModifiedEMail;
  }

  private function saveUnterrichtsmittel($kurstag)
  {
    $statusResult = '';
    $alleUnterrichtsMittel = array();
    $user = $this->getUser();
    
    if ($this->toolSettings->useUnterrichtsMittelErf) {
      if (is_array($this->request->data->Unterrichtsmittel)) {
        $neueUnterrichtsMittel = array();
        foreach ($this->request->data->Unterrichtsmittel as $unterrichtsmittel) {
          
          $uMittel = \Datamodul::toDatamodul('Unterrichtsmittel', $unterrichtsmittel);
          
          if (!$unterrichtsmittel->id > 0) {
            $uMittel = \Datamodul::toDatamodul('Unterrichtsmittel', $unterrichtsmittel);
            $uMittel->erfasstam = \DateTimeOperations::getDateNow();
            $uMittel->erfasstvon = \SessionOperations::getCurrentWebToolsUserKennung();
            $uMittel->bearbdatum = \DateTimeOperations::getDateNow();
            $uMittel->bearbeiter = \SessionOperations::getCurrentWebToolsUserKennung();
            $uMittel->knr = $kurstag->knr;
            $uMittel->dnr = $user->dnr;
            $neueUnterrichtsMittel[] = $uMittel;
          }
          $alleUnterrichtsMittel[] = $uMittel;
        }
        try {
          
          
          
          if (count($neueUnterrichtsMittel) > 0) {
            if (\NewAnwesenheitAPI::unterrichtsmittelEintragen($neueUnterrichtsMittel)) {
              $statusResult = self::UNTERRICHTSMITTEL_EINTRAEGEN_ERFOLGREICH;
            } else {
              $statusResult = self::EINTRAGUNG_FEHLER;
            }
          }
          
        } 
        catch (\Exception $ex) {
          $statusResult = self::EINTRAGUNG_FEHLER_EXCEPTION;
        }
      } 
    } 
    
    
    $this->response->unterrichtsMittel = $alleUnterrichtsMittel;

    return $statusResult;
  }

  private function getAnwInfoFromDb()
  {
    $dbwAnw = new \DBWorkAnwesenheit2();
    $dbwKurstage = KurstageUtils::getDbwKursTage($this->toolSettings);
    $kurstag = $dbwKurstage->getKurstag($this->request->kurstagId);

    $stati = AnwesenheitenUtils::getStatusArray($this->toolSettings);

    return $dbwAnw->getAnwesenheiten($kurstag->knr, $kurstag->datum, $kurstag->datum, $stati, $kurstag->id);
  }

  
  private function getAnwInfoFromRequest()
  {
    $anwInfo = $this->request->data->AnwesenheitsInfo;

    if (is_array($anwInfo) && count($anwInfo) > 0) {
      $anwInfoDatamodul = array();
      foreach ($anwInfo as $anwInfoAsObject) {
        $anwInfoDatamodul[] = \Datamodul::toDatamodul('Anwesenheit', $anwInfoAsObject, array('_eanws' => 'AnwesenheitExtra'));
      }

      return $anwInfoDatamodul;
    }

    return array();
  }
}

class AnwesenheitenSpeichernRequest extends \Kufer\Web\KuferTools\Basis\UseCase\XsrfRequest
{
  public $anwesenheitsInfo;
  public $data;
  public $kurstagId;
  public $arbeitsbericht;
  public $lehrinhalt;
  public $klassenbuchueok;
  public $klassenbuchabwue;
  public $klassenbuchgrund;
  public $unterrichtsmittel;
  public $verhaltenseintrag;
}

class AnwesenheitenSpeichernResponse extends \Kufer\Web\KuferTools\Basis\UseCase\ToolResponse
{
  public $statusCode = array();
  public $unterrichtsMittel = array();
  public $anwExtraStoreAry = array();
  public $verhaltensInfo = array();
}