<?php

namespace App\Services;

class LegGovDiscoveryService
{
    /**
     * Instalações PHP puro LegGov já homologadas.
     */
    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',
    ];

    /**
     * Sistemas adicionais explicitamente homologados.
     *
     * connection_file será usado posteriormente pelo serviço de métricas.
     * Nenhuma senha é armazenada aqui.
     */
    private array $additionalSystems = [
        [
            'name' => 'Portal Câmara Arapiraca',
            'slug' => 'arapiraca-leg',
            'category' => 'legislativo',
            'category_label' => 'Legislativo',
            'path' => '/var/www/arapiraca-leg',
            'database' => 'leg_arapiraca',
            'connection_file' => '/var/www/arapiraca-leg/includes/conexao.php',
        ],
        [
            'name' => 'Portal Câmara Dois Riachos',
            'slug' => 'doisriachos-leg',
            'category' => 'legislativo',
            'category_label' => 'Legislativo',
            'path' => '/var/www/doisriachos-leg',
            'database' => 'leg_doisriachos',
            'connection_file' => '/var/www/doisriachos-leg/includes/conexao.php',
        ],
        [
            'name' => 'Portal Câmara Murici',
            'slug' => 'murici-leg',
            'category' => 'legislativo',
            'category_label' => 'Legislativo',
            'path' => '/var/www/murici-leg',
            'database' => 'leg_murici',
            'connection_file' => '/var/www/murici-leg/config/db.local.php',
        ],

        [
            'name' => 'Transparência Arapiraca',
            'slug' => 'arapiraca-leg-transparencia',
            'category' => 'transparencia',
            'category_label' => 'Transparência',
            'path' => '/var/www/arapiraca-leg-transparencia',
            'database' => null,
            'connection_file' => null,
        ],
        [
            'name' => 'Transparência Dois Riachos',
            'slug' => 'doisriachos-leg-transparencia',
            'category' => 'transparencia',
            'category_label' => 'Transparência',
            'path' => '/var/www/doisriachos-leg-transparencia',
            'database' => null,
            'connection_file' => null,
        ],
        [
            'name' => 'Transparência Murici',
            'slug' => 'murici-leg-transparencia',
            'category' => 'transparencia',
            'category_label' => 'Transparência',
            'path' => '/var/www/murici-leg-transparencia',
            'database' => null,
            'connection_file' => null,
        ],

        [
            'name' => 'Portal Legislativo Arapiraca',
            'slug' => 'legislativo-arapiraca',
            'category' => 'portal_legislativo',
            'category_label' => 'Portal Legislativo',
            'path' => '/var/www/legislativo-arapiraca',
            'database' => 'arapiracac',
            'connection_file' => '/var/www/legislativo-arapiraca/config/db.php',
        ],
        [
            'name' => 'Portal Legislativo Dois Riachos',
            'slug' => 'legislativo-doisriachos',
            'category' => 'portal_legislativo',
            'category_label' => 'Portal Legislativo',
            'path' => '/var/www/legislativo-doisriachos',
            'database' => 'doisriachosc',
            'connection_file' => '/var/www/legislativo-doisriachos/config/db.php',
        ],
        [
            'name' => 'Portal Legislativo Murici',
            'slug' => 'legislativo-murici',
            'category' => 'portal_legislativo',
            'category_label' => 'Portal Legislativo',
            'path' => '/var/www/legislativo-murici',
            'database' => 'muricic',
            'connection_file' => '/var/www/legislativo-murici/config/db.php',
        ],

        [
            'name' => 'Gabinete / Vereador',
            'slug' => 'vereador',
            'category' => 'gabinete',
            'category_label' => 'Gabinete / Vereador',
            'path' => '/var/www/vereador',
            'database' => 'vereador',
            'connection_file' => '/var/www/vereador/config.php',
        ],

        [
            'name' => 'Protocolo Murici',
            'slug' => 'muricip',
            'category' => 'protocolo',
            'category_label' => 'Protocolo',
            'path' => '/var/www/muricip',
            'database' => 'muricip',
            'connection_file' => '/var/www/muricip/config/config.php',
        ],

        [
            'name' => 'Patrimônio Murici',
            'slug' => 'patrimonio-murici',
            'category' => 'patrimonio',
            'category_label' => 'Patrimônio',
            'path' => '/var/www/patrimonio-murici',
            'database' => 'muricipp',
            'connection_file' => '/var/www/patrimonio-murici/config/config.php',
        ],
    ];

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

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

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

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

        uasort($apps, function (array $a, array $b) {
            $category = strcasecmp(
                $a['category_label'] ?? '',
                $b['category_label'] ?? ''
            );

            return $category !== 0
                ? $category
                : 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',
                        'category' => 'leggov',
                        'category_label' => 'LegGov',
                        'path' => $path,
                        'database' => $env['DB_DATABASE'] ?? null,
                        'domains' => [],
                        'connection_file' => $path.'/.env',
                    ];
                }

                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',
                'category' => 'leggov',
                'category_label' => 'LegGov',
                'path' => $path,
                'database' => $env['DB_DATABASE']
                    ?? $env['DB_NAME']
                    ?? $env['DATABASE_NAME']
                    ?? null,
                'domains' => $this->domainsForPath($path),
                'connection_file' => $path.'/.env',
            ];
        }

        return array_values($apps);
    }

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

        foreach ($this->additionalSystems as $system) {
            $path = $system['path'];

            if (!is_dir($path)) {
                continue;
            }

            $apps[] = [
                'id' => 'system:'.$path,
                'name' => $system['name'],
                'slug' => $system['slug'],
                'type' => 'php_external',
                'technology' => 'PHP',
                'category' => $system['category'],
                'category_label' => $system['category_label'],
                'path' => $path,
                'database' => $system['database'],
                'domains' => $this->domainsForPath($path),
                'connection_file' => $system['connection_file'],
            ];
        }

        return $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));
    }
}
