<?php

declare(strict_types=1);

namespace App\Repositories;

use Core\Repository;

class TerritoryRepository extends Repository
{
    protected string $table      = 'territories';
    protected string $primaryKey = 'id';

    public function countAll(string $search = ''): int
    {
        if ($search !== '') {
            $row = $this->database->first(
                'SELECT COUNT(*) AS n FROM territories WHERE name LIKE :s OR description LIKE :s',
                ['s' => '%' . $search . '%']
            );
        } else {
            $row = $this->database->first('SELECT COUNT(*) AS n FROM territories');
        }

        return (int) ($row['n'] ?? 0);
    }

    /** @return list<array<string,mixed>> */
    public function findPaged(int $page, int $perPage, string $search = ''): array
    {
        $offset = ($page - 1) * $perPage;

        if ($search !== '') {
            return $this->database->query(
                'SELECT * FROM territories WHERE name LIKE :s OR description LIKE :s
                 ORDER BY name ASC LIMIT :limit OFFSET :offset',
                ['s' => '%' . $search . '%', 'limit' => $perPage, 'offset' => $offset]
            );
        }

        return $this->database->query(
            'SELECT * FROM territories ORDER BY name ASC LIMIT :limit OFFSET :offset',
            ['limit' => $perPage, 'offset' => $offset]
        );
    }

    /** @return list<array<string,mixed>> */
    public function allOrdered(): array
    {
        return $this->database->query('SELECT * FROM territories ORDER BY name ASC');
    }

    public function householdCount(int|string $territoryId): int
    {
        $row = $this->database->first(
            'SELECT COUNT(*) AS n FROM households WHERE territory_id = :id',
            ['id' => $territoryId]
        );

        return (int) ($row['n'] ?? 0);
    }

    /** @return list<array<string,mixed>> */
    public function householdCountsKeyed(): array
    {
        $rows = $this->database->query(
            'SELECT territory_id, COUNT(*) AS n FROM households GROUP BY territory_id'
        );

        $counts = [];
        foreach ($rows as $row) {
            $counts[(int) $row['territory_id']] = (int) $row['n'];
        }

        return $counts;
    }

    /** @return list<string> */
    public function distinctStreets(int|string $territoryId): array
    {
        $rows = $this->database->query(
            'SELECT DISTINCT street_name FROM households
             WHERE territory_id = :id AND street_name IS NOT NULL AND street_name != \'\'
             ORDER BY street_name ASC',
            ['id' => $territoryId]
        );

        return array_column($rows, 'street_name');
    }
}
