<?php

declare(strict_types=1);

namespace Atdt\Screens;

use Atdt\Ctx;
use Atdt\In;
use Atdt\Pipe;
use Atdt\Screen;

/**
 * The user list (SPEC §10.6): every active caller, paged.
 */
final class UserListScreen implements Screen
{
    private const PER_PAGE = 14;

    public function describe(): string
    {
        return 'Reading the user list';
    }

    public function enter(Ctx $c): array
    {
        $rows = $c->db()->all(
            "SELECT handle, location, level, calls, last_login FROM users
             WHERE status = 'active' ORDER BY handle"
        );
        $page = max(0, (int)$c->get('page', 0));
        $pages = max(1, (int)ceil(max(1, count($rows)) / self::PER_PAGE));
        $page = min($page, $pages - 1);
        $c->set('page', $page);

        $o = $c->out()->cls();
        $o->at(2, 1)->txt($c->center($c->tstr('users.title')));
        $o->at(3, 1)->fg(8)->txt($c->center(str_repeat('─', 50)))->reset();
        $o->at(5, 4)->txt($c->tstr('users.columns', ['PG' => ($page + 1) . '/' . $pages]));
        $row = 7;
        foreach (array_slice($rows, $page * self::PER_PAGE, self::PER_PAGE) as $u) {
            $o->at($row++, 4)->txt($c->pipe(sprintf(
                '|15%-20s |07%-24s |03%3d |07%5d  |08%s',
                Pipe::escape(mb_strimwidth((string)$u['handle'], 0, 20)),
                Pipe::escape(mb_strimwidth((string)($u['location'] ?? ''), 0, 24)),
                (int)$u['level'],
                (int)$u['calls'],
                ($u['last_login'] === null ? 'never' : $c->localStamp((string)$u['last_login'], 'Y-m-d'))
            )));
        }
        $o->at(21, 1)->txt($c->center($c->tstr('users.prompt')));
        return [$c->ansi($o->reset()->str()), $c->hotkey()];
    }

    public function input(Ctx $c, In $in): array
    {
        if ($in->kind !== 'key') {
            return [$c->bell()];
        }
        switch (strtoupper((string)$in->key)) {
            case 'N':
                $c->set('page', (int)$c->get('page', 0) + 1);
                return $this->enter($c);
            case 'P':
                $c->set('page', max(0, (int)$c->get('page', 0) - 1));
                return $this->enter($c);
            case 'Q':
            case 'ESC':
                return $c->pop();
            default:
                return $this->enter($c);
        }
    }
}
