<?php
// Depto de Engenharia e Automação - Master Automação - Autor: Derlivon Silva

namespace App\Core;

/**
 * Registro de lojas para o modo MULTI-LOJA.
 *
 * - Se NÃO existir config/lojas.php  -> modo SINGLE-LOJA (usa config/database.php, igual antes).
 * - Se existir config/lojas.php      -> modo MULTI-LOJA (várias conexões, loja ativa na sessão).
 *
 * É 100% retrocompatível: sem lojas.php, multi() devolve false e tudo funciona como hoje.
 *
 * Formato de config/lojas.php (return array):
 *   return [
 *     'matriz' => [
 *       'nome'=>'Mega Importados 1,99','host'=>'localhost','port'=>3050,
 *       'database'=>'C:\\Banco\\...\\FIRE.FDB','username'=>'SYSDBA','password'=>'masterkey',
 *       'charset'=>'WIN1252','cod_empresa'=>5,
 *       'leitor'=>true,      // o leitor (operacional) pode usar esta loja (banco local)
 *       'principal'=>true,   // loja padrão ao abrir
 *     ],
 *     'barra' => [ ... ],
 *   ];
 */
class Lojas
{
    private static ?array $cache = null;
    /** Loja "em foco" durante o loop do consolidado (sobrepõe a ativa só p/ escopo de cache). */
    private static ?string $focoOverride = null;

    private static function path(): string
    {
        return dirname(__DIR__, 2) . '/config/lojas.php';
    }

    /** Recarrega o arquivo (útil em testes). */
    public static function resetar(): void
    {
        self::$cache = null;
    }

    /** Salva a configuração de lojas em config/lojas.php (gerenciada pela tela de config). */
    public static function salvarTodas(array $lojas): bool
    {
        self::$cache = null;
        $export = var_export($lojas, true);
        $conteudo = "<?php\n"
            . "// Configuração de LOJAS (multi-loja) — gerada pela tela Configurações > Lojas.\n"
            . "// Sem este arquivo (ou vazio), o sistema roda em SINGLE-LOJA (config/database.php).\n"
            . "return {$export};\n";
        return file_put_contents(self::path(), $conteudo) !== false;
    }

    /** Todas as lojas configuradas. Vazio = modo single-loja. */
    public static function todas(): array
    {
        if (self::$cache !== null) return self::$cache;
        $path = self::path();
        if (!is_file($path)) return self::$cache = [];
        $data = require $path;
        return self::$cache = (is_array($data) ? $data : []);
    }

    /** Está em modo multi-loja? (existe lojas.php com pelo menos 1 loja) */
    public static function multi(): bool
    {
        return count(self::todas()) > 0;
    }

    public static function existe(string $id): bool
    {
        return array_key_exists($id, self::todas());
    }

    public static function get(string $id): ?array
    {
        return self::todas()[$id] ?? null;
    }

    /** Id da loja padrão (a marcada 'principal', senão a primeira). */
    public static function padraoId(): ?string
    {
        $todas = self::todas();
        if (!$todas) return null;
        foreach ($todas as $id => $l) {
            if (!empty($l['principal'])) return (string) $id;
        }
        return (string) array_key_first($todas);
    }

    /** Garante sessão iniciada (sem warning se já houver). */
    private static function sessao(): void
    {
        if (session_status() === PHP_SESSION_NONE) {
            @session_start();
        }
    }

    /** Id da loja ativa na sessão. Null em single-loja. */
    public static function idAtiva(): ?string
    {
        if (!self::multi()) return null;
        self::sessao();
        $id = $_SESSION['loja_ativa'] ?? null;
        if ($id !== null && self::existe((string) $id)) return (string) $id;
        return self::padraoId();
    }

    /** Define a loja ativa na sessão. */
    public static function setAtiva(string $id): bool
    {
        if (!self::existe($id)) return false;
        self::sessao();
        $_SESSION['loja_ativa'] = $id;
        return true;
    }

    /** Lojas onde o LEITOR pode operar (banco local). Em single-loja, vazio (usa database.php). */
    public static function paraLeitor(): array
    {
        return array_filter(self::todas(), fn($l) => !empty($l['leitor']));
    }

    /**
     * Loja está com o servidor LIGADO e respondendo? TCP probe rápido (400ms).
     * Resposta cacheada por 30s (ver FirebirdService::pingHost), então pode ser
     * chamado livremente em seletores/sidebar.
     *
     * Em single-loja, ou loja local, sempre devolve true.
     */
    public static function estaOnline(string $id): bool
    {
        $l = self::get($id);
        if (!$l) return false;
        $host = (string) ($l['host'] ?? '');
        $port = (int)    ($l['port'] ?? 3050);
        return \App\Services\FirebirdService::pingHost($host, $port);
    }

    /**
     * Config de conexão de uma loja, no formato que o FirebirdService espera.
     */
    public static function configDe(string $id): ?array
    {
        $l = self::get($id);
        if (!$l) return null;
        return [
            'host'        => $l['host']        ?? 'localhost',
            'port'        => $l['port']        ?? 3050,
            'database'    => $l['database']    ?? '',
            'username'    => $l['username']    ?? 'SYSDBA',
            'password'    => $l['password']    ?? '',
            'charset'     => $l['charset']     ?? 'WIN1252',
            'cod_empresa' => (int) ($l['cod_empresa'] ?? 0),
            'empresa'     => $l['nome']        ?? $id,
        ];
    }

    /**
     * Segmento da loja ATIVA (multi-loja). Devolve null em single-loja OU quando
     * a loja ativa não tem campo 'segmento' configurado — nesse caso o caller
     * deve cair pro segmento global do config/database.php.
     *
     * Permite operar várias lojas de SEGMENTOS DIFERENTES na mesma instância:
     *   'loja_bar'   => [..., 'segmento' => 'bar'],
     *   'loja_merc'  => [..., 'segmento' => 'supermercado'],
     */
    public static function segmentoAtiva(): ?string
    {
        if (!self::multi()) return null;
        $id = self::idAtiva();
        if ($id === null) return null;
        $s = self::get($id)['segmento'] ?? null;
        if (!is_string($s) || $s === '') return null;
        return $s;
    }

    /**
     * Resolve o segmento efetivo: prioriza o da loja ativa (multi-loja com campo
     * 'segmento' setado); senão cai no segmento global do config/database.php
     * (passado em $config). Fallback final = 'loja'.
     *
     * Use ESTE método em sidebar/guards/views em vez de $config['segmento']
     * direto, pra suportar lojas com segmentos diferentes na mesma instância.
     */
    public static function resolverSegmento(array $config): string
    {
        $s = self::segmentoAtiva();
        if ($s !== null && $s !== '') return $s;
        $g = $config['segmento'] ?? '';
        return is_string($g) && $g !== '' ? $g : 'loja';
    }

    /**
     * cod_empresa da loja ATIVA. Em single-loja, lê do config/database.php (igual antes).
     */
    public static function codEmpresaAtiva(): int
    {
        $id = self::idAtiva();
        if ($id !== null) {
            return (int) (self::get($id)['cod_empresa'] ?? 0);
        }
        $path = dirname(__DIR__, 2) . '/config/database.php';
        if (is_file($path)) {
            $cfg = require $path;
            return (int) ($cfg['cod_empresa'] ?? 0);
        }
        return 0;
    }

    /**
     * Sufixo p/ chaves de cache — garante isolamento por loja
     * (duas lojas com o MESMO cod_empresa não podem colidir no cache).
     * Em single-loja, devolve '' (mantém as chaves atuais).
     */
    public static function escopoCache(): string
    {
        if (self::$focoOverride !== null) return '_loja_' . self::$focoOverride;
        $id = self::idAtiva();
        return $id !== null ? ('_loja_' . $id) : '';
    }

    /** Define a loja "em foco" (consolidado) — alinha o escopo de cache à loja consultada. */
    public static function setFoco(?string $id): void
    {
        self::$focoOverride = $id;
    }

    // ── Modo consolidado ("Todas as lojas") ────────────────────────────────────
    public static function setConsolidado(bool $on): void
    {
        self::sessao();
        $_SESSION['loja_consolidado'] = $on;
    }

    public static function consolidado(): bool
    {
        if (!self::multi()) return false;
        self::sessao();
        return !empty($_SESSION['loja_consolidado']);
    }

    // ── Metas POR LOJA ──────────────────────────────────────────────────────────
    /** Caminho do arquivo de metas da loja ATIVA. Single-loja = config/metas.json. */
    public static function metasPath(): string
    {
        $base = dirname(__DIR__, 2) . '/config';
        if (self::multi()) {
            $id = self::idAtiva();
            if ($id !== null && $id !== '') {
                $safe = preg_replace('/[^A-Za-z0-9_]/', '_', (string) $id);
                return $base . '/metas_' . $safe . '.json';
            }
        }
        return $base . '/metas.json';
    }

    /** Lê as metas da loja ativa (fallback no metas.json global p/ não perder o que já existe). */
    public static function lerMetas(): array
    {
        $p = self::metasPath();
        if (is_file($p)) {
            $j = json_decode((string) @file_get_contents($p), true);
            if (is_array($j) && $j) return $j;
        }
        // fallback: metas globais legadas (até a loja salvar a sua própria)
        $legacy = dirname(__DIR__, 2) . '/config/metas.json';
        if ($p !== $legacy && is_file($legacy)) {
            $j = json_decode((string) @file_get_contents($legacy), true);
            if (is_array($j)) return $j;
        }
        return [];
    }
}
