<?php

declare(strict_types=1);

namespace Butschster\ContextGenerator\Source\Tree;

use Butschster\ContextGenerator\Application\Logger\LoggerPrefix;
use Butschster\ContextGenerator\Lib\Content\ContentBuilderFactory;
use Butschster\ContextGenerator\Modifier\ModifiersApplierInterface;
use Butschster\ContextGenerator\Source\Fetcher\SourceFetcherInterface;
use Butschster\ContextGenerator\Source\File\SymfonyFinder;
use Butschster\ContextGenerator\Source\SourceInterface;
use Psr\Log\LoggerInterface;

/**
 * Fetcher for Tree sources that generates hierarchical visualizations
 * @implements SourceFetcherInterface<TreeSource>
 */
final readonly class TreeSourceFetcher implements SourceFetcherInterface
{
    public function __construct(
        private string $basePath,
        private SymfonyFinder $finder,
        private ContentBuilderFactory $builderFactory = new ContentBuilderFactory(),
        #[LoggerPrefix(prefix: 'tree-source')]
        private ?LoggerInterface $logger = null,
    ) {}

    public function supports(SourceInterface $source): bool
    {
        $isSupported = $source instanceof TreeSource;
        $this->logger?->debug('Checking if source is supported', [
            'sourceType' => $source::class,
            'isSupported' => $isSupported,
        ]);
        return $isSupported;
    }

    public function fetch(SourceInterface $source, ModifiersApplierInterface $modifiersApplier): string
    {
        if (!$source instanceof TreeSource) {
            $errorMessage = 'Source must be an instance of TreeSource';
            $this->logger?->error($errorMessage, [
                'sourceType' => $source::class,
            ]);
            throw new \InvalidArgumentException($errorMessage);
        }

        $this->logger?->info('Fetching tree source content', [
            'description' => $source->getDescription(),
            'basePath' => $this->basePath,
            'sourcePaths' => $source->sourcePaths,
            'renderFormat' => $source->renderFormat,
            'hasModifiers' => !empty($source->modifiers),
        ]);

        $this->logger?->debug('Creating content builder');
        $builder = $this->builderFactory
            ->create()
            ->addTitle($source->getDescription());

        try {
            // Use SymfonyFinder to find files
            $finderResult = $this->finder->find($source, $this->basePath, $source->treeView->getOptions());

            // Add content to builder
            $builder->addCodeBlock($finderResult->treeView);
        } catch (\Throwable $e) {
            $errorMessage = \sprintf('Error while generating tree: %s', $e->getMessage());
            $this->logger?->error($errorMessage, [
                'error' => $e->getMessage(),
                'file' => $e->getFile(),
                'line' => $e->getLine(),
            ]);
            throw new \RuntimeException($errorMessage);
        }

        $content = $builder->build();
        $this->logger?->info('Tree source content fetched successfully', [
            'contentLength' => \strlen($content),
        ]);

        return $content;
    }
}
