<?php
declare(strict_types=1);

/**
 * Área dos aliados (em espanhol): entrada com o código de aliado e a senha única, envio do arquivo
 * de Excel com validação na hora e lista dos envios do próprio aliado.
 */

require dirname(__DIR__) . '/app/inicio.php';

Seguranca::cabecalhos();
if (Seguranca::instalacaoExposta()) {
    pagina_instalacao_exposta('es');
}
Seguranca::iniciaSessao('aliado', (int) Config::get('sessao_aliado_min'));

const TIPOS_ES = ['sellout' => 'Sell out', 'estoque' => 'Stock'];

$acao = (string) ($_GET['acao'] ?? '');
$post = ($_SERVER['REQUEST_METHOD'] ?? 'GET') === 'POST';

// aliado da sessão: sai se foi desativado ou se a senha dos aliados mudou depois que ele entrou
$aliado = null;
if (isset($_SESSION['aliado'])) {
    $a = Banco::aliado((string) $_SESSION['aliado']);
    $senhaMudou = (string) ($_SESSION['entrou_em'] ?? '') < (string) (Banco::config('senha_aliados_em') ?? '');
    if ($a !== null && (int) $a['ativo'] === 1 && !$senhaMudou) {
        $aliado = $a;
    } else {
        $_SESSION = [];
    }
}

if ($acao === 'entrar' && $post) {
    entrar();
}
if ($acao === 'sair' && $post) {
    if (Seguranca::csrfValido()) {
        Seguranca::encerraSessao();
    }
    redireciona('./');
}
if ($acao === 'enviar') {
    enviar($aliado, $post);
}
if ($acao === 'modelo') {
    baixar_modelo($aliado);
}
if ($aliado === null) {
    tela_login();
}
tela_envio($aliado);

// ======================================================================== ações

function entrar(): never
{
    $codigo = Texto::codigoAliado((string) ($_POST['codigo'] ?? ''));
    $senha = (string) ($_POST['senha'] ?? '');
    $erro = null;
    if (!Seguranca::csrfValido()) {
        $erro = 'La página estuvo abierta mucho tiempo. Intente de nuevo.';
    } elseif ($codigo === '' || $senha === '') {
        $erro = 'Escriba su código de aliado y la contraseña.';
    } elseif (Seguranca::bloqueado('aliado:' . $codigo)) {
        $erro = 'Demasiados intentos con error. Espere ' . (int) Config::get('tentativas_janela_min') . ' minutos e intente de nuevo.';
    } else {
        $hash = (string) (Banco::config('senha_aliados_hash') ?? '');
        $a = Banco::aliado($codigo);
        $senhaCerta = $hash !== '' && password_verify($senha, $hash);
        if ($senhaCerta && $a !== null && (int) $a['ativo'] === 1) {
            Seguranca::limpaErros('aliado:' . $codigo);
            session_regenerate_id(true);
            $_SESSION = ['aliado' => (string) $a['codigo'], 'entrou_em' => Banco::agora(), 'ultimo_uso' => time()];
            redireciona('./');
        }
        Seguranca::registraErro('aliado:' . $codigo);
        $erro = $hash === ''
            ? 'El acceso todavía no está habilitado. Consulte a su contacto en Intelbras.'
            : 'Código de aliado o contraseña incorrectos.';
    }
    $_SESSION['login_erro'] = $erro;
    $_SESSION['login_codigo'] = $codigo;
    redireciona('./');
}

/** Recebe o arquivo (chamado pelo aliado.js) e responde em JSON. */
function enviar(?array $aliado, bool $post): never
{
    if (!$post) {
        responde_json(['ok' => false], 405);
    }
    if ($aliado === null) {
        responde_json(['ok' => false, 'sessao' => true, 'erros' => [[
            'titulo' => 'Su sesión terminó.',
            'detalhe' => 'La página se recargará. Ingrese de nuevo con su código y contraseña.']]], 401);
    }
    if (!Seguranca::csrfValido()) {
        responde_json(['ok' => false, 'sessao' => true, 'erros' => [[
            'titulo' => 'La página quedó desactualizada.',
            'detalhe' => 'Se recargará; después envíe el archivo de nuevo.']]], 403);
    }
    $maxMb = (int) Config::get('tamanho_max_mb');
    $falha = static function (string $titulo, string $detalhe = '', int $status = 422): never {
        responde_json(['ok' => false, 'erros' => [['titulo' => $titulo, 'detalhe' => $detalhe]]], $status);
    };

    $f = $_FILES['arquivo'] ?? null;
    if (!is_array($f) && (int) ($_SERVER['CONTENT_LENGTH'] ?? 0) > 0 && !$_POST) {
        $falha('El archivo es demasiado grande.', 'El tamaño máximo es ' . $maxMb . ' MB.', 413);
    }
    $empresa = Texto::apara(preg_replace('/\s+/u', ' ', (string) ($_POST['empresa'] ?? '')) ?? '');
    $tipo = (string) ($_POST['tipo'] ?? '');
    if (mb_strlen($empresa) < 2 || mb_strlen($empresa) > 120) {
        $falha('Escriba el nombre de su empresa.');
    }
    if (!isset(TIPOS_ES[$tipo])) {
        $falha('Elija el tipo de archivo: Sell out o Stock.');
    }
    if (!is_array($f) || (int) ($f['error'] ?? UPLOAD_ERR_NO_FILE) === UPLOAD_ERR_NO_FILE) {
        $falha('Elija el archivo de Excel.');
    }
    $codErro = (int) $f['error'];
    if (in_array($codErro, [UPLOAD_ERR_INI_SIZE, UPLOAD_ERR_FORM_SIZE], true) || (int) $f['size'] > $maxMb * 1048576) {
        $falha('El archivo es demasiado grande.', 'El tamaño máximo es ' . $maxMb . ' MB. Envíe solo los datos de un mes.', 413);
    }
    $tmp = (string) $f['tmp_name'];
    if ($codErro !== UPLOAD_ERR_OK || !is_uploaded_file($tmp)) {
        $falha('El archivo no llegó completo.', 'Intente de nuevo. Si el problema continúa, verifique su conexión a internet.', 400);
    }
    $nome = Texto::apara((string) $f['name']);
    $ext = strtolower(pathinfo($nome, PATHINFO_EXTENSION));
    $inicio = (string) file_get_contents($tmp, false, null, 0, 8);
    if (str_starts_with($inicio, "\xD0\xCF\x11\xE0")) {
        $falha('El archivo está en el formato antiguo de Excel (.xls) o protegido con contraseña.',
            'Ábralo en Excel, quite la contraseña si la tiene y use «Guardar como» → «Libro de Excel (.xlsx)». Después envíelo de nuevo.');
    }
    if (!str_starts_with($inicio, "PK\x03\x04") || !in_array($ext, ['xlsx', 'xlsm'], true)) {
        $falha('El archivo no es una planilla de Excel (.xlsx).', in_array($ext, ['csv', 'txt'], true)
            ? 'Es un archivo de texto (.' . $ext . '). Ábralo en Excel y use «Guardar como» → «Libro de Excel (.xlsx)».'
            : 'Envíe la planilla en formato .xlsx (en Excel: «Guardar como» → «Libro de Excel (.xlsx)»).');
    }

    try {
        $class = Classificacao::carrega();
    } catch (Throwable $e) {
        error_log('sellout-latam: tabela de preços ilegível: ' . $e->getMessage());
        $class = null; // o envio segue; só não completa Unidade/Segmento/Família
    }
    // sugestões que o aliado aceitou (OK) na tentativa anterior com este mesmo arquivo: nomes de colunas do modelo
    $completar = json_decode((string) ($_POST['completar'] ?? '[]'), true);
    $completar = is_array($completar)
        ? array_slice(array_values(array_filter($completar, static fn ($x) => is_string($x) && $x !== '' && mb_strlen($x) <= 60)), 0, 40)
        : [];
    try {
        $res = Validacao::processa($tmp, $tipo, (string) $aliado['codigo'], $class,
            ['completar' => $completar, 'aliado' => ['nome' => (string) $aliado['nome'], 'pais' => (string) $aliado['pais']]]);
    } catch (Throwable $e) {
        error_log('sellout-latam: erro ao validar ' . $nome . ': ' . $e);
        $falha('No conseguimos leer el archivo.',
            'Ábralo en Excel, guárdelo de nuevo como «Libro de Excel (.xlsx)» y envíelo otra vez.', 500);
    }
    if (!$res['ok']) {
        // quando tudo se resolve com as sugestões, ainda não é recusa: o aliado decide se completa
        if (!$res['completavel']) {
            Envios::registraRecusa((string) $aliado['codigo'], $tipo, $nome, $res['erros']);
        }
        responde_json(['ok' => false, 'erros' => $res['erros'], 'avisos' => $res['avisos'], 'completavel' => $res['completavel']], 422);
    }
    $mes = (string) $res['resumo']['mes_ref'];
    $anterior = Envios::vigente((string) $aliado['codigo'], $tipo, $mes);
    try {
        Envios::grava($aliado, $empresa, $tipo, $res, $nome);
    } catch (Throwable $e) {
        error_log('sellout-latam: erro ao gravar envio: ' . $e);
        $falha('El archivo está correcto, pero no pudimos guardarlo.',
            'Intente de nuevo en unos minutos. Si el problema continúa, avise a su contacto en Intelbras.', 500);
    }
    $r = $res['resumo'];
    responde_json([
        'ok' => true,
        'resumo' => [
            'tipo' => TIPOS_ES[$tipo],
            'mes' => mes_curto($mes, 'es'),
            'linhas' => num_br($r['linhas'], 0),
            'total' => num_br($r['total_usd']),
            'quantidade' => num_br($r['quantidade'], 0),
            'clientes' => num_br($r['clientes'], 0),
            'itens' => num_br($r['itens'], 0),
        ],
        'avisos' => $res['avisos'],
        'completou' => completou_es($res['completou']),
        'substituiu' => $anterior !== null ? data_br((string) $anterior['criado_em']) : null,
        'lista' => lista_do_aliado((string) $aliado['codigo']),
    ]);
}

/** O que o site completou com o OK do aliado, em frases para a tela de sucesso. @return list<string> */
function completou_es(array $lista): array
{
    $out = [];
    foreach ($lista as $c) {
        $n = (int) $c['n'];
        $como = match ((string) $c['como']) {
            'valor' => 'con «' . (string) $c['valor'] . '»',
            'mes' => $c['coluna'] === 'TX_MES' ? 'con el mes escrito de CD_MES' : 'con el número del mes de TX_MES',
            'conta' => 'con el valor calculado',
            'aliado' => $c['coluna'] === 'CD_ALIADO' ? 'con su código de aliado' : 'con los datos de su empresa',
            'tabela' => 'con nuestra tabla de productos',
            default => '',
        };
        $out[] = $c['coluna'] . ': ' . ($c['nova'] ? 'columna agregada' : num_br($n, 0) . ($n === 1 ? ' celda completada' : ' celdas completadas'))
            . ($como !== '' ? ' ' . $como : '') . '.';
    }
    return $out;
}

/** Planilha modelo, só com a linha de títulos. */
function baixar_modelo(?array $aliado): never
{
    if ($aliado === null) {
        redireciona('./');
    }
    $tipo = (string) ($_GET['tipo'] ?? '');
    if (!isset(TIPOS_ES[$tipo])) {
        http_response_code(404);
        exit;
    }
    $titulos = array_column(Banco::modelo($tipo), 'nome');
    $tmp = (string) tempnam(sys_get_temp_dir(), 'mod');
    XlsxGravador::grava($tmp, $tipo === 'estoque' ? 'Stock' : 'Sellout', $titulos, []);
    Envios::entrega($tmp, 'Modelo_' . ($tipo === 'estoque' ? 'Stock' : 'SellOut') . '.xlsx',
        'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', true);
}

/** Últimos envios do aliado, já formatados para a tela. */
function lista_do_aliado(string $codigo): array
{
    $out = [];
    foreach (Envios::doAliado($codigo) as $e) {
        $out[] = [
            'data' => data_br((string) $e['criado_em']),
            'tipo' => TIPOS_ES[$e['tipo']] ?? (string) $e['tipo'],
            'mes' => mes_curto((string) $e['mes_ref'], 'es'),
            'arquivo' => (string) $e['nome_original'],
            'linhas' => num_br((int) $e['linhas'], 0),
            'total' => num_br((float) $e['total_usd']),
            'vigente' => (int) $e['substituido'] === 0,
        ];
    }
    return $out;
}

// ======================================================================== telas

function tela_login(): never
{
    $erro = $_SESSION['login_erro'] ?? null;
    $codigo = (string) ($_SESSION['login_codigo'] ?? '');
    unset($_SESSION['login_erro'], $_SESSION['login_codigo']);
    pagina_inicio('Envío de Sell out y Stock', 'es', 'pagina-login');
    ?>
<main class="caixa-login">
  <div class="cartao">
    <p class="sobretitulo">Aliados LATAM</p>
    <h1>Envío de Sell out y Stock</h1>
    <p class="sub">Ingrese con su código de aliado y la contraseña que recibió.</p>
    <?php if ($erro): ?><div class="aviso aviso-erro" role="alert"><?= h($erro) ?></div><?php endif; ?>
    <form method="post" action="?acao=entrar" class="formulario">
      <input type="hidden" name="csrf" value="<?= h(Seguranca::tokenCsrf()) ?>">
      <label for="codigo">Código de aliado</label>
      <input id="codigo" name="codigo" autocomplete="username" required maxlength="20" value="<?= h($codigo) ?>"<?= $codigo === '' ? ' autofocus' : '' ?>>
      <label for="senha">Contraseña</label>
      <input id="senha" name="senha" type="password" autocomplete="current-password" required maxlength="200"<?= $codigo !== '' ? ' autofocus' : '' ?>>
      <button type="submit" class="botao botao-largo">Ingresar</button>
    </form>
  </div>
</main>
    <?php
    pagina_fim();
    exit;
}

function tela_envio(array $aliado): never
{
    $maxMb = (int) Config::get('tamanho_max_mb');
    $csrf = Seguranca::tokenCsrf();
    $lista = lista_do_aliado((string) $aliado['codigo']);
    pagina_inicio('Envío de Sell out y Stock', 'es', 'pagina-aliado');
    ?>
<header class="topo">
  <div class="marca">Envío de Sell out y Stock</div>
  <form method="post" action="?acao=sair" class="usuario">
    <input type="hidden" name="csrf" value="<?= h($csrf) ?>">
    <span class="quem"><?= h($aliado['nome']) ?> <span class="cod"><?= h($aliado['codigo']) ?></span></span>
    <button type="submit" class="botao-link">Salir</button>
  </form>
</header>
<main class="conteudo">
  <noscript><div class="aviso aviso-erro">Para enviar archivos, active JavaScript en su navegador.</div></noscript>

  <section class="cartao">
    <h1>Enviar archivo</h1>
    <p class="sub">Un archivo de Excel (.xlsx) por mes y por tipo. El sistema revisa el archivo en el momento: si falta algo, le indica qué corregir o le sugiere cómo completarlo.</p>
    <form id="form-envio" class="formulario passos" data-max-mb="<?= $maxMb ?>" novalidate>
      <input type="hidden" name="csrf" value="<?= h($csrf) ?>">
      <div class="passo">
        <label for="empresa"><span class="num">1</span> Nombre de su empresa</label>
        <input id="empresa" name="empresa" maxlength="120" autocomplete="organization" required>
      </div>
      <div class="passo">
        <label for="tipo"><span class="num">2</span> Tipo de archivo</label>
        <select id="tipo" name="tipo" required>
          <option value="">Elija…</option>
          <option value="sellout">Sell out (ventas a sus clientes)</option>
          <option value="estoque">Stock (inventario)</option>
        </select>
      </div>
      <div class="passo">
        <label for="arquivo"><span class="num">3</span> Archivo de Excel (.xlsx)</label>
        <input id="arquivo" name="arquivo" type="file" accept=".xlsx,.xlsm" disabled>
        <p class="ajuda" id="ajuda-arquivo">Complete los pasos 1 y 2 para elegir el archivo.</p>
      </div>
      <div class="acoes">
        <button type="submit" id="btn-enviar" class="botao" disabled>Enviar archivo</button>
        <span id="estado" class="estado" aria-live="polite"></span>
      </div>
      <progress id="progresso" max="100" value="0" hidden></progress>
    </form>
    <div id="resultado" aria-live="polite"></div>
  </section>

  <section class="cartao">
    <h2>Columnas del archivo</h2>
    <p id="colunas-sem-tipo" class="sub">Elija el tipo de archivo (paso 2) para ver las columnas que la planilla debe tener.</p>
    <?php foreach (TIPOS_ES as $tipo => $rotulo): ?>
    <div data-colunas="<?= h($tipo) ?>" hidden>
      <p class="sub">La primera fila de la planilla de <?= h($rotulo) ?> debe tener estos títulos. Todas las celdas deben estar completas, salvo donde se indica. Los valores van en <b>dólares (USD)</b>.</p>
      <ul class="colunas">
        <?php foreach (Banco::modelo($tipo) as $c): ?>
        <li><code><?= h($c['nome']) ?></code><?php
            if (!$c['obrigatoria']) {
                echo ' <span class="etiqueta">opcional</span>';
            } elseif ($c['pode_vazio']) {
                echo ' <span class="etiqueta">puede quedar en blanco</span>';
            }
            if ($c['numerica']) {
                echo ' <span class="etiqueta etiqueta-num">número</span>';
            } ?></li>
        <?php endforeach; ?>
      </ul>
      <p class="ajuda">Si UNIDADE, SEGMENTO o FAMILIA quedan en blanco, las completamos con nuestra tabla de productos.
        Si falta un dato que podemos completar (por ejemplo, TX_MES a partir de CD_MES), le mostramos la sugerencia y usted decide con OK.
        Si el archivo tiene la columna TX_MES, en cada fila debe estar el mismo mes de CD_MES (por ejemplo, 10 y OCTUBRE).</p>
      <p><a class="botao botao-secundario" href="?acao=modelo&amp;tipo=<?= h($tipo) ?>">Descargar planilla modelo de <?= h($rotulo) ?> (.xlsx)</a></p>
    </div>
    <?php endforeach; ?>
  </section>

  <section class="cartao">
    <h2>Sus envíos</h2>
    <p id="sem-envios" class="sub"<?= $lista ? ' hidden' : '' ?>>Todavía no hay archivos enviados.</p>
    <div class="rolagem">
      <table id="tabela-envios" class="tabela"<?= $lista ? '' : ' hidden' ?>>
        <thead><tr><th>Fecha</th><th>Tipo</th><th>Mes</th><th>Archivo</th><th class="n">Filas</th><th class="n">Total USD</th><th>Estado</th></tr></thead>
        <tbody>
        <?php foreach ($lista as $e): ?>
          <tr<?= $e['vigente'] ? '' : ' class="apagado"' ?>>
            <td><?= h($e['data']) ?></td><td><?= h($e['tipo']) ?></td><td><?= h($e['mes']) ?></td>
            <td class="arquivo"><?= h($e['arquivo']) ?></td><td class="n"><?= h($e['linhas']) ?></td>
            <td class="n"><?= h($e['total']) ?></td>
            <td><?= $e['vigente'] ? '<span class="selo selo-ok">Vigente</span>' : '<span class="selo">Reemplazado</span>' ?></td>
          </tr>
        <?php endforeach; ?>
        </tbody>
      </table>
    </div>
    <p class="ajuda">Si envía de nuevo el mismo tipo y mes, el archivo nuevo reemplaza al anterior.</p>
  </section>
</main>

<dialog id="aviso-usd" class="dialogo" aria-labelledby="aviso-usd-titulo">
  <form method="dialog">
    <h2 id="aviso-usd-titulo">Valores en dólares</h2>
    <p>Las columnas <b>VALOR UNIT USD</b> y <b>VALOR TOT USD</b> deben estar en <b>dólares estadounidenses (USD)</b>. El sistema no convierte monedas.</p>
    <p>Si su archivo está en otra moneda, cancele, convierta los valores a dólares y envíelo después.</p>
    <div class="acoes">
      <button value="cancelar" class="botao botao-secundario">Cancelar</button>
      <button value="ok" class="botao" id="usd-ok">OK, están en dólares</button>
    </div>
  </form>
</dialog>
    <?php
    pagina_fim(['aliado.js']);
    exit;
}
