<?php

declare(strict_types=1);

namespace PpPhp\Modules\ProjectWorkspace\Controllers;

use PpPhp\Core\Config;
use PpPhp\Core\DB;
use PpPhp\Core\Security;
use PpPhp\Core\ProjectNav;
use PpPhp\Core\DatabaseConnection;
use PpPhp\Core\ProjectCatalog;
use PpPhp\Core\ModuleState;

class WorkspaceController
{
    public function __construct(private Config $config) {}

    public function index(string $slug): string
    {
        Security::RequireAuth();

        // Fetch project (owner or superadmin)
        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);
            return 'Project not found.';
        }
        $project = $project[0];

        // Opening a project is activity, not a content modification.
        ProjectCatalog::touchOpened((int)$project['id']);

        // A one-shot flash (e.g. a locked DB-only module bounced us here).
        $projectFlash = $_SESSION['project_flash'] ?? null;
        unset($_SESSION['project_flash']);

        // Variables needed by the shell
        $baseUrl   = $this->config->get('base_url');
        $assetsUrl = $this->config->get('assets_url');
        $user      = Security::CurrentUserData();
        $pageTitle = 'Workspace';

        $projectOwner = Security::CurrentUsername();
        if ((int)($project['created_by'] ?? 0) !== (int)($user['id'] ?? 0)) {
            $owner = DB::Select('users', ['id' => $project['created_by'] ?? 0]);
            $projectOwner = (string)($owner[0]['username'] ?? $projectOwner);
        }
        $projectDir = constant('BASE_PATH') . '/projects/' . $projectOwner . '/' . $slug;
        // Standalone (database-free) project: no DB, DB-only modules locked.
        $standalone = \PpPhp\Core\ProjectDatabaseProfile::isStandalone($projectDir);
        // Sidebar navigation (centralised) — locks the DB-only modules on standalone.
        $navItems = ProjectNav::items('/workspace', $standalone);
        $connection = ['type' => 'mysql', 'host' => '', 'dbname' => ''];
        $configPath = $projectDir . '/config/database.php';
        if (!$standalone && is_file($configPath)) {
            try {
                $connection = DatabaseConnection::normalize((array)require $configPath);
            } catch (\Throwable) {
                // Keep the workspace available even when a connection profile needs attention.
            }
        }

        $tablesState = $this->readJson($projectDir . '/config/tables.json');
        $pagesState = $this->readJson($projectDir . '/config/pages.json');
        $designerState = $this->readJson($projectDir . '/config/designer.json');
        $outputState = $this->readJson($projectDir . '/config/output.json');
        $selectedTableCount = count((array)($tablesState['selectedTables'] ?? []));
        $configuredPageTables = count((array)($pagesState['byTable'] ?? []));
        $designedTableCount = count((array)($designerState['pages'] ?? []));
        $milestones = [
            $selectedTableCount > 0,
            $configuredPageTables > 0,
            $designedTableCount > 0,
            !empty($outputState['general']),
        ];
        $workspaceStats = [
            'tables' => $selectedTableCount,
            'pageTables' => $configuredPageTables,
            'designs' => $designedTableCount,
            'progress' => $standalone
                ? ($designedTableCount > 0 ? 100 : 40)
                : (int)round((count(array_filter($milestones)) / count($milestones)) * 100),
            'databaseLabel' => $standalone ? 'Standalone' : DatabaseConnection::label((string)($connection['type'] ?? 'mysql')),
            'databaseTarget' => $standalone ? 'No database' : (($connection['type'] ?? 'mysql') === 'sqlite'
                ? basename((string)($connection['path'] ?? 'app.sqlite'))
                : (string)($connection['dbname'] ?? '')),
        ];
        // The workspace reuses the Projects database editor so database
        // capabilities and PDO availability always come from one source.
        $databaseTypes = DatabaseConnection::definitions();

        // ── Resume where you left off ──────────────────────────────────
        // Only when the project is opened at its root (/project/{slug}), not
        // when Workspace is reached via the toolbar (/project/{slug}/workspace).
        $resumePrompt = null;
        $reqPath = strtok((string) ($_SERVER['REQUEST_URI'] ?? ''), '?');
        $isFreshOpen = !str_ends_with(rtrim($reqPath, '/'), '/workspace');
        if ($isFreshOpen) {
            $resume = ModuleState::load($slug, '_resume');
            $resumeUri = (string) ($resume['uri'] ?? '');
            if ($resumeUri !== '' && $resumeUri !== '/workspace') {
                foreach (ProjectNav::items() as $navItem) {
                    if (($navItem['uri'] ?? '') === $resumeUri) {
                        $resumePrompt = [
                            'url'   => $baseUrl . '/project/' . rawurlencode($slug) . $resumeUri,
                            'label' => (string) $navItem['label'],
                        ];
                        break;
                    }
                }
            }
        }

        ob_start();
        include __DIR__ . '/../Views/partials/welcome.php';
        $innerContent = ob_get_clean();

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

    /**
     * Record the screen the user is currently on, so opening the project later
     * can offer to jump back here. Stored per-user (ModuleState paths are keyed
     * by the current username). Only known SPA pages are accepted.
     */
    public function saveResume(string $slug): void
    {
        header('Content-Type: application/json');
        Security::RequireAuth();

        $input = json_decode((string) file_get_contents('php://input'), true) ?: [];
        $uri = (string) ($input['uri'] ?? '');

        $valid = array_column(ProjectNav::items(), 'uri');
        if (!in_array($uri, $valid, true)) {
            echo json_encode(['success' => false, 'message' => 'Unknown screen.']);
            exit;
        }

        ModuleState::save($slug, '_resume', ['uri' => $uri, 'ts' => time()]);
        echo json_encode(['success' => true]);
        exit;
    }

    private function readJson(string $path): array
    {
        if (!is_file($path)) {
            return [];
        }
        $decoded = json_decode((string)file_get_contents($path), true);
        return is_array($decoded) ? $decoded : [];
    }
}
