<?php

namespace FleekDash\Services\Theme;

defined('ABSPATH') || exit;

/**
 * Formats themes and palettes for API responses and resolves palette–theme relationships.
 */
final class ThemePresentation
{
    private ThemeStorage $storage;

    public function __construct(ThemeStorage $storage)
    {
        $this->storage = $storage;
    }

    /**
     * @param array<string, mixed> $palette
     * @return array<string, mixed>
     */
    public function formatBundledPalette(array $palette): array
    {
        return [
            'id' => $palette['id'],
            'name' => $palette['name'],
            'description' => $palette['description'],
            'theme' => $palette['theme'],
            'source' => 'bundled',
            'wp_sync_key' => $palette['wp_sync_key'],
            'modes' => PalettePresets::getModes($palette['id']),
        ];
    }

    /**
     * @param array<string, mixed> $palette
     * @return array<string, mixed>
     */
    public function formatCustomPalette(array $palette): array
    {
        return [
            'id' => $palette['id'] ?? '',
            'name' => $palette['name'] ?? '',
            'description' => $palette['description'] ?? '',
            'theme' => $palette['theme'] ?? '',
            'source' => $palette['source'] ?? 'custom',
            'wp_sync_key' => $palette['wp_sync_key'] ?? '',
            'mode_sync_variables' => $palette['mode_sync_variables'] ?? [],
            'modes' => $palette['modes'] ?? [],
            'created_at' => $palette['created_at'] ?? '',
            'updated_at' => $palette['updated_at'] ?? '',
        ];
    }

    /**
     * @param array<string, mixed> $theme
     * @param array<int, array<string, mixed>>|null $customPaletteRows Pre-filtered custom palettes for this theme id;
     *                                                                 null = load from storage (single-theme format path).
     * @return array<string, mixed>
     */
    public function formatBundledTheme(array $theme, ?array $customPaletteRows = null): array
    {
        $palettes = [];
        foreach ($theme['palettes'] as $paletteId) {
            $palette = ThemeRegistry::getBundledPalette($paletteId);
            if ($palette) {
                $palettes[] = $this->formatBundledPalette($palette);
            }
        }

        if ($customPaletteRows === null) {
            $customPaletteRows = [];
            foreach ($this->storage->getCustomPalettes() as $customPalette) {
                if (\sanitize_key($customPalette['theme'] ?? '') === \sanitize_key($theme['id'] ?? '')) {
                    $customPaletteRows[] = $customPalette;
                }
            }
        }

        foreach ($customPaletteRows as $customPalette) {
            $palettes[] = $this->formatCustomPalette($customPalette);
        }

        return [
            'id' => $theme['id'],
            'name' => $theme['name'],
            'description' => $theme['description'],
            'author' => $theme['author'],
            'version' => $theme['version'],
            'source' => 'bundled',
            'is_editable' => false,
            'default_palette' => $theme['default_palette'],
            'palettes' => $palettes,
        ];
    }

    /**
     * @param array<string, mixed> $theme
     * @param callable(string): (?array<string, mixed>) $resolvePalette
     * @return array<string, mixed>
     */
    public function formatCustomTheme(array $theme, callable $resolvePalette): array
    {
        $palettes = [];
        foreach ($theme['palettes'] ?? [] as $paletteId) {
            $palette = $resolvePalette($paletteId);
            if ($palette) {
                $palettes[] = $palette;
            }
        }

        return [
            'id' => $theme['id'] ?? '',
            'name' => $theme['name'] ?? '',
            'description' => $theme['description'] ?? '',
            'author' => $theme['author'] ?? '',
            'version' => $theme['version'] ?? '1.0.0',
            'source' => 'custom',
            'is_editable' => true,
            'default_palette' => $theme['default_palette'] ?? '',
            'palettes' => $palettes,
            'color_modes' => $theme['color_modes'] ?? [],
            'parent_theme' => $theme['parent_theme'] ?? 'starter',
            'created_at' => $theme['created_at'] ?? '',
            'updated_at' => $theme['updated_at'] ?? '',
        ];
    }

    /**
     * @param mixed $palettes
     * @return array<int, string>
     */
    public function sanitizePaletteIds($palettes): array
    {
        if (!is_array($palettes)) {
            return [];
        }

        $ids = [];
        foreach ($palettes as $paletteId) {
            $paletteId = \sanitize_key($paletteId);
            if ($paletteId !== '') {
                $ids[] = $paletteId;
            }
        }

        return $ids;
    }

    /**
     * @param mixed $paletteEntry Theme palette entry (palette id string or palette array).
     */
    private function paletteEntryMatchesId(string $paletteId, $paletteEntry): bool
    {
        if (is_array($paletteEntry)) {
            return \sanitize_key($paletteEntry['id'] ?? '') === $paletteId;
        }
        if (is_string($paletteEntry)) {
            return \sanitize_key($paletteEntry) === $paletteId;
        }

        return false;
    }

    /**
     * @param callable(string): (?array<string, mixed>) $getTheme
     * @param callable(string): (?array<string, mixed>) $getPalette
     */
    public function paletteBelongsToTheme(
        string $paletteId,
        string $themeId,
        callable $getTheme,
        callable $getPalette
    ): bool {
        $paletteId = \sanitize_key($paletteId);
        $belongs = false;
        $theme = $paletteId !== '' ? $getTheme($themeId) : null;

        if ($theme) {
            foreach ($theme['palettes'] ?? [] as $paletteEntry) {
                if ($this->paletteEntryMatchesId($paletteId, $paletteEntry)) {
                    $belongs = true;
                    break;
                }
            }
            if (!$belongs) {
                $paletteRow = $getPalette($paletteId);
                $belongs = $paletteRow && \sanitize_key($paletteRow['theme'] ?? '') === $themeId;
            }
        }

        return $belongs;
    }

    /**
     * @param callable(string): (?array<string, mixed>) $getTheme
     */
    public function resolveDefaultPaletteForTheme(string $themeId, callable $getTheme): string
    {
        $themeId = \sanitize_key($themeId);
        $default = '';
        $theme = $getTheme($themeId);
        if ($theme && !empty($theme['default_palette'])) {
            $default = \sanitize_key($theme['default_palette']);
        }
        if ($default === '') {
            $bundled = ThemeRegistry::getBundledTheme($themeId);
            if ($bundled && !empty($bundled['default_palette'])) {
                $default = \sanitize_key($bundled['default_palette']);
            }
        }
        if ($default === '') {
            $default = 'starter-fresh';
        }

        return $default;
    }
}
