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

namespace Kufer\Web\Classes\Dbfilter;

use Kufer\Web\Classes\Db\DBWorkAktuellesFreigabe;
use Kufer\Web\Classes\Identifier\Identifier;


class AktuellesWTSQLFilter extends BasicSQLFilter
{
  private const FILTER_OPTION_FAECHER = 'faecher';
  private const FILTER_OPTION_AKT_FAECHER = 'akt_faecher';
  private const FILTER_OPTION_FREIGABE = 'akt_freigabe';

  protected function __construct()
  {
    parent::__construct();
    $this->registerDb('Id', 'id', static::TYPE_INTEGER);
    $this->registerDb('Title', 'titel', static::TYPE_STRING);
    $this->registerDb('Content', 'inhalt', static::TYPE_STRING);
    $this->registerDb('CreatedAt', 'erstelldatum', static::TYPE_DATETIME);
    $this->registerDb('Author', 'autor_id', static::TYPE_IDENTIFIER_NO_GUID);
    $this->registerDb('Benutzergruppe', 'benutzergruppe', static::TYPE_STRING);
    $this->registerDb('LastEditedBy', 'letzter_bearbeiter', static::TYPE_STRING);
    $this->registerDb('LastEditedAt', 'letzter_bearbeiter_datum', static::TYPE_DATETIME);
    $this->registerDb('DnrPrivatnachricht', 'dnr_privatnachricht', static::TYPE_STRING);
    $this->registerDb('ValidUntil', 'gueltigbis', static::TYPE_DATE);
    $this->registerDb('Bezirk', 'bezirk', static::TYPE_STRING);
    $this->registerForeignDb(
      'FachbereichId',
      $this->addToBuilder(),
      static function(\DBOperation $dboperation, $fachKennz): \SelectQueryBuilder {
        return (new \SelectQueryBuilder($dboperation))
          ->select('akt_id')
          ->from('web_akt_fachb')
          ->where('fachb_kennz = :fachKennz:')
          ->paramString('fachKennz', $fachKennz);
      },
      static function(\DBOperation $dboperation, $fachKennzAry): \SelectQueryBuilder {
        return (new \SelectQueryBuilder($dboperation))
          ->select('akt_id')
          ->from('web_akt_fachb')
          ->where('fachb_kennz IN (:fachKennz:)')
          ->paramStringArray('fachKennz', $fachKennzAry);
      }
    );
  }

  public function getTablePraeffix(): string
  {
    return 'web_aktuelles';
  }

  protected function addToBuilder(): callable
  {
    return static function(\SelectQueryBuilder $toAdd, \SelectQueryBuilder $result): \SelectQueryBuilder {
      $var = $result->uniqueVar();

      return $result->and(":table:.id IN (:$var:)")
        ->paramSelectQuery($var, $toAdd);
    };
  }

  public function equalsId($id): IFilter
  {
    $this->applyFilterCurrent(
      static::FILTER_OPTION_ID,
      SQLFilterUtils::filterEqualsIdInt('id', $id)
    );

    return $this;
  }

  public function inId(iterable $ids): IFilter
  {
    $this->applyFilterCurrent(
      static::FILTER_OPTION_ID,
      SQLFilterUtils::filterInIdInt('id', $ids)
    );

    return $this;
  }

  
  public function hasBenutzergruppe(int $benutzergruppe): AktuellesWTSQLFilter
  {
    $this->any(static function(AktuellesWTSQLFilter $filter) use ($benutzergruppe): AktuellesWTSQLFilter {
      $filter->equalsBenutzergruppe("$benutzergruppe");
      $filter->likeBenutzergruppe("$benutzergruppe,%");
      $filter->likeBenutzergruppe("%,$benutzergruppe");
      $filter->containsBenutzergruppe(",$benutzergruppe,");

      return $filter;
    });

    return $this;
  }

  
  public function hasAnyBenutzergruppen(array $benutzergruppen): AktuellesWTSQLFilter
  {
    $this->any(static function(AktuellesWTSQLFilter $filter) use ($benutzergruppen): AktuellesWTSQLFilter {
      foreach ($benutzergruppen as $benutzergruppe) {
        $filter->hasBenutzergruppe($benutzergruppe);
      }

      return $filter;
    });

    return $this;
  }

  public function hasPersonPrivatenachricht(\Benutzer $user): AktuellesWTSQLFilter
  {
    return $this->hasPersonPrivatenachrichtWithIds(
      $user->getDnrIdentifier(),
      $user->getAnrIdentifier(),
      $user->getTnrIdentifier(),
      $user->getBenIdentifier()
    );
  }

  public function hasPersonPrivatenachrichtWithIds(
    ?Identifier $dnId,
    ?Identifier $anId,
    ?Identifier $tnId,
    ?Identifier $benId
  ): AktuellesWTSQLFilter {
    $this->any(static function(AktuellesWTSQLFilter $filter) use ($dnId, $anId, $tnId, $benId): void {
      $filter->hasOldDozentPrivatenaricht($dnId);

      $filter->all(static function(AktuellesWTSQLFilter $filter) use ($dnId, $anId, $tnId, $benId): void {
        $filter->equalsDnrPrivatnachricht('-2');

        $idAndTypeAry = array(
          array($dnId, 'D'),
          array($anId, 'A'),
          array($tnId, 'T'),
          array($benId, 'M')
        );

        $filterFreigabe = AktuellesFreigabeSQLFilter::create();
        $filterFreigabe->any(static function(AktuellesFreigabeSQLFilter $filterFreigabe) use ($idAndTypeAry): void {
          foreach ($idAndTypeAry as $idAndType) {
            
            list($id, $type) = $idAndType;
            if (is_null($id) || $id->isEmpty()) {
              continue;
            }

            $filterFreigabe->all(static function(AktuellesFreigabeSQLFilter $filterFreigabe) use ($id, $type): void {
              $filterFreigabe->equalsPersonId($id);
              $filterFreigabe->equalsPersonType($type);
            });
          }
        });

        $filter->applyAktuellesFreigabeFilter($filterFreigabe);
      });
    });

    return $this;
  }

  private function hasOldDozentPrivatenaricht(Identifier $dnId): void
  {
    if ($dnId->isEmpty(false)) {
      return;
    }

    $dnr = $dnId->getId();

    $this->all(static function(AktuellesWTSQLFilter $filter) use ($dnr): AktuellesWTSQLFilter {
      $filter->notAny(static function(AktuellesWTSQLFilter $filter) {
        $filter->equalsDnrPrivatnachricht('0');
        $filter->equalsDnrPrivatnachricht('-1');
        $filter->equalsDnrPrivatnachricht('-2');
        $filter->equalsDnrPrivatnachricht('');
      });

      $filter->any(static function(AktuellesWTSQLFilter $filter) use ($dnr) {
        $filter->equalsDnrPrivatnachricht("$dnr");
        $filter->likeDnrPrivatnachricht("$dnr,%");
        $filter->likeDnrPrivatnachricht("%,$dnr");
        $filter->containsDnrPrivatnachricht(",$dnr,");
      });

      return $filter;
    });
  }

  public function applyFaecherAdrFilter(FaecherAdrSQLFilter $filter): AktuellesWTSQLFilter
  {
    $filter->makeImmutable();
    if ($filter->isEmpty()) {
      return $this;
    }

    $this->applyFilterCurrent(
      static::FILTER_OPTION_FAECHER,
      static function(\SelectQueryBuilder $builder) use ($filter): \SelectQueryBuilder {
        $faecherAdrBuilder = \DBWorkFachAdr::getDefaultInstance($builder->getDBOperation()->dbnr)
          ->findByFilterQuery($filter)
          ->select('kennz');

        $faecherAktuellesBuilder = (new \SelectQueryBuilder($builder->getDBOperation()))
          ->select('akt_id')
          ->from('web_akt_fachb')
          ->and('fachb_kennz IN (:query:)')
          ->or('fachb_kennz = 0')
          ->paramSelectQuery('query', $faecherAdrBuilder);

        $queryId = $builder->uniqueVar();

        return $builder
          ->and(":table:.id IN (:$queryId:)")
          ->paramSelectQuery($queryId, $faecherAktuellesBuilder);
      }
    );

    return $this;
  }

  public function applyAktuellesFreigabeFilter(AktuellesFreigabeSQLFilter $filter): AktuellesWTSQLFilter
  {
    $filter->makeImmutable();
    if ($filter->isEmpty()) {
      return $this;
    }

    $this->applyFilterCurrent(
      static::FILTER_OPTION_FREIGABE,
      static function(\SelectQueryBuilder $builder) use ($filter): \SelectQueryBuilder {
        $builderFreigabe = DBWorkAktuellesFreigabe::getDefaultInstance($builder->getDBOperation()->dbnr)
          ->findByFilterQuery($filter)
          ->select(':table:.wa_id');

        $var = $builder->uniqueVar();

        return $builder
          ->and(":table:.id IN (:$var:)")
          ->paramSelectQuery($var, $builderFreigabe);
      }
    );

    return $this;
  }
}