<?php

declare(strict_types=1);

namespace PpPhp\Modules\Pages\Controllers;

use PpPhp\Core\Config;
use PpPhp\Core\ModuleManager;
use PpPhp\Core\DB;
use PpPhp\Core\DatabaseConnection;
use PpPhp\Core\Database\Dialect\DatabaseDialectRegistry;
use PpPhp\Core\Database\Dialect\DatabaseDialectInterface;
use PpPhp\Core\Security;
use PpPhp\Core\ProjectNav;
use PpPhp\Core\ModuleState;

class PagesController
{
    private array $project = [];
    private string $slug = '';
    private array $databaseConfig = [];
    private ?DatabaseDialectInterface $dialect = null;

    public function __construct(
        private Config $config,
        private ModuleManager $moduleManager
    ) {}

    /**
     * Main SPA page.
     */
    public function index(string $slug): string
    {
        $this->initProject($slug);
        $project = $this->project;

        // Load Tables module state (selected tables)
        $tablesState = ModuleState::load($slug, 'tables');
        $selectedTableNames = $tablesState['selectedTables'] ?? [];

        $tables = [];
        if (empty($selectedTableNames)) {
            // Fallback: show all tables if none selected. Use the project's dialect
            // so this works on every engine (SHOW FULL TABLES is MySQL-only and would
            //500 the whole SPA on pgsql/sqlite/sqlsrv/oci).
            try {
                if ($this->dialect !== null) {
                    $tables = $this->dialect->listObjects(DB::Pdo(), $this->databaseConfig);
                } else {
                    $rows = DB::Query('SHOW FULL TABLES')->fetchAll(\PDO::FETCH_NUM);
                    foreach ($rows as $row) {
                        $tables[] = ['name' => $row[0], 'type' => ($row[1] === 'VIEW') ? 'VIEW' : 'TABLE'];
                    }
                }
            } catch (\Throwable $e) {
                $tables = [];
            }
            usort($tables, fn($a, $b) => $a['name'] <=> $b['name']);
        } else {
            foreach ($selectedTableNames as $tableName) {
                $tables[] = ['name' => $tableName, 'type' => 'TABLE'];
            }
        }

        // Pages config now comes from its own file (config/pages.json)
        $pagesState = ModuleState::load($slug, 'pages');
        $pagesConfig = $pagesState['byTable'] ?? [];
        $currentTableName = $pagesState['activeTable'] ?? null;

        $navItems = ProjectNav::items('/pages');
        $baseUrl   = $this->config->get('base_url');
        $assetsUrl = $this->config->get('assets_url');
        $user      = $_SESSION['user'];
        $pageTitle = 'Pages';

        ob_start();
        include __DIR__ . '/../Views/index.php';
        return ob_get_clean();
    }

    // ── Private helpers ────────────────────────────────────────────────

    private function initProject(string $slug): void
    {
        Security::RequireAuth();
        $this->slug = $slug;

        DB::Init(); // central DB
        $project = DB::Select('projects', ['slug' => $slug, 'created_by' => Security::CurrentUserData()['id']]);
        if (empty($project) && Security::IsAdmin()) {
            $project = DB::Select('projects', ['slug' => $slug]);
        }
        if (empty($project)) {
            http_response_code(404);
            echo 'Project not found.';
            exit;
        }
        $this->project = $project[0];
        if (\PpPhp\Core\ProjectDatabaseProfile::isStandaloneSlug($slug)) {
            $_SESSION['project_flash'] = 'Pages isn’t available for standalone apps — this project has no database.';
            redirect('/project/' . rawurlencode($slug) . '/workspace');
        }
        DB::Init($slug);
        DB::SetConnection($slug);

        $configPath = \PpPhp\Core\ProjectLocator::dir($this->slug) . '/config/database.php';
        if (is_file($configPath)) {
            $this->databaseConfig = DatabaseConnection::normalize((array) require $configPath);
            $this->dialect = DatabaseDialectRegistry::forConfig($this->databaseConfig);
        }
    }


    /**
     * Save state for a single table (used by auto-save).
     */
    public function saveState(string $slug): void
    {
        header('Content-Type: application/json');
        $this->initProject($slug);
        \PpPhp\Core\Security::RequireCsrf(); // beacon carries the token via the keepalive-fetch shim

        $input = json_decode(file_get_contents('php://input'), true) ?? $_POST;
        $tableName = $input['tableName'] ?? '';
        $state = $input['state'] ?? [];

        if ($tableName === '' || empty($state)) {
            http_response_code(400);
            echo json_encode(['success' => false, 'message' => 'Table name and state are required.']);
            exit;
        }

        // Load existing pages state
        $pagesState = ModuleState::load($slug, 'pages');
        if (!is_array($pagesState) || array_is_list($pagesState)) {
            $pagesState = [];
        }
        if (!isset($pagesState['byTable'])) {
            $pagesState['byTable'] = [];
        }

        // Merge this table's state
        $pagesState['byTable'][$tableName] = $state;
        $pagesState['activeTable'] = $tableName;

        ModuleState::save($slug, 'pages', $pagesState);

        echo json_encode(['success' => true]);
        exit;
    }


    /**
     * Load pages configuration for a table.
     */
    public function load(string $slug, string $table): void
    {
        header('Content-Type: application/json');
        $this->initProject($slug);

        $state = ModuleState::load($slug, 'pages');
        $config = $state['byTable'][$table] ?? [
            'pageTypes'    => ['list'],
            'functionality' => [
                'spreadsheet'    => false,
                'updateSelected' => false,
                'inlineEdit'     => false,
                'inlineAdd'      => false,
                'deleteRecords'  => true,
                'copyRecords'    => false,
            ],
            'keyColumns'   => [],
            'settings'     => new \stdClass(),
        ];

        echo json_encode(['success' => true, 'config' => $config]);
        exit;
    }
}
