<?php
declare(strict_types=1);
namespace App\Services;
use App\Core\Database;
use InvalidArgumentException;
use PDO;
final class StudioFormService
{
    public function module(int $id): ?array { $s=Database::connection()->prepare("SELECT * FROM axiom_studio_modules WHERE id=:id AND archived_at IS NULL");$s->execute(['id'=>$id]);$r=$s->fetch(PDO::FETCH_ASSOC);return $r?:null; }
    public function entities(int $moduleId): array { $s=Database::connection()->prepare("SELECT * FROM axiom_studio_entities WHERE module_id=:id AND archived_at IS NULL ORDER BY position,name");$s->execute(['id'=>$moduleId]);return $s->fetchAll(PDO::FETCH_ASSOC); }
    public function entity(int $id): ?array { $s=Database::connection()->prepare("SELECT * FROM axiom_studio_entities WHERE id=:id AND archived_at IS NULL");$s->execute(['id'=>$id]);$r=$s->fetch(PDO::FETCH_ASSOC);return $r?:null; }
    public function fields(int $entityId): array { $s=Database::connection()->prepare("SELECT * FROM axiom_studio_fields WHERE entity_id=:id AND archived_at IS NULL ORDER BY position,id");$s->execute(['id'=>$entityId]);return $s->fetchAll(PDO::FETCH_ASSOC); }
    public function form(int $entityId): ?array { $s=Database::connection()->prepare("SELECT * FROM axiom_studio_forms WHERE entity_id=:id AND archived_at IS NULL ORDER BY id DESC LIMIT 1");$s->execute(['id'=>$entityId]);$r=$s->fetch(PDO::FETCH_ASSOC);return $r?:null; }
    public function components(int $formId): array { $s=Database::connection()->prepare("SELECT c.*,f.label field_label,f.field_type FROM axiom_studio_form_components c LEFT JOIN axiom_studio_fields f ON f.id=c.field_id WHERE c.form_id=:id AND c.archived_at IS NULL ORDER BY c.position,id");$s->execute(['id'=>$formId]);return $s->fetchAll(PDO::FETCH_ASSOC); }
    public function ensureForm(int $moduleId,int $entityId,?int $userId): int {
        $entity=$this->entity($entityId); if(!$entity || (int)$entity['module_id']!==$moduleId) throw new InvalidArgumentException('Entité invalide.');
        $existing=$this->form($entityId); if($existing) return (int)$existing['id'];
        $s=Database::connection()->prepare("INSERT INTO axiom_studio_forms(module_id,entity_id,name,code,layout_json,created_by,updated_by) VALUES(:m,:e,:n,:c,'{}',:u,:u)");
        $s->execute(['m'=>$moduleId,'e'=>$entityId,'n'=>'Formulaire '.$entity['name'],'c'=>$entity['code'].'_form','u'=>$userId]); return (int)Database::connection()->lastInsertId();
    }
    public function addComponent(int $formId,array $input,?int $userId): int {
        $fieldId=(int)($input['field_id']??0); $type=trim((string)($input['component_type']??'text')); $allowed=['text','textarea','select','checkbox','radio','date','time','datetime','email','phone','number','currency','percentage','signature','file','image','address','relation','heading','separator'];
        if(!in_array($type,$allowed,true)) throw new InvalidArgumentException('Composant invalide.');
        $label=trim((string)($input['label']??'')); if($label==='') throw new InvalidArgumentException('Le libellé est obligatoire.');
        $p=Database::connection()->prepare("SELECT COALESCE(MAX(position),0)+10 FROM axiom_studio_form_components WHERE form_id=:id");$p->execute(['id'=>$formId]);$position=(int)$p->fetchColumn();
        $s=Database::connection()->prepare("INSERT INTO axiom_studio_form_components(form_id,field_id,component_type,label,placeholder,help_text,width_desktop,width_tablet,width_mobile,is_required,visibility_rule_json,position,created_by,updated_by) VALUES(:form,:field,:type,:label,:placeholder,:help,:wd,:wt,:wm,:req,:rules,:position,:u,:u)");
        $s->execute(['form'=>$formId,'field'=>$fieldId?:null,'type'=>$type,'label'=>$label,'placeholder'=>trim((string)($input['placeholder']??''))?:null,'help'=>trim((string)($input['help_text']??''))?:null,'wd'=>$this->width($input['width_desktop']??12),'wt'=>$this->width($input['width_tablet']??12),'wm'=>$this->width($input['width_mobile']??12),'req'=>!empty($input['is_required'])?1:0,'rules'=>json_encode(['field'=>trim((string)($input['condition_field']??'')),'operator'=>trim((string)($input['condition_operator']??'')),'value'=>trim((string)($input['condition_value']??''))],JSON_UNESCAPED_UNICODE),'position'=>$position,'u'=>$userId]);
        return (int)Database::connection()->lastInsertId();
    }
    public function saveOrder(int $formId,array $ids,?int $userId): void { $s=Database::connection()->prepare("UPDATE axiom_studio_form_components SET position=:p,updated_by=:u WHERE id=:id AND form_id=:f");$p=10;foreach($ids as $id){$s->execute(['p'=>$p,'u'=>$userId,'id'=>(int)$id,'f'=>$formId]);$p+=10;} }
    public function archiveComponent(int $id,?int $userId): void { $s=Database::connection()->prepare("UPDATE axiom_studio_form_components SET archived_at=CURRENT_TIMESTAMP,updated_by=:u WHERE id=:id");$s->execute(['u'=>$userId,'id'=>$id]); }
    public function preview(array $components): array { return ['json'=>json_encode(['version'=>'1.0','components'=>$components],JSON_PRETTY_PRINT|JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES)?:'{}','components'=>$components]; }
    private function width(mixed $v): int {$n=(int)$v;return in_array($n,[1,2,3,4,5,6,7,8,9,10,11,12],true)?$n:12;}
}
