<?php
declare(strict_types=1);

namespace App\Theme;

use App\Settings\SettingsRepository;
use InvalidArgumentException;
use RuntimeException;

final class ThemeProfileService
{
    public function __construct(private readonly ThemeProfileRepository $profiles, private readonly SettingsRepository $settings) {}

    /** @param array<string,mixed> $tokens */
    public function create(string $name, string $description, array $tokens, int $actorId): int
    {
        $safe=$this->validate($name,$description,$tokens);return $this->profiles->create($safe['name'],$safe['description'],$safe['tokens'],$actorId);
    }
    public function duplicate(int $id,int $actorId):int{$profile=$this->require($id);return $this->profiles->create((string)$profile['name'].' Copy',(string)($profile['description']??''),(array)$profile['tokens'],$actorId);}
    /** @param array<string,mixed> $tokens */
    public function update(int $id,string $name,string $description,array $tokens,int $actorId):void{$safe=$this->validate($name,$description,$tokens);$this->profiles->update($id,$safe['name'],$safe['description'],$safe['tokens'],$actorId);if(!empty($this->require($id)['is_active']))$this->persistActive($id,$safe['tokens']);}
    public function apply(int $id,int $actorId):void{$profile=$this->require($id);$errors=ThemeTokenService::validateForApply((array)$profile['tokens']);if($errors!==[])throw new InvalidArgumentException('Theme profile failed apply validation: '.implode(', ',$errors));$this->profiles->activate($id);$this->persistActive($id,(array)$profile['tokens']);}
    public function restore(int $id,int $versionId,int $actorId):void{$current=$this->require($id);$version=$this->profiles->version($id,$versionId);if($version===null)throw new RuntimeException('Theme profile version not found.');$this->profiles->update($id,(string)$current['name'],(string)($current['description']??''),(array)$version['tokens'],$actorId);if(!empty($current['is_active']))$this->persistActive($id,(array)$version['tokens']);}
    public function import(string $json,int $actorId):int{$data=ThemeProfilePackageService::import($json);return $this->create($data['name'],$data['description'],$data['tokens'],$actorId);}
    public function delete(int $id):void{$this->profiles->delete($id);}
    public function export(int $id):string{$profile=$this->require($id);return ThemeProfilePackageService::export((string)$profile['name'],(string)($profile['description']??''),(array)$profile['tokens']);}
    /** @return array<string,mixed> */ public function require(int $id):array{$profile=$this->profiles->find($id);if($profile===null)throw new RuntimeException('Theme profile not found.');return $profile;}
    /** @param array<string,mixed> $tokens @return array{name:string,description:string,tokens:array<string,array<string,string>>} */
    private function validate(string $name,string $description,array $tokens):array{$name=trim($name);$description=trim($description);$len=static fn(string $v):int=>function_exists('mb_strlen')?mb_strlen($v,'UTF-8'):strlen($v);if($name===''||$len($name)>120||$len($description)>500)throw new InvalidArgumentException('Theme profile metadata is invalid.');$safe=ThemeTokenService::normalize($tokens);return ['name'=>$name,'description'=>$description,'tokens'=>$safe];}
    /** @param array<string,mixed> $tokens */ private function persistActive(int $id,array $tokens):void{$this->settings->put('theme.profile_id',$id,'integer');$this->settings->put('theme.tokens',ThemeTokenService::normalize($tokens),'json');}
}
