<?php
declare(strict_types=1);

namespace ROITheme\Shared\Infrastructure\Adapters;

use ROITheme\Shared\Infrastructure\Di\DIContainer;
use ROITheme\Shared\Domain\ValueObjects\ComponentName;
use ROITheme\Shared\Domain\ValueObjects\ComponentConfiguration;
use ROITheme\Shared\Domain\Contracts\ComponentRepositoryInterface;
use ROITheme\Shared\Domain\Contracts\DefaultRepositoryInterface;

/**
 * LegacyDBManagerAdapter - Adapter para ROI_DB_Manager deprecated
 *
 * RESPONSABILIDAD: Traducir llamadas legacy a la nueva arquitectura
 *
 * PATRÓN: Adapter Pattern
 * - Interfaz antigua (ROI_DB_Manager methods)
 * - Implementación nueva (Clean Architecture repositories)
 *
 * Este adapter mantiene compatibilidad backward mientras se migra el código
 *
 * @package ROITheme\Infrastructure\Adapters
 */
final class LegacyDBManagerAdapter
{
    private ComponentRepositoryInterface $componentRepository;
    private ComponentDefaultsRepositoryInterface $defaultsRepository;

    public function __construct()
    {
        global $wpdb;

        // Get repositories from DI Container
        $schemasPath = get_template_directory() . '/schemas';
        $container = new DIContainer($wpdb, $schemasPath);

        $this->componentRepository = $container->getComponentRepository();
        $this->defaultsRepository = $container->getDefaultsRepository();
    }

    /**
     * Save component configuration (legacy method)
     *
     * Adapta save_config() legacy a WordPressComponentRepository::save()
     *
     * @param string $component_name Component name
     * @param string $config_key Configuration key
     * @param mixed $config_value Configuration value
     * @param string $data_type Data type
     * @param string|null $version Schema version
     * @param string $table_type Table type (components or defaults)
     * @return bool Success status
     */
    public function save_config(
        string $component_name,
        string $config_key,
        $config_value,
        string $data_type = 'string',
        ?string $version = null,
        string $table_type = 'components'
    ): bool {
        try {
            $componentNameVO = new ComponentName($component_name);

            if ($table_type === 'defaults') {
                // Save to defaults repository
                $config = $this->defaultsRepository->exists($componentNameVO)
                    ? $this->defaultsRepository->getByName($componentNameVO)
                    : ComponentConfiguration::fromArray([]);

                $data = $config->toArray();
                $data[$config_key] = $this->convertValue($config_value, $data_type);

                $newConfig = ComponentConfiguration::fromArray($data);
                $this->defaultsRepository->save($componentNameVO, $newConfig);

                return true;
            }

            // Save to component repository
            $component = $this->componentRepository->findByName($componentNameVO);

            if ($component === null) {
                // Create new component with this configuration
                $data = [
                    'visibility' => ['is_enabled' => true],
                    'content' => [$config_key => $this->convertValue($config_value, $data_type)],
                    'styles' => [],
                    'config' => []
                ];

                $newComponent = new \ROITheme\Shared\Domain\Entities\Component(
                    $component_name,
                    $component_name,
                    $data
                );

                $this->componentRepository->save($newComponent);
            } else {
                // Update existing component
                $data = $component->getData();

                // Determinar en qué sección guardar
                $section = $this->determineSection($config_key);
                if (!isset($data[$section])) {
                    $data[$section] = [];
                }

                $data[$section][$config_key] = $this->convertValue($config_value, $data_type);

                $updatedComponent = $component->withData($data);
                $this->componentRepository->save($updatedComponent);
            }

            return true;
        } catch (\Exception $e) {
            // Log error but maintain backward compatibility
            error_log("LegacyDBManagerAdapter::save_config error: " . $e->getMessage());
            return false;
        }
    }

    /**
     * Get component configuration (legacy method)
     *
     * Adapta get_config() legacy a WordPressComponentRepository::findByName()
     *
     * @param string $component_name Component name
     * @param string|null $config_key Specific configuration key (null for all)
     * @param string $table_type Table type (components or defaults)
     * @return mixed Configuration value(s) or null
     */
    public function get_config(
        string $component_name,
        ?string $config_key = null,
        string $table_type = 'components'
    ) {
        try {
            $componentNameVO = new ComponentName($component_name);

            if ($table_type === 'defaults') {
                if (!$this->defaultsRepository->exists($componentNameVO)) {
                    return null;
                }

                $config = $this->defaultsRepository->getByName($componentNameVO);
                $data = $config->toArray();

                return $config_key ? ($data[$config_key] ?? null) : $data;
            }

            // Get from component repository
            $component = $this->componentRepository->findByName($componentNameVO);

            if ($component === null) {
                return null;
            }

            $data = $component->getData();

            if ($config_key === null) {
                // Return all configuration
                return $this->flattenComponentData($data);
            }

            // Search for key in all sections
            foreach (['visibility', 'content', 'styles', 'config'] as $section) {
                if (isset($data[$section][$config_key])) {
                    return $data[$section][$config_key];
                }
            }

            return null;
        } catch (\Exception $e) {
            error_log("LegacyDBManagerAdapter::get_config error: " . $e->getMessage());
            return null;
        }
    }

    /**
     * Delete component configuration (legacy method)
     *
     * Adapta delete_config() legacy a WordPressComponentRepository::delete()
     *
     * @param string $component_name Component name
     * @param string $table_type Table type (components or defaults)
     * @return bool Success status
     */
    public function delete_config(string $component_name, string $table_type = 'components'): bool
    {
        try {
            $componentNameVO = new ComponentName($component_name);

            if ($table_type === 'defaults') {
                return $this->defaultsRepository->delete($componentNameVO);
            }

            return $this->componentRepository->delete($componentNameVO);
        } catch (\Exception $e) {
            error_log("LegacyDBManagerAdapter::delete_config error: " . $e->getMessage());
            return false;
        }
    }

    /**
     * Get component by table (legacy method)
     *
     * @param string $component_name Component name
     * @param string $table_type Table type
     * @return array|null Component data or null
     */
    public function get_component_by_table(string $component_name, string $table_type = 'components'): ?array
    {
        try {
            $componentNameVO = new ComponentName($component_name);

            if ($table_type === 'defaults') {
                if (!$this->defaultsRepository->exists($componentNameVO)) {
                    return null;
                }

                $config = $this->defaultsRepository->getByName($componentNameVO);
                return [
                    'component_name' => $component_name,
                    'default_schema' => json_encode($config->toArray()),
                    'created_at' => '',
                    'updated_at' => ''
                ];
            }

            $component = $this->componentRepository->findByName($componentNameVO);

            if ($component === null) {
                return null;
            }

            return [
                'component_name' => $component_name,
                'configuration' => json_encode($component->getData()),
                'is_enabled' => $component->isEnabled() ? 1 : 0,
                'created_at' => '',
                'updated_at' => ''
            ];
        } catch (\Exception $e) {
            error_log("LegacyDBManagerAdapter::get_component_by_table error: " . $e->getMessage());
            return null;
        }
    }

    /**
     * Convert value to appropriate type
     *
     * @param mixed $value Value to convert
     * @param string $type Target type
     * @return mixed Converted value
     */
    private function convertValue($value, string $type)
    {
        switch ($type) {
            case 'boolean':
                return filter_var($value, FILTER_VALIDATE_BOOLEAN);
            case 'integer':
                return (int) $value;
            case 'array':
                return is_array($value) ? $value : json_decode($value, true);
            case 'string':
            default:
                return (string) $value;
        }
    }

    /**
     * Determine which section a config key belongs to
     *
     * @param string $key Configuration key
     * @return string Section name
     */
    private function determineSection(string $key): string
    {
        // Visibility keys
        if (in_array($key, ['is_enabled', 'sticky', 'show_on_mobile', 'show_on_desktop'])) {
            return 'visibility';
        }

        // Style keys
        if (strpos($key, 'color') !== false || strpos($key, 'font') !== false || strpos($key, 'size') !== false) {
            return 'styles';
        }

        // Config keys
        if (in_array($key, ['auto_close', 'close_delay', 'animation'])) {
            return 'config';
        }

        // Default to content
        return 'content';
    }

    /**
     * Flatten component data for legacy compatibility
     *
     * @param array $data Component data
     * @return array Flattened data
     */
    private function flattenComponentData(array $data): array
    {
        $flattened = [];

        foreach ($data as $section => $values) {
            if (is_array($values)) {
                foreach ($values as $key => $value) {
                    $flattened[$key] = $value;
                }
            }
        }

        return $flattened;
    }
}
