<?php

declare(strict_types=1);

final class MyronLlmsTxtGenerator
{
    public function __construct(
        private readonly MyronContentRepository $repository,
        private readonly array $siteSettings,
    ) {
    }

    public function generate(): string
    {
        $siteTitle = trim((string) ($this->siteSettings['site_title'] ?? 'MyronCMS')) ?: 'MyronCMS';
        $description = trim((string) ($this->siteSettings['seo_default_description'] ?? ''));
        $pages = $this->repository->findPublishedIndexablePages();

        $lines = ['# ' . $siteTitle, ''];
        if ($description !== '') {
            $lines[] = '> ' . $this->singleLine($description);
            $lines[] = '';
        }

        $hasHierarchy = $this->hasHierarchy($pages);
        if (!$hasHierarchy) {
            $lines[] = '## Pages';
            $lines[] = '';
            foreach ($pages as $page) {
                $lines[] = $this->pageLine($page);
            }
            return rtrim(implode("\n", $lines)) . "\n";
        }

        $childrenByParent = [];
        $pagesById = [];
        foreach ($pages as $page) {
            $id = (string) ($page['id'] ?? '');
            if ($id !== '') {
                $pagesById[$id] = $page;
            }
            $parentId = trim((string) ($page['parent_page_id'] ?? ''));
            if ($parentId !== '') {
                $childrenByParent[$parentId][] = $page;
            }
        }

        $lines[] = '## Pages';
        $lines[] = '';
        foreach ($pages as $page) {
            $parentId = trim((string) ($page['parent_page_id'] ?? ''));
            if ($parentId !== '' && isset($pagesById[$parentId])) {
                continue;
            }

            $lines[] = $this->pageLine($page);
            foreach ($childrenByParent[(string) ($page['id'] ?? '')] ?? [] as $child) {
                $lines[] = '  ' . $this->pageLine($child);
            }
        }

        return rtrim(implode("\n", $lines)) . "\n";
    }

    /**
     * @param list<array<string, mixed>> $pages
     */
    private function hasHierarchy(array $pages): bool
    {
        foreach ($pages as $page) {
            if (trim((string) ($page['parent_page_id'] ?? '')) !== '') {
                return true;
            }
        }
        return false;
    }

    /**
     * @param array<string, mixed> $page
     */
    private function pageLine(array $page): string
    {
        $title = trim((string) (($page['version_title'] ?? '') ?: ($page['title'] ?? 'Untitled page'))) ?: 'Untitled page';
        $description = $this->truncate($this->singleLine((string) ($page['meta_description'] ?? '')), 140);
        return '- [' . str_replace([']', "\n", "\r"], ['', ' ', ' '], $title) . ']('
            . rtrim(myronAppUrl(), '/') . myronBuildPublicPageUrl((string) ($page['path'] ?? '/')) . '): '
            . $description;
    }

    private function singleLine(string $value): string
    {
        return trim((string) preg_replace('/\s+/', ' ', $value));
    }

    private function truncate(string $value, int $limit): string
    {
        if (strlen($value) <= $limit) {
            return $value;
        }

        return rtrim(substr($value, 0, max(0, $limit - 3))) . '...';
    }
}
