<?php

class Agro_TemplateRenderer
{
    protected Zend_View $view;
    protected string $basePath;

    public function __construct()
    {
        $this->view = new Zend_View();
        $this->basePath = rtrim(APPLICATION_PATH . '/templates', '/');
    }

    /**
     * Renderiza um template HTML com:
     * - Variáveis escalares: {{chave}} ou {{obj.propriedade}}
     * - Loops: <!-- BEGIN lista --> ... {{campo}} ... <!-- END lista -->
     *
     * @param string $caminhoRelativo Caminho relativo ao /templates
     * @param array  $variaveis       Dados para substituição
     * @return string HTML final
     */
    public function renderizar(string $caminhoRelativo, array $variaveis = []): string
    {
        $fullPath = $this->basePath . '/' . ltrim($caminhoRelativo, '/');
        if (!file_exists($fullPath)) {
            throw new RuntimeException("Template não encontrado: {$fullPath}");
        }

        // opcional: ainda deixa disponível no Zend_View
        foreach ($variaveis as $chave => $valor) {
            $this->view->$chave = $valor;
        }

        $content = file_get_contents($fullPath);

        // 1) Resolve blocos de repetição
        $content = $this->renderLoops($content, $variaveis);

        // 2) Resolve variáveis escalares remanescentes
        $content = $this->renderVariables($content, $variaveis);

        return $content;
    }

    /**
     * Processa blocos <!-- BEGIN nome --> ... <!-- END nome -->
     * e repete o conteúdo do bloco para cada item do array $variaveis['nome'].
     */
    protected function renderLoops(string $tpl, array $variaveis): string
    {
        $pattern = '/<!--\s*LOOP_BEGIN\s+([a-zA-Z0-9_]+)\s*-->(.*?)<!--\s*LOOP_END\s+\1\s*-->/s';

        // Usa callback para cada bloco encontrado
        $result = preg_replace_callback($pattern, function ($m) use ($variaveis) {
            $listaKey = $m[1];   // nome da lista (ex.: "coberturas")
            $block    = $m[2];   // HTML dentro do bloco

            // Se não tiver a lista ou não for array, remove o bloco
            if (!isset($variaveis[$listaKey]) || !is_array($variaveis[$listaKey])) {
                return '';
            }

            $saida = '';
            foreach ($variaveis[$listaKey] as $item) {
                // Garante que cada item é array (permite objeto convertendo)
                if (is_object($item)) {
                    $item = (array) $item;
                } elseif (!is_array($item)) {
                    $item = ['value' => $item];
                }

                // Primeiro, resolve sub-blocos dentro do bloco com o contexto do item
                $rowHtml = $this->renderLoops($block, $item);

                // Depois, aplica variáveis do item ({{descricao}}, {{tipo}}, {{x.y}})
                $rowHtml = $this->renderVariables($rowHtml, $item);

                $saida .= $rowHtml;
            }
            return $saida;
        }, $tpl);

        return $result ?? $tpl; // preg_replace_callback pode retornar null
    }

    /**
     * Substitui variáveis {{chave}} e {{chave.subchave}} por valores escalares.
     * Não faz escape para permitir HTML; se precisar, use htmlspecialchars no valor antes.
     */
    protected function renderVariables(string $tpl, array $vars): string
    {
        $pattern = '/\{\{\s*([a-zA-Z0-9_\.]+)\s*\}\}/';

        $result = preg_replace_callback($pattern, function ($m) use ($vars) {
            $path = explode('.', $m[1]);
            $val  = $vars;

            foreach ($path as $p) {
                if (is_array($val) && array_key_exists($p, $val)) {
                    $val = $val[$p];
                } else {
                    // Se não achar a chave, retorna string vazia
                    $val = '';
                    break;
                }
            }

            // Converte para string simples (ignora arrays/objetos)
            if (is_scalar($val) || (is_object($val) && method_exists($val, '__toString'))) {
                return (string) $val;
            }
            return '';
        }, $tpl);

        return $result ?? $tpl;
    }
}
