<?php

declare(strict_types=1);

namespace Atdt;

/**
 * What a door's daily cron hook receives (SPEC §13.5): its store and a
 * logger — no session, no caller. Keep hooks under five seconds.
 *
 * 1.5.5: cron hooks may also read board rumors and post an announcement
 * message as the sysop (a round chronicle, a season notice) — the two
 * sanctioned holes in the wall, both mediated here so doors still never
 * touch a board table themselves.
 */
final class DoorCronContext
{
    public function __construct(
        private readonly DoorStore $store,
        private readonly string $slug,
        private readonly Settings $settings,
        private readonly ?Db $db = null,
    ) {
    }

    public function kv(): DoorStore
    {
        return $this->store;
    }

    public function table(string $name): DoorTable
    {
        return $this->store->table($name);
    }

    public function tx(callable $fn): mixed
    {
        return $this->store->tx($fn);
    }

    public function log(string $msg): void
    {
        atdt_log_event('info', 'door:' . $this->slug, mb_strimwidth($msg, 0, 200));
    }

    /** The board's timezone-aware "today", for once-a-day bookkeeping. */
    public function boardToday(): string
    {
        return Cron::boardToday($this->settings);
    }

    /** Recent approved board rumors (flavor for rendered briefings). */
    public function boardRumors(int $limit = 5): array
    {
        if ($this->db === null) {
            return [];
        }
        $rows = $this->db->all(
            'SELECT body FROM rumors WHERE approved = 1 ORDER BY id DESC LIMIT ' . max(1, min(10, $limit))
        );
        return array_map(fn(array $r) => (string)$r['body'], $rows);
    }

    /**
     * Post a message into a board area as the sysop (door announcements:
     * a round chronicle, a season opening). Fail-soft: false when the
     * area or the sysop account cannot be found.
     * @param list<string> $lines pipe-coded body lines
     */
    public function postMessage(string $areaTag, string $subject, array $lines): bool
    {
        if ($this->db === null) {
            return false;
        }
        return DoorRunner::postAsSysop($this->db, $this->settings, $this->slug, $areaTag, $subject, $lines);
    }
}
