<?php

namespace App\Services;

class LegGovDiscoveryService
{
    /**
     * Instalações PHP puro homologadas nesta geração do sistema.
     *
     * A estrutura é validada antes de qualquer instalação ser aceita.
     */
    private array $phpPuroPaths = [
        '/var/www/arapiraca',
        '/var/www/belem',
        '/var/www/campogrande',
        '/var/www/doisriachos',
        '/var/www/feiragrande',
        '/var/www/jacare',
        '/var/www/murici',
        '/var/www/portodepedras',
        '/var/www/santoantonio',
        '/var/www/satuba',
    ];

    public function discover(): array
    {
        $apps = [];

        foreach ($this->discoverLaravel() as $app) {
            $apps[$app['id']] = $app;
        }

        foreach ($this->discoverPhpPuro() as $app) {
            $apps[$app['id']] = $app;
        }

        uasort($apps, function (array $a, array $b) {
            return strcasecmp($a['name'], $b['name']);
        });

        return array_values($apps);
    }

    private function discoverLaravel(): array
    {
        $apps = [];

        foreach (glob('/etc/apache2/sites-enabled/*.conf') ?: [] as $file) {
            $content = @file_get_contents($file);

            if ($content === false) {
                continue;
            }

            preg_match_all(
                '/<VirtualHost\b[^>]*>(.*?)<\/VirtualHost>/is',
                $content,
                $blocks
            );

            foreach ($blocks[1] ?? [] as $block) {
                if (!preg_match(
                    '/^\s*DocumentRoot\s+["\']?([^"\'\s]+)["\']?/mi',
                    $block,
                    $rootMatch
                )) {
                    continue;
                }

                $documentRoot = rtrim($rootMatch[1], '/');

                if (!preg_match(
                    '#^(/var/www/leggov-[^/]+)/public$#',
                    $documentRoot,
                    $appMatch
                )) {
                    continue;
                }

                $path = $appMatch[1];
                $baseName = basename($path);
                $lower = strtolower($baseName);

                if (
                    str_contains($lower, 'backup') ||
                    str_contains($lower, '_backup') ||
                    $baseName === 'leggov-test' ||
                    $baseName === 'leggov-central'
                ) {
                    continue;
                }

                if (
                    !is_file($path.'/artisan') ||
                    !is_file($path.'/composer.json') ||
                    !is_file($path.'/.env')
                ) {
                    continue;
                }

                $env = $this->readEnv($path.'/.env');

                preg_match(
                    '/^\s*ServerName\s+([^\s#]+)/mi',
                    $block,
                    $serverMatch
                );

                $domain = $serverMatch[1] ?? null;

                $id = 'laravel:'.$path;

                if (!isset($apps[$id])) {
                    $apps[$id] = [
                        'id' => $id,
                        'name' => $this->displayName($baseName, 'laravel'),
                        'slug' => $baseName,
                        'type' => 'laravel',
                        'technology' => 'Laravel',
                        'path' => $path,
                        'database' => $env['DB_DATABASE'] ?? null,
                        'domains' => [],
                    ];
                }

                if (
                    $domain &&
                    !in_array($domain, $apps[$id]['domains'], true)
                ) {
                    $apps[$id]['domains'][] = $domain;
                }
            }
        }

        return array_values($apps);
    }

    private function discoverPhpPuro(): array
    {
        $apps = [];

        foreach ($this->phpPuroPaths as $path) {
            if (!$this->isValidPhpPuro($path)) {
                continue;
            }

            $baseName = basename($path);
            $env = $this->readEnv($path.'/.env');

            $id = 'php:'.$path;

            $apps[$id] = [
                'id' => $id,
                'name' => $this->displayName($baseName, 'php'),
                'slug' => $baseName,
                'type' => 'php',
                'technology' => 'PHP puro',
                'path' => $path,
                'database' => $env['DB_DATABASE']
                    ?? $env['DB_NAME']
                    ?? $env['DATABASE_NAME']
                    ?? null,
                'domains' => $this->domainsForPath($path),
            ];
        }

        return array_values($apps);
    }

    private function isValidPhpPuro(string $path): bool
    {
        $lower = strtolower(basename($path));

        if (
            str_contains($lower, 'backup') ||
            str_contains($lower, 'antes-deploy')
        ) {
            return false;
        }

        return is_dir($path)
            && is_file($path.'/.env')
            && is_file($path.'/src/db.php')
            && is_file($path.'/public/index.php')
            && !is_file($path.'/artisan');
    }

    private function domainsForPath(string $path): array
    {
        $domains = [];

        foreach (glob('/etc/apache2/sites-enabled/*.conf') ?: [] as $file) {
            $content = @file_get_contents($file);

            if ($content === false) {
                continue;
            }

            preg_match_all(
                '/<VirtualHost\b[^>]*>(.*?)<\/VirtualHost>/is',
                $content,
                $blocks
            );

            foreach ($blocks[1] ?? [] as $block) {
                if (!preg_match(
                    '/^\s*DocumentRoot\s+["\']?([^"\'\s]+)["\']?/mi',
                    $block,
                    $rootMatch
                )) {
                    continue;
                }

                $root = rtrim($rootMatch[1], '/');

                if (
                    $root !== $path &&
                    $root !== $path.'/public'
                ) {
                    continue;
                }

                if (preg_match(
                    '/^\s*ServerName\s+([^\s#]+)/mi',
                    $block,
                    $serverMatch
                )) {
                    $domain = $serverMatch[1];

                    if (!in_array($domain, $domains, true)) {
                        $domains[] = $domain;
                    }
                }
            }
        }

        return $domains;
    }

    private function readEnv(string $file): array
    {
        $result = [];

        foreach (
            @file($file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) ?: []
            as $line
        ) {
            $line = trim($line);

            if (
                $line === '' ||
                str_starts_with($line, '#') ||
                !str_contains($line, '=')
            ) {
                continue;
            }

            [$key, $value] = explode('=', $line, 2);

            $result[trim($key)] = trim(trim($value), "\"'");
        }

        return $result;
    }

    private function displayName(string $name, string $type): string
    {
        if ($type === 'laravel') {
            $name = preg_replace('/^leggov-/', '', $name);
        }

        $special = [
            'arapiraca' => 'Arapiraca',
            'belem' => 'Belém',
            'bocadamata' => 'Boca da Mata',
            'campogrande' => 'Campo Grande',
            'doisriachos' => 'Dois Riachos',
            'feiragrande' => 'Feira Grande',
            'jacare' => 'Jacaré dos Homens',
            'minador' => 'Minador do Negrão',
            'murici' => 'Murici',
            'portodepedras' => 'Porto de Pedras',
            'portoreal' => 'Porto Real do Colégio',
            'santoantonio' => 'Santo Antônio',
            'satuba' => 'Satuba',
        ];

        return $special[$name]
            ?? ucwords(str_replace(['-', '_'], ' ', $name));
    }
}
