<?php

declare(strict_types=1);

namespace PpPhp\Core;

class ProjectState
{
    public static function load(string $slug): array
    {
        $file = self::path($slug);
        if (!file_exists($file)) {
            return self::migrate($slug);   // first time – migrate old files
        }
        $data = json_decode(file_get_contents($file), true);
        if (!is_array($data) || array_is_list($data)) {
            return [];
        }
        return $data;
    }

    /**
     * Save new state data while preserving all existing top‑level keys.
     * Uses a deep merge: any key present in $newData overwrites the same key
     * in the stored file; keys only in the file are kept untouched.
     */
    public static function save(string $slug, array $newData): void
    {
        $file = self::path($slug);
        $dir = dirname($file);
        if (!is_dir($dir)) {
            mkdir($dir, 0755, true);
        }

        // Load the current state and deeply merge the new data on top
        $current = self::load($slug);
        $merged = self::deepMerge($current, $newData);
        $merged['updatedAt'] = date('Y-m-d H:i:s');
        file_put_contents($file, json_encode($merged, JSON_PRETTY_PRINT));
    }

    /** Merge a module’s data and save */
    public static function mergeAndSave(string $slug, string $module, array $data): void
    {
        $state = self::load($slug);
        $state[$module] = $data;
        self::save($slug, $state);
    }

    /** Get a module's data */
    public static function get(string $slug, string $module, array $default = []): array
    {
        $state = self::load($slug);
        return $state[$module] ?? $default;
    }

    // ── private ──────────────────────────────────────────────

    private static function path(string $slug): string
    {
        $username = $_SESSION['user']['username'] ?? 'default';
        return constant('BASE_PATH') . "/projects/{$username}/{$slug}/config/project.json";
    }

    /**
     * Recursively merge two arrays.
     * $b overwrites $a for matching associative keys.
     */
    private static function deepMerge(array $a, array $b): array
    {
        foreach ($b as $key => $value) {
            if (
                is_array($value) && isset($a[$key]) && is_array($a[$key]) &&
                !array_is_list($value) && !array_is_list($a[$key])
            ) {
                $a[$key] = self::deepMerge($a[$key], $value);
            } else {
                $a[$key] = $value;
            }
        }
        return $a;
    }

    /**
     * Migrate old separate state files into the unified project.json.
     */
    private static function migrate(string $slug): array
    {
        $username = $_SESSION['user']['username'] ?? 'default';
        $base = constant('BASE_PATH') . "/projects/{$username}/{$slug}/config";
        $state = [];

        // Tables
        $tFile = "$base/table_state.json";
        if (file_exists($tFile)) {
            $t = json_decode(file_get_contents($tFile), true);
            $state['tables'] = [
                'selectedTables' => $t['selectedTables'] ?? [],
                'positions'      => $t['positions'] ?? [],
            ];
            @unlink($tFile);
        }

        // Relations
        $rFile = "$base/relations.json";
        if (file_exists($rFile)) {
            $state['tables']['relations'] = json_decode(file_get_contents($rFile), true) ?? [];
            @unlink($rFile);
        }

        // Queries (individual files → merged)
        $qDir = "$base/queries";
        if (is_dir($qDir)) {
            $saved = [];
            foreach (glob("$qDir/*.json") as $file) {
                $name = pathinfo($file, PATHINFO_FILENAME);
                $content = json_decode(file_get_contents($file), true);
                if ($content) $saved[$name] = $content;
                @unlink($file);
            }
            if (!empty($saved)) $state['queries'] = ['saved' => $saved];
            @rmdir($qDir);
        }

        if (!empty($state)) self::save($slug, $state);
        return $state;
    }
}