<?php

namespace App\Command;

use App\Entity\Reference;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;

#[AsCommand(
    name: 'ImportReference',
    aliases: ['app:import-ref'],
    description: 'Script to use to crawl a directory and import references',
)]
class IngestReferenceCommand extends Command
{
    /**
     * Files found in the directory
     *
     * @var array
     */
    private array $files = [];

    /**
     * IO
     *
     * @var SymfonyStyle
     */
    private SymfonyStyle $io;

    /**
     * EntityManager
     *
     * @var EntityManagerInterface
     */
    private EntityManagerInterface $emi;

    /**
     * IngestReferenceCommand constructor.
     */
    public function __construct(
        EntityManagerInterface $emi,
        private string $dir = '',
        private string $name = '',
        private string $type = '',
        private string $label = ''
    ) {
        parent::__construct();

        $this->emi = $emi;
    }

    /**
     * {@inheritdoc}
     */
    protected function configure(): void
    {
        $this
            ->addArgument('directory', InputArgument::REQUIRED, 'Directory to crawl')
            ->addArgument('name', InputArgument::REQUIRED, 'Name of the reference')
            ->addArgument('type', InputArgument::REQUIRED, 'Type of the reference')
            ->addArgument('label', InputArgument::REQUIRED, 'Label of the reference')
        ;
    }

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $this->io = new SymfonyStyle($input, $output);
        $this->dir = $input->getArgument('directory');
        $this->name = $input->getArgument('name');
        $this->type = $input->getArgument('type');
        $this->label = $input->getArgument('label');

        if (!$this->dir || !file_exists($this->dir) ||!is_dir($this->dir)) {
            $this->io->error('Directory not specific or does not exist');
            return Command::FAILURE;
        }

        if (!$this->name) {
            $this->io->error('No name specified');
            return Command::FAILURE;
        }

        if (!$this->type) {
            $this->io->error('No type specified');
            return Command::FAILURE;
        }

        if (!$this->label) {
            $this->io->error('No label specified');
            return Command::FAILURE;
        }

        $this->io->note("Crawling {$this->dir} and ingesting {$this->name} as {$this->type}:{$this->label}");

        foreach ($this->getFiles() as $file) {
            $ref = $this->processFile($file);

            $this->emi->persist($ref);
        }

        $this->emi->flush();

        return Command::SUCCESS;
    }

    public function getFiles(): array
    {
        $this->files = glob($this->dir . '/*.md');

        if(!$this->files || count($this->files) === 0) {
            $this->io->warning("No files found in this directory\n{$this->dir}");
            $this->files = [];
        }

        return $this->files;
    }

    public function processFile(string $file): Reference|bool
    {
        $this->io->info("Processing {$file}");
        $md = trim(file_get_contents($file));
        $ref = new Reference();

        if (!$md) {
            $this->io->warning("File is empty\n{$file}");
            return false;
        }

        $match = [];
        $label = str_replace("{\$ndx}", "", $this->label);
        if(preg_match("/([\d]+)/", $file, $match)) {
            $ndx = ltrim($match[1], "0");
            $label = str_replace("{\$ndx}", $ndx, $this->label);
            $ref->setNdx($ndx);
        } elseif (preg_match("/\(([^\)]+)\)/", $file, $match)) {
            $label = $match[1];
        }

        $ref->setContent($md);
        $ref->setName($this->name);
        $ref->setType($this->type);

        if ($this->type == 'cd') {
            $label = substr(basename($file), 0, -3);
        }
        $ref->setLabel($label);

        $this->io->success("Ingested {$this->name} as {$this->type}:{$label}");

        return $ref;
    }
}
