<?php
declare(strict_types=1);
namespace PpPhp\Core\Projects;
use PpPhp\Core\DB;

final class ProjectVersionCatalog
{
    private static bool $ready=false;
    public static function schemaSql(): string{return "CREATE TABLE IF NOT EXISTS `project_versions` (`id` BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,`project_id` INT NOT NULL,`owner_id` INT NOT NULL,`label` VARCHAR(120) NOT NULL,`notes` TEXT,`kind` VARCHAR(30) NOT NULL DEFAULT 'manual',`package_path` VARCHAR(500) NOT NULL,`manifest_json` MEDIUMTEXT,`package_size` BIGINT NOT NULL DEFAULT 0,`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,INDEX `idx_project_versions_project_created` (`project_id`,`created_at`),CONSTRAINT `fk_project_versions_project` FOREIGN KEY (`project_id`) REFERENCES `projects` (`id`) ON DELETE CASCADE,CONSTRAINT `fk_project_versions_owner` FOREIGN KEY (`owner_id`) REFERENCES `users` (`id`) ON DELETE CASCADE) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4";}
    public static function settingsSchemaSql(): string{return "CREATE TABLE IF NOT EXISTS `project_vcs_settings` (`project_id` INT NOT NULL PRIMARY KEY,`remote_url` VARCHAR(500) DEFAULT NULL,`default_branch` VARCHAR(100) NOT NULL DEFAULT 'main',`author_name` VARCHAR(120) DEFAULT NULL,`author_email` VARCHAR(190) DEFAULT NULL,`auto_checkpoint` TINYINT(1) NOT NULL DEFAULT 1,`updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,CONSTRAINT `fk_project_vcs_project` FOREIGN KEY (`project_id`) REFERENCES `projects` (`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 history: '.DB::LastError());DB::Exec(self::settingsSchemaSql());if(DB::LastError()!=='')throw new \RuntimeException('Could not prepare version-control settings: '.DB::LastError());self::$ready=true;}
    public static function create(array $v):int{self::ensureSchema();$id=DB::Insert('project_versions',['project_id'=>(int)$v['project_id'],'owner_id'=>(int)$v['owner_id'],'label'=>(string)$v['label'],'notes'=>(string)($v['notes']??''),'kind'=>(string)($v['kind']??'manual'),'package_path'=>(string)$v['package_path'],'manifest_json'=>json_encode((array)($v['manifest']??[]),JSON_UNESCAPED_SLASHES|JSON_UNESCAPED_UNICODE),'package_size'=>(int)($v['package_size']??0)]);if($id===false)throw new \RuntimeException('Could not record the checkpoint: '.DB::LastError());return $id;}
    public static function forProject(int $projectId,int $ownerId):array{self::ensureSchema();$rows=DB::Select('project_versions',['project_id'=>$projectId,'owner_id'=>$ownerId],'created_at DESC');return array_map([self::class,'normalize'],is_array($rows)?$rows:[]);}
    public static function findOwned(int $id,int $projectId,int $ownerId):array{self::ensureSchema();$rows=DB::Select('project_versions',['id'=>$id,'project_id'=>$projectId,'owner_id'=>$ownerId]);if(empty($rows))throw new \RuntimeException('Checkpoint not found.',404);return self::normalize($rows[0]);}
    public static function remove(int $id,int $projectId,int $ownerId):void{self::ensureSchema();if(DB::Delete('project_versions',['id'=>$id,'project_id'=>$projectId,'owner_id'=>$ownerId])===false)throw new \RuntimeException('Could not delete the checkpoint: '.DB::LastError());}
    public static function settings(int $projectId):array{self::ensureSchema();$rows=DB::Select('project_vcs_settings',['project_id'=>$projectId]);return $rows[0]??['project_id'=>$projectId,'remote_url'=>'','default_branch'=>'main','author_name'=>'','author_email'=>'','auto_checkpoint'=>1];}
    public static function saveSettings(int $projectId,array $v):array{self::ensureSchema();$existing=DB::Select('project_vcs_settings',['project_id'=>$projectId]);$data=['remote_url'=>(string)($v['remote_url']??''),'default_branch'=>(string)($v['default_branch']??'main'),'author_name'=>(string)($v['author_name']??''),'author_email'=>(string)($v['author_email']??''),'auto_checkpoint'=>!empty($v['auto_checkpoint'])?1:0];$ok=$existing?DB::Update('project_vcs_settings',$data,['project_id'=>$projectId]):DB::Insert('project_vcs_settings',['project_id'=>$projectId]+$data);if($ok===false)throw new \RuntimeException('Could not save version-control settings: '.DB::LastError());return self::settings($projectId);}
    private static function normalize(array $r):array{$m=json_decode((string)($r['manifest_json']??''),true);return ['id'=>(int)$r['id'],'project_id'=>(int)$r['project_id'],'owner_id'=>(int)$r['owner_id'],'label'=>(string)$r['label'],'notes'=>(string)($r['notes']??''),'kind'=>(string)$r['kind'],'package_path'=>(string)$r['package_path'],'manifest'=>is_array($m)?$m:[],'package_size'=>(int)$r['package_size'],'created_at'=>(string)$r['created_at']];}
}
