<?php
declare(strict_types=1);

namespace ROITheme\Admin\CustomCSSManager\Infrastructure\Ui;

use ROITheme\Admin\Infrastructure\Ui\AdminDashboardRenderer;
use ROITheme\Admin\CustomCSSManager\Infrastructure\Persistence\WordPressSnippetRepository;
use ROITheme\Admin\CustomCSSManager\Application\UseCases\GetAllSnippetsUseCase;

/**
 * FormBuilder para gestión de CSS snippets en Admin Panel
 *
 * Sigue el patrón estándar de FormBuilders del tema:
 * - Constructor recibe AdminDashboardRenderer
 * - Método buildForm() genera el HTML del formulario
 *
 * NOTA: El handler de formulario POST está en CustomCSSManagerBootstrap
 * para que se ejecute en admin_init ANTES de que se envíen headers HTTP.
 *
 * Design System: Gradiente navy #0E2337 → #1e3a5f, accent #FF8600
 */
final class CustomCSSManagerFormBuilder
{
    private const COMPONENT_ID = 'custom-css-manager';
    private const NONCE_ACTION = 'roi_custom_css_manager';

    private WordPressSnippetRepository $repository;
    private GetAllSnippetsUseCase $getAllUseCase;

    public function __construct(
        private readonly AdminDashboardRenderer $renderer
    ) {
        // Crear repositorio y Use Case para listar snippets
        global $wpdb;
        $this->repository = new WordPressSnippetRepository($wpdb);
        $this->getAllUseCase = new GetAllSnippetsUseCase($this->repository);
        // NOTA: El handler POST está en CustomCSSManagerBootstrap (admin_init)
    }

    /**
     * Construye el formulario del componente
     *
     * @param string $componentId ID del componente (custom-css-manager)
     * @return string HTML del formulario
     */
    public function buildForm(string $componentId): string
    {
        $snippets = $this->getAllUseCase->execute();
        $message = $this->getFlashMessage();

        $html = '';

        // Header
        $html .= $this->buildHeader($componentId, count($snippets));

        // Toast para mensajes (usa el sistema existente de admin-dashboard.js)
        if ($message) {
            $html .= $this->buildToastTrigger($message);
        }

        // Lista de snippets existentes
        $html .= $this->buildSnippetsList($snippets);

        // Formulario de creación/edición
        $html .= $this->buildSnippetForm();

        // JavaScript
        $html .= $this->buildJavaScript();

        return $html;
    }

    /**
     * Construye el header del componente
     */
    private function buildHeader(string $componentId, int $snippetCount): string
    {
        $html = '<div class="card shadow-sm mb-4" style="border-left: 4px solid #FF8600;">';
        $html .= '  <div class="card-header d-flex justify-content-between align-items-center" style="background: linear-gradient(135deg, #0E2337 0%, #1e3a5f 100%);">';
        $html .= '    <h3 class="mb-0 text-white"><i class="bi bi-file-earmark-code me-2"></i>Gestor de CSS Personalizado</h3>';
        $html .= '    <span class="badge bg-light text-dark">' . esc_html($snippetCount) . ' snippet(s)</span>';
        $html .= '  </div>';
        $html .= '  <div class="card-body">';
        $html .= '    <p class="text-muted mb-0">Gestiona snippets de CSS personalizados. Los snippets críticos se cargan en el head, los diferidos en el footer.</p>';
        $html .= '  </div>';
        $html .= '</div>';

        return $html;
    }

    /**
     * Construye la lista de snippets existentes
     */
    private function buildSnippetsList(array $snippets): string
    {
        $html = '<div class="card shadow-sm mb-4" style="border-left: 4px solid #FF8600;">';
        $html .= '  <div class="card-body">';
        $html .= '    <h5 class="fw-bold mb-3" style="color: #1e3a5f;">';
        $html .= '      <i class="bi bi-list-ul me-2" style="color: #FF8600;"></i>';
        $html .= '      Snippets Configurados';
        $html .= '    </h5>';

        if (empty($snippets)) {
            $html .= '    <p class="text-muted">No hay snippets configurados.</p>';
        } else {
            $html .= '    <div class="table-responsive">';
            $html .= '      <table class="table table-hover">';
            $html .= '        <thead>';
            $html .= '          <tr>';
            $html .= '            <th>Nombre</th>';
            $html .= '            <th>Tipo</th>';
            $html .= '            <th>Páginas</th>';
            $html .= '            <th>Estado</th>';
            $html .= '            <th>Acciones</th>';
            $html .= '          </tr>';
            $html .= '        </thead>';
            $html .= '        <tbody>';
            foreach ($snippets as $snippet) {
                $html .= $this->renderSnippetRow($snippet);
            }
            $html .= '        </tbody>';
            $html .= '      </table>';
            $html .= '    </div>';
        }

        $html .= '  </div>';
        $html .= '</div>';

        return $html;
    }

    /**
     * Renderiza una fila de snippet en la tabla
     */
    private function renderSnippetRow(array $snippet): string
    {
        $id = esc_attr($snippet['id']);
        $name = esc_html($snippet['name']);
        $type = $snippet['type'] === 'critical' ? 'Crítico' : 'Diferido';
        $typeBadge = $snippet['type'] === 'critical' ? 'bg-danger' : 'bg-info';
        $pages = implode(', ', $snippet['pages'] ?? ['all']);
        $enabled = ($snippet['enabled'] ?? false) ? 'Activo' : 'Inactivo';
        $enabledBadge = ($snippet['enabled'] ?? false) ? 'bg-success' : 'bg-secondary';

        // Usar data-attribute para JSON seguro
        $snippetJson = esc_attr(wp_json_encode($snippet, JSON_HEX_APOS | JSON_HEX_QUOT));
        $nonce = wp_create_nonce(self::NONCE_ACTION);

        return <<<HTML
        <tr>
            <td><strong>{$name}</strong></td>
            <td><span class="badge {$typeBadge}">{$type}</span></td>
            <td><small>{$pages}</small></td>
            <td><span class="badge {$enabledBadge}">{$enabled}</span></td>
            <td>
                <button type="button" class="btn btn-sm btn-outline-primary btn-edit-snippet"
                        data-snippet="{$snippetJson}">
                    <i class="bi bi-pencil"></i>
                </button>
                <form method="post" class="d-inline"
                      onsubmit="return confirm('¿Eliminar este snippet?');">
                    <input type="hidden" name="_wpnonce" value="{$nonce}">
                    <input type="hidden" name="roi_css_action" value="delete">
                    <input type="hidden" name="snippet_id" value="{$id}">
                    <button type="submit" class="btn btn-sm btn-outline-danger">
                        <i class="bi bi-trash"></i>
                    </button>
                </form>
            </td>
        </tr>
        HTML;
    }

    /**
     * Construye el formulario de creación/edición de snippets
     */
    private function buildSnippetForm(): string
    {
        $nonce = wp_create_nonce(self::NONCE_ACTION);

        $html = '<div class="card shadow-sm mb-4" style="border-left: 4px solid #FF8600;">';
        $html .= '  <div class="card-body">';
        $html .= '    <h5 class="fw-bold mb-3" style="color: #1e3a5f;">';
        $html .= '      <i class="bi bi-plus-circle me-2" style="color: #FF8600;"></i>';
        $html .= '      Agregar/Editar Snippet';
        $html .= '    </h5>';

        $html .= '    <form method="post" id="roi-snippet-form">';
        $html .= '      <input type="hidden" name="_wpnonce" value="' . esc_attr($nonce) . '">';
        $html .= '      <input type="hidden" name="roi_css_action" value="save">';
        $html .= '      <input type="hidden" name="snippet_id" id="snippet_id" value="">';

        $html .= '      <div class="row g-3">';

        // Nombre
        $html .= '        <div class="col-md-6">';
        $html .= '          <label class="form-label">Nombre *</label>';
        $html .= '          <input type="text" name="snippet_name" id="snippet_name" class="form-control" required maxlength="100" placeholder="Ej: Estilos Tablas APU">';
        $html .= '        </div>';

        // Tipo
        $html .= '        <div class="col-md-3">';
        $html .= '          <label class="form-label">Tipo *</label>';
        $html .= '          <select name="snippet_type" id="snippet_type" class="form-select">';
        $html .= '            <option value="critical">Crítico (head)</option>';
        $html .= '            <option value="deferred" selected>Diferido (footer)</option>';
        $html .= '          </select>';
        $html .= '        </div>';

        // Orden
        $html .= '        <div class="col-md-3">';
        $html .= '          <label class="form-label">Orden</label>';
        $html .= '          <input type="number" name="snippet_order" id="snippet_order" class="form-control" value="100" min="1" max="999">';
        $html .= '        </div>';

        // Descripción
        $html .= '        <div class="col-12">';
        $html .= '          <label class="form-label">Descripción</label>';
        $html .= '          <input type="text" name="snippet_description" id="snippet_description" class="form-control" maxlength="255" placeholder="Descripción breve del propósito del CSS">';
        $html .= '        </div>';

        // Páginas
        $html .= '        <div class="col-md-6">';
        $html .= '          <label class="form-label">Aplicar en páginas</label>';
        $html .= '          <div class="d-flex flex-wrap gap-2">';
        foreach ($this->getPageOptions() as $value => $label) {
            $checked = $value === 'all' ? 'checked' : '';
            $html .= sprintf(
                '<div class="form-check"><input type="checkbox" name="snippet_pages[]" value="%s" id="page_%s" class="form-check-input" %s><label class="form-check-label" for="page_%s">%s</label></div>',
                esc_attr($value),
                esc_attr($value),
                $checked,
                esc_attr($value),
                esc_html($label)
            );
        }
        $html .= '          </div>';
        $html .= '        </div>';

        // Estado
        $html .= '        <div class="col-md-6">';
        $html .= '          <label class="form-label">Estado</label>';
        $html .= '          <div class="form-check form-switch">';
        $html .= '            <input type="checkbox" name="snippet_enabled" id="snippet_enabled" class="form-check-input" checked>';
        $html .= '            <label class="form-check-label" for="snippet_enabled">Habilitado</label>';
        $html .= '          </div>';
        $html .= '        </div>';

        // Código CSS
        $html .= '        <div class="col-12">';
        $html .= '          <label class="form-label">Código CSS *</label>';
        $html .= '          <textarea name="snippet_css" id="snippet_css" class="form-control font-monospace" rows="10" required placeholder="/* Tu CSS aquí */"></textarea>';
        $html .= '          <small class="text-muted">Crítico: máx 14KB | Diferido: máx 100KB</small>';
        $html .= '        </div>';

        // Botones
        $html .= '        <div class="col-12">';
        $html .= '          <button type="submit" class="btn text-white" style="background-color: #FF8600;">';
        $html .= '            <i class="bi bi-check-circle me-1"></i> Guardar Cambios';
        $html .= '          </button>';
        $html .= '          <button type="button" class="btn btn-secondary" onclick="resetCssForm()">';
        $html .= '            <i class="bi bi-x-circle me-1"></i> Cancelar';
        $html .= '          </button>';
        $html .= '        </div>';

        $html .= '      </div>';
        $html .= '    </form>';
        $html .= '  </div>';
        $html .= '</div>';

        return $html;
    }

    /**
     * Genera el JavaScript necesario para el formulario
     */
    private function buildJavaScript(): string
    {
        return <<<JS
        <script>
        // Event delegation para botones de edición
        document.addEventListener('DOMContentLoaded', function() {
            document.querySelectorAll('.btn-edit-snippet').forEach(function(btn) {
                btn.addEventListener('click', function() {
                    const snippet = JSON.parse(this.dataset.snippet);
                    editCssSnippet(snippet);
                });
            });
        });

        function editCssSnippet(snippet) {
            document.getElementById('snippet_id').value = snippet.id;
            document.getElementById('snippet_name').value = snippet.name;
            document.getElementById('snippet_description').value = snippet.description || '';
            document.getElementById('snippet_type').value = snippet.type;
            document.getElementById('snippet_order').value = snippet.order || 100;
            document.getElementById('snippet_css').value = snippet.css;
            document.getElementById('snippet_enabled').checked = snippet.enabled;

            // Actualizar checkboxes de páginas
            document.querySelectorAll('input[name="snippet_pages[]"]').forEach(cb => {
                cb.checked = (snippet.pages || ['all']).includes(cb.value);
            });

            document.getElementById('snippet_name').focus();

            // Scroll al formulario
            document.getElementById('roi-snippet-form').scrollIntoView({ behavior: 'smooth' });
        }

        function resetCssForm() {
            document.getElementById('roi-snippet-form').reset();
            document.getElementById('snippet_id').value = '';
        }
        </script>
        JS;
    }

    /**
     * Opciones de páginas disponibles
     */
    private function getPageOptions(): array
    {
        return [
            'all' => 'Todas',
            'home' => 'Inicio',
            'posts' => 'Posts',
            'pages' => 'Páginas',
            'archives' => 'Archivos',
        ];
    }

    /**
     * Obtiene mensaje flash de la URL
     */
    private function getFlashMessage(): ?array
    {
        $message = $_GET['roi_message'] ?? null;

        if ($message === 'success') {
            return ['type' => 'success', 'text' => 'Cambios guardados correctamente'];
        }

        if ($message === 'error') {
            $error = urldecode($_GET['roi_error'] ?? 'Error desconocido');
            return ['type' => 'error', 'text' => $error];
        }

        return null;
    }

    /**
     * Genera script para mostrar Toast
     */
    private function buildToastTrigger(array $message): string
    {
        $type = esc_js($message['type']);
        $text = esc_js($message['text']);

        // Mapear tipo a configuración de Bootstrap
        $typeMap = [
            'success' => ['bg' => 'success', 'icon' => 'bi-check-circle-fill'],
            'error' => ['bg' => 'danger', 'icon' => 'bi-x-circle-fill'],
        ];
        $config = $typeMap[$type] ?? $typeMap['success'];
        $bg = $config['bg'];
        $icon = $config['icon'];

        return <<<HTML
        <script>
        document.addEventListener('DOMContentLoaded', function() {
            // Crear container de toasts si no existe
            let toastContainer = document.getElementById('roiToastContainer');
            if (!toastContainer) {
                toastContainer = document.createElement('div');
                toastContainer.id = 'roiToastContainer';
                toastContainer.className = 'toast-container position-fixed start-50 translate-middle-x';
                toastContainer.style.top = '60px';
                toastContainer.style.zIndex = '999999';
                document.body.appendChild(toastContainer);
            }

            // Crear toast
            const toastId = 'toast-' + Date.now();
            const toastHTML = `
                <div id="\${toastId}" class="toast align-items-center text-white bg-{$bg} border-0" role="alert" aria-live="assertive" aria-atomic="true">
                    <div class="d-flex">
                        <div class="toast-body">
                            <i class="bi {$icon} me-2"></i>
                            <strong>{$text}</strong>
                        </div>
                        <button type="button" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast" aria-label="Close"></button>
                    </div>
                </div>
            `;

            toastContainer.insertAdjacentHTML('beforeend', toastHTML);

            // Mostrar toast
            const toastElement = document.getElementById(toastId);
            const toast = new bootstrap.Toast(toastElement, {
                autohide: true,
                delay: 5000
            });
            toast.show();

            // Eliminar del DOM después de ocultarse
            toastElement.addEventListener('hidden.bs.toast', function() {
                toastElement.remove();
            });

            // Limpiar parámetros de URL sin recargar
            const url = new URL(window.location.href);
            url.searchParams.delete('roi_message');
            url.searchParams.delete('roi_error');
            window.history.replaceState({}, '', url.toString());
        });
        </script>
        HTML;
    }
}
