<?php

declare(strict_types=1);

namespace PpPhp\Core\Projects;

use PpPhp\Core\DB;

/** Central metadata for reusable project templates; package contents stay on disk. */
final class ProjectTemplateCatalog
{
    private static bool $ready = false;

    public static function schemaSql(): string
    {
        return "CREATE TABLE IF NOT EXISTS `project_templates` (
            `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
            `owner_id` INT NOT NULL,
            `name` VARCHAR(100) NOT NULL,
            `slug` VARCHAR(100) NOT NULL,
            `description` TEXT,
            `category` VARCHAR(50) NOT NULL DEFAULT 'General',
            `tags_json` TEXT,
            `source_project_slug` VARCHAR(100) DEFAULT NULL,
            `package_path` VARCHAR(500) NOT NULL,
            `manifest_json` MEDIUMTEXT,
            `color` VARCHAR(20) NOT NULL DEFAULT '#4f46e5',
            `icon` VARCHAR(50) NOT NULL DEFAULT 'window-stack',
            `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
            `updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
            UNIQUE KEY `uq_project_template_owner_slug` (`owner_id`, `slug`),
            INDEX `idx_project_template_owner_updated` (`owner_id`, `updated_at`),
            CONSTRAINT `fk_project_template_owner` FOREIGN KEY (`owner_id`) REFERENCES `users` (`id`) ON DELETE CASCADE
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4";
    }

    public static function ensureSchema(): void
    {
        if (self::$ready) return;
        DB::Init(); DB::SetConnection(); DB::Exec(self::schemaSql());
        if (DB::LastError() !== '') throw new \RuntimeException('Could not prepare project templates: ' . DB::LastError());
        self::$ready = true;
    }

    public static function forOwner(int $ownerId): array
    {
        self::ensureSchema();
        $rows = DB::Select('project_templates', ['owner_id' => $ownerId], 'updated_at DESC');
        return array_map([self::class, 'normalize'], is_array($rows) ? $rows : []);
    }

    public static function findOwned(int $id, int $ownerId): array
    {
        self::ensureSchema();
        $rows = DB::Select('project_templates', ['id' => $id, 'owner_id' => $ownerId]);
        if (empty($rows)) throw new \RuntimeException('Project template not found.', 404);
        return self::normalize($rows[0]);
    }

    public static function slugExists(int $ownerId, string $slug): bool
    {
        self::ensureSchema();
        return !empty(DB::Select('project_templates', ['owner_id' => $ownerId, 'slug' => $slug]));
    }

    public static function create(array $values): int
    {
        self::ensureSchema();
        $id = DB::Insert('project_templates', [
            'owner_id' => (int)$values['owner_id'], 'name' => (string)$values['name'], 'slug' => (string)$values['slug'],
            'description' => (string)($values['description'] ?? ''), 'category' => (string)($values['category'] ?? 'General'),
            'tags_json' => json_encode(array_values((array)($values['tags'] ?? [])), JSON_UNESCAPED_SLASHES),
            'source_project_slug' => (string)($values['source_project_slug'] ?? ''), 'package_path' => (string)$values['package_path'],
            'manifest_json' => json_encode((array)($values['manifest'] ?? []), JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE),
            'color' => (string)($values['color'] ?? '#4f46e5'), 'icon' => (string)($values['icon'] ?? 'window-stack'),
        ]);
        if ($id === false) throw new \RuntimeException('Could not save the project template: ' . DB::LastError());
        return $id;
    }

    public static function remove(int $id, int $ownerId): void
    {
        self::ensureSchema();
        if (DB::Delete('project_templates', ['id' => $id, 'owner_id' => $ownerId]) === false) {
            throw new \RuntimeException('Could not remove the project template: ' . DB::LastError());
        }
    }

    private static function normalize(array $row): array
    {
        $manifest = json_decode((string)($row['manifest_json'] ?? ''), true);
        $tags = json_decode((string)($row['tags_json'] ?? ''), true);
        return [
            'id' => (int)$row['id'], 'owner_id' => (int)$row['owner_id'], 'name' => (string)$row['name'], 'slug' => (string)$row['slug'],
            'description' => (string)($row['description'] ?? ''), 'category' => (string)($row['category'] ?? 'General'),
            'tags' => is_array($tags) ? $tags : [], 'source_project_slug' => (string)($row['source_project_slug'] ?? ''),
            'package_path' => (string)$row['package_path'], 'manifest' => is_array($manifest) ? $manifest : [],
            'color' => (string)($row['color'] ?? '#4f46e5'), 'icon' => (string)($row['icon'] ?? 'window-stack'),
            'created_at' => (string)$row['created_at'], 'updated_at' => (string)$row['updated_at'],
        ];
    }
}
