<?php

// SPDX-FileCopyrightText: 2023 Icinga GmbH <https://icinga.com>
// SPDX-License-Identifier: GPL-3.0-or-later

namespace Icinga\Module\Notifications\Widget;

use Icinga\Module\Notifications\Common\Database;
use Icinga\Module\Notifications\Model\Contact;
use ipl\Html\Attributes;
use ipl\Html\BaseHtmlElement;
use ipl\Html\HtmlElement;
use ipl\Html\Text;
use ipl\Stdlib\Filter;
use Psr\Http\Message\ServerRequestInterface;

class MemberSuggestions extends BaseHtmlElement
{
    protected $tag = 'ul';

    protected ?string $searchTerm = null;

    protected ?string $originalValue = null;

    /** @var string[] */
    protected array $excludeTerms = [];

    public function setSearchTerm(string $term): static
    {
        $this->searchTerm = $term;

        return $this;
    }

    public function setOriginalValue(string $term): static
    {
        $this->originalValue = $term;

        return $this;
    }

    public function excludeTerms(array $terms): static
    {
        $this->excludeTerms = $terms;

        return $this;
    }

    /**
     * Load suggestions as requested by the client
     *
     * @param ServerRequestInterface $request
     *
     * @return $this
     */
    public function forRequest(ServerRequestInterface $request): static
    {
        if ($request->getMethod() !== 'POST') {
            return $this;
        }

        $requestData = json_decode($request->getBody()->read(8192), true);
        if (empty($requestData)) {
            return $this;
        }

        $this->setSearchTerm($requestData['term']['label']);
        $this->setOriginalValue($requestData['term']['search']);

        $toExclude = array_filter($requestData['exclude'] ?? [], function ($term) {
            return is_numeric($term);
        });

        $this->excludeTerms($toExclude);

        return $this;
    }

    protected function assemble(): void
    {
        $contactFilter = Filter::like('full_name', $this->searchTerm);

        if (! empty($this->excludeTerms)) {
            $contactFilter = Filter::all(
                $contactFilter,
                Filter::any(
                    Filter::equal('full_name', $this->originalValue),
                    Filter::unequal('id', $this->excludeTerms)
                )
            );
        }

        foreach (Contact::on(Database::get())->filter($contactFilter) as $contact) {
            $this->addHtml(
                new HtmlElement(
                    'li',
                    null,
                    new HtmlElement(
                        'input',
                        Attributes::create([
                            'type'        => 'button',
                            'value'       => $contact->full_name,
                            'data-label'  => $contact->full_name,
                            'data-search' => $contact->id,
                            'data-class'  => 'contact'
                        ])
                    )
                )
            );
        }

        if ($this->isEmpty()) {
            $this->addHtml(
                new HtmlElement(
                    'li',
                    Attributes::create(['class' => 'nothing-to-suggest']),
                    new HtmlElement('em', null, Text::create(t('Nothing to suggest')))
                )
            );
        }
    }

    public function renderUnwrapped(): string
    {
        $this->ensureAssembled();

        if ($this->isEmpty()) {
            return '';
        }

        return parent::renderUnwrapped();
    }
}
