<?php
declare(strict_types=1);

namespace ROITheme\Admin\CustomCSSManager\Infrastructure\Persistence;

use ROITheme\Shared\Domain\Contracts\CSSSnippetRepositoryInterface;

/**
 * Repositorio WordPress para snippets CSS
 *
 * Almacena snippets como JSON en wp_roi_theme_component_settings
 */
final class WordPressSnippetRepository implements CSSSnippetRepositoryInterface
{
    private const COMPONENT_NAME = 'custom-css-manager';
    private const GROUP_NAME = 'css_snippets';
    private const ATTRIBUTE_NAME = 'snippets_json';

    public function __construct(
        private readonly \wpdb $wpdb
    ) {}

    public function getAll(): array
    {
        $tableName = $this->wpdb->prefix . 'roi_theme_component_settings';

        $sql = $this->wpdb->prepare(
            "SELECT attribute_value FROM {$tableName}
             WHERE component_name = %s
               AND group_name = %s
               AND attribute_name = %s
             LIMIT 1",
            self::COMPONENT_NAME,
            self::GROUP_NAME,
            self::ATTRIBUTE_NAME
        );

        $json = $this->wpdb->get_var($sql);

        if (empty($json)) {
            return [];
        }

        $snippets = json_decode($json, true);

        return is_array($snippets) ? $snippets : [];
    }

    public function getByLoadType(string $loadType): array
    {
        $all = $this->getAll();

        $filtered = array_filter($all, function ($snippet) use ($loadType) {
            return ($snippet['type'] ?? '') === $loadType
                && ($snippet['enabled'] ?? false) === true;
        });

        // Reindexar para evitar keys dispersas [0,2,5] → [0,1,2]
        return array_values($filtered);
    }

    public function getForPage(string $loadType, string $pageType): array
    {
        $snippets = $this->getByLoadType($loadType);

        $filtered = array_filter($snippets, function ($snippet) use ($pageType) {
            $pages = $snippet['pages'] ?? ['all'];
            return in_array('all', $pages, true)
                || in_array($pageType, $pages, true);
        });

        // Reindexar para evitar keys dispersas
        return array_values($filtered);
    }

    public function save(array $snippet): void
    {
        $all = $this->getAll();

        // Actualizar o agregar
        $found = false;
        foreach ($all as &$existing) {
            if ($existing['id'] === $snippet['id']) {
                $existing = $snippet;
                $found = true;
                break;
            }
        }

        if (!$found) {
            $all[] = $snippet;
        }

        // Ordenar por 'order'
        usort($all, fn($a, $b) => ($a['order'] ?? 100) <=> ($b['order'] ?? 100));

        $this->persist($all);
    }

    public function delete(string $snippetId): void
    {
        $all = $this->getAll();

        $filtered = array_filter($all, fn($s) => $s['id'] !== $snippetId);

        $this->persist(array_values($filtered));
    }

    /**
     * Persiste la lista de snippets en BD
     *
     * Usa update() + insert() para consistencia con patrón existente.
     * NOTA: NO usa replace() porque:
     * - Preserva ID autoincremental
     * - Preserva campos como is_editable, created_at
     *
     * @param array $snippets Lista de snippets a persistir
     */
    private function persist(array $snippets): void
    {
        $tableName = $this->wpdb->prefix . 'roi_theme_component_settings';
        $json = wp_json_encode($snippets, JSON_UNESCAPED_UNICODE);

        // Verificar si el registro existe
        $exists = $this->wpdb->get_var($this->wpdb->prepare(
            "SELECT COUNT(*) FROM {$tableName}
             WHERE component_name = %s
               AND group_name = %s
               AND attribute_name = %s",
            self::COMPONENT_NAME,
            self::GROUP_NAME,
            self::ATTRIBUTE_NAME
        ));

        if ($exists > 0) {
            // UPDATE existente (preserva id, created_at, is_editable)
            $this->wpdb->update(
                $tableName,
                ['attribute_value' => $json],
                [
                    'component_name' => self::COMPONENT_NAME,
                    'group_name' => self::GROUP_NAME,
                    'attribute_name' => self::ATTRIBUTE_NAME,
                ],
                ['%s'],
                ['%s', '%s', '%s']
            );
        } else {
            // INSERT nuevo
            $this->wpdb->insert(
                $tableName,
                [
                    'component_name' => self::COMPONENT_NAME,
                    'group_name' => self::GROUP_NAME,
                    'attribute_name' => self::ATTRIBUTE_NAME,
                    'attribute_value' => $json,
                    'is_editable' => 1,
                ],
                ['%s', '%s', '%s', '%s', '%d']
            );
        }
    }
}
