<?php
declare(strict_types=1);

namespace PpPhp\Core\Designer\Shell;

use PpPhp\Core\Assets\AssetRuntime;
use PpPhp\Core\Designer\Auth\DesignerAuthRuntime;
use PpPhp\Core\Designer\Dashboard\DesignerDashboardRuntime;
use PpPhp\Core\Designer\DataGrid\DesignerDataGridRuntime;
use PpPhp\Core\Designer\Form\DesignerFormRuntime;
use PpPhp\Core\Designer\Navigation\DesignerNavigationRuntime;

final class DesignerApplicationShellRuntime
{
    private array $operations = [];

    public function createCrudApplication(string $appId, string $title, array $tables): array
    {
        $gridRuntime = new DesignerDataGridRuntime();
        $formRuntime = new DesignerFormRuntime();
        $dashboardRuntime = new DesignerDashboardRuntime();
        $navRuntime = new DesignerNavigationRuntime();
        $authRuntime = new DesignerAuthRuntime();
        $assetRuntime = new AssetRuntime();

        $pages = [];

        foreach ($tables as $table => $fields) {
            $tableName = is_string($table) ? $table : (string) $fields;
            $fieldRows = is_array($fields) ? $fields : [
                ['name' => 'id', 'type' => 'number'],
                ['name' => 'name', 'type' => 'text'],
                ['name' => 'created_at', 'type' => 'datetime'],
            ];

            $pages[] = $gridRuntime->pageFor($tableName, $fieldRows);
            $pages[] = $formRuntime->pageFor($tableName, 'add', $fieldRows);
            $pages[] = $formRuntime->pageFor($tableName, 'edit', $fieldRows);
            $pages[] = $formRuntime->pageFor($tableName, 'view', $fieldRows);
        }

        $dashboard = $dashboardRuntime->pageFor('admin');
        array_unshift($pages, $dashboard);

        $authPages = $authRuntime->createSuite();
        $navigation = $navRuntime->fromPages($appId . '_menu', $pages);
        $routes = $navRuntime->routesFromPages(array_merge($pages, array_values($authPages)));
        $assets = $assetRuntime->packageForGeneratedApp(['inter-font', 'designer-base-theme', 'bootstrap-icons', 'chartjs'], $appId);

        $shell = DesignerApplicationShellDefinition::create($appId, $title, $navigation, $dashboard, $pages, $authPages, $routes, $assets)->toArray();

        $this->record('createCrudApplication', ['appId' => $appId, 'tables' => count($tables), 'pages' => count($pages)]);
        return $shell;
    }

    public function render(array $shell): string
    {
        $html = [];
        $html[] = '<div class="ppd-application-shell" data-app-id="' . $this->e((string) ($shell['appId'] ?? 'app')) . '">';
        $html[] = '<aside class="ppd-shell-sidebar">{{ navigation }}</aside>';
        $html[] = '<main class="ppd-shell-main"><header><h1>' . $this->e((string) ($shell['title'] ?? 'Application')) . '</h1></header><section>{{ page }}</section></main>';
        $html[] = '</div>';
        return implode('', $html);
    }

    public function validate(array $shell): array
    {
        $summary = (array) ($shell['summary'] ?? []);

        return [
            'ok' => ($shell['type'] ?? '') === 'application_shell'
                && ($summary['pages'] ?? 0) >= 5
                && ($summary['authPages'] ?? 0) >= 8
                && ($summary['routes'] ?? 0) >= (($summary['pages'] ?? 0) + ($summary['authPages'] ?? 0)),
            'pages' => $summary['pages'] ?? 0,
            'authPages' => $summary['authPages'] ?? 0,
            'routes' => $summary['routes'] ?? 0,
            'assets' => $summary['assets'] ?? 0,
        ];
    }

    public function operations(): array { return $this->operations; }

    public function stats(): array
    {
        return [
            'operations' => count($this->operations),
            'applications' => count(array_filter($this->operations, static fn (array $op): bool => ($op['operation'] ?? '') === 'createCrudApplication')),
        ];
    }

    private function record(string $operation, array $payload): void
    {
        $this->operations[] = ['operation' => $operation, 'payload' => $payload, 'createdAt' => date('c')];
    }

    private function e(string $value): string
    {
        return htmlspecialchars($value, ENT_QUOTES, 'UTF-8');
    }
}
