<?php

namespace Signteer\Web\Admin\Page\Sheet;

use Plainwork\Http\Request;
use Plainwork\Http\Redirect;
use Plainwork\Http\Dispatch;
use Plainwork\Ui\Html;
use Signteer\Core\Action\Signup\AssignVolunteer;
use Signteer\Core\Action\Signup\SendConfirmationEmailToVolunteer;
use Signteer\Core\Criteria\TaskCriteria;
use Signteer\Core\Criteria\VolunteerCriteria;
use Signteer\Core\Criteria\SignupCriteria;
use Signteer\Core\Finder\SheetFinder;
use Signteer\Core\Finder\TaskFinder;
use Signteer\Core\Finder\SignupFinder;
use Signteer\Core\Finder\VolunteerFinder;
use Signteer\Core\Model\Task;
use Signteer\Core\Model\Volunteer;

final class AssignVolunteerPage
{
    public $actionAssignVolunteer = AssignVolunteer::class;
    public $notifyVolunteerAction = SendConfirmationEmailToVolunteer::class;
    public $taskFinder = TaskFinder::class;
    public $sheetFinder = SheetFinder::class;
    public $signupFinder = SignupFinder::class;
    public $volunteerFinder = VolunteerFinder::class;

    public function __invoke(Request $request)
    {
        $sheetId = $request->getQueryParam('sheet');
        if (!$sheetId) {
            return new Redirect('admin/sheet');
        }

        $taskId = $request->getQueryParam('task');
        if (!$taskId) {
            return new Redirect('admin/sheet/' . $sheetId);
        }

        $c = (new TaskCriteria())->whereSheetId('=', $sheetId)->whereId('=', $taskId);
        $task = current($this->taskFinder->find($c));
        if (!$task) {
            return new Redirect('admin/sheet/' . $sheetId);
        }

        $signupCriteria = (new SignupCriteria())->whereSheetId('=', $sheetId);
        $areadySignedUpVolunteerIds = $this->signupFinder->findVolunteerIds($signupCriteria);

        $volunteerId = $request->getQueryParam('volunteer');
        if ($volunteerId && in_array($volunteerId, $areadySignedUpVolunteerIds)) {
            $volunteerId = null;
        }

        $volunteer = (null !== $volunteerId) ? $this->volunteerFinder->get($volunteerId) : null;
        if (null !== $volunteer) {
            return $this->handleConfirm($request, $task, $volunteer);
        }

        $volunteerCriteria = (new VolunteerCriteria());
        if ($areadySignedUpVolunteerIds) {
            $volunteerCriteria = $volunteerCriteria->whereId('<>', $areadySignedUpVolunteerIds);
        }

        $limit = 10;
        $offset = $request->getQueryParam('offset-') ?? 0;
        $count = $this->volunteerFinder->count($volunteerCriteria);

        if (!$count) {
            return new Redirect('./new');
            // return new Dispatch('./new');
        }

        $ms = $this->volunteerFinder->find($volunteerCriteria, null, $limit, $offset);

        $html = new Html();

        $ret = $html->menu()->setVertical();
        foreach ($ms as $m) {
            $id = $m->getId();
            $ret_ = $html->link('.', ['volunteer' => $id], $m);
            $ret->add($ret_);
        }

        $ret = $html->blockList($html->el('p', '__Click on volunteer to assign to task.__'), $ret);

        if ($count > $limit) {
            $pager = $html->pager($count, $limit)->setOffset($offset);
            $ret->add($pager);
        }

        $ret = $html->main($ret);
        $ret->title = $html->el('h1', '__Available volunteers__');
        $ret->titleMenu->add($html->link('./new', [], '__Create new volunteer__'));

        return $ret;
    }

    public function handleConfirm(Request $request, Task $task, Volunteer $volunteer)
    {
        $html = new Html();

        $ret = $html->blockList();

        $taskId = $task->getId();
        $sheetId = $task->getSheetId();

        $ret->add(
            $html->dl()->asTable()
                ->add('__Task__', $task->getTitle())
                ->add('__Volunteer__', $volunteer)
            );

        $form = $html->form();

        $v = $this->notifyVolunteerAction->isEnabled();
        $form->add($html->checkboxInput('notify')->setLabel('__Send email notification__')->setValue($v));

        $values = $form->grab($request);
        if ($values) {
            if ($form->isValid()) {

                if (!$values['notify']) {
                    $this->notifyVolunteerAction->disable();
                }

                $res = ($this->actionAssignVolunteer)($task->getId(), $volunteer->getId());
                if ($res->isOk()) {
                    $ret = '__Volunteer assigned__';

                    $ret = $html->main($ret);
                    $ret->title = $html->el('h1', '__Volunteer assigned__');
                    $ret->afterContentMenu->add($html->link('admin/sheet/' . $sheetId, [], '__View sheet__'));

                    $signupCriteria = (new SignupCriteria())->whereTaskId('=', $taskId);
                    $countSignups = $this->signupFinder->count($signupCriteria);
                    if ($countSignups < $task->getSpots()){
                        $ret->afterContentMenu
                            ->add($html->link('admin/sheet/' . $sheetId . '/assign', ['task' => $taskId], '__Assign another volunteer__'), 10)
                            ;
                    }

                    return $ret;
                }

                $ret->add($html->dl('__Error__', $html->formErrors($res->getErrors())));
            }
        }

        $ret->add($html->dl(null, $form->input('notify')));
        $ret->add($html->dl(null, $html->button('__Assign volunteer__')));

        $ret = $form->setContent($ret);

        $ret = $html->main($ret);
        $ret->title = $html->el('h1', '__Assign volunteer to task__');
        $ret->titleMenu->add($html->link('./create', [], '__Add new__'));

        return $ret;
    }
}
