<?php
declare(strict_types=1);
namespace App\Identity;
use App\Core\Database;
use PDO;
final class IdentityRepository
{
    private PDO $pdo;
    public function __construct(){ $this->pdo = Database::connection(); }
    public function stats(): array {
        $r=['total'=>0,'personnes'=>0,'organisations'=>0,'roles'=>0];
        $r['total']=(int)$this->pdo->query("SELECT COUNT(*) FROM axiom_identities WHERE archived_at IS NULL")->fetchColumn();
        $r['personnes']=(int)$this->pdo->query("SELECT COUNT(*) FROM axiom_identities WHERE type_identite='personne' AND archived_at IS NULL")->fetchColumn();
        $r['organisations']=(int)$this->pdo->query("SELECT COUNT(*) FROM axiom_identities WHERE type_identite='organisation' AND archived_at IS NULL")->fetchColumn();
        $r['roles']=(int)$this->pdo->query("SELECT COUNT(*) FROM axiom_identity_roles WHERE actif=1")->fetchColumn();
        return $r;
    }
    public function search(string $q='', string $type=''): array {
        $sql="SELECT i.*, GROUP_CONCAT(DISTINCT r.role_label ORDER BY r.role_label SEPARATOR ', ') roles FROM axiom_identities i LEFT JOIN axiom_identity_roles r ON r.identity_id=i.id AND r.actif=1 WHERE i.archived_at IS NULL";
        $p=[];
        if($q!==''){ $sql.=" AND (i.nom LIKE :q OR i.prenom LIKE :q OR i.raison_sociale LIKE :q OR i.identifiant_externe LIKE :q)"; $p['q']='%'.$q.'%'; }
        if(in_array($type,['personne','organisation'],true)){ $sql.=" AND i.type_identite=:type"; $p['type']=$type; }
        $sql.=" GROUP BY i.id ORDER BY COALESCE(i.raison_sociale,i.nom), i.prenom LIMIT 250";
        $s=$this->pdo->prepare($sql);$s->execute($p);return $s->fetchAll();
    }
    public function find(int $id): ?array {
        $s=$this->pdo->prepare('SELECT * FROM axiom_identities WHERE id=:id');$s->execute(['id'=>$id]);$i=$s->fetch();if(!$i)return null;
        foreach(['contacts'=>'axiom_identity_contacts','addresses'=>'axiom_identity_addresses','roles'=>'axiom_identity_roles'] as $k=>$t){$q=$this->pdo->prepare("SELECT * FROM $t WHERE identity_id=:id ORDER BY id");$q->execute(['id'=>$id]);$i[$k]=$q->fetchAll();}
        $q=$this->pdo->prepare('SELECT r.*, t.nom target_nom, t.prenom target_prenom, t.raison_sociale target_raison_sociale FROM axiom_identity_relations r JOIN axiom_identities t ON t.id=r.target_identity_id WHERE r.source_identity_id=:id AND r.actif=1 ORDER BY r.id DESC');$q->execute(['id'=>$id]);$i['relations']=$q->fetchAll();
        return $i;
    }
    public function create(array $d, int $userId): int {
        $this->pdo->beginTransaction();
        try{
            $s=$this->pdo->prepare('INSERT INTO axiom_identities (organisation_id,type_identite,civilite,nom,prenom,raison_sociale,date_naissance,identifiant_externe,notes) VALUES (:organisation_id,:type_identite,:civilite,:nom,:prenom,:raison_sociale,:date_naissance,:identifiant_externe,:notes)');
            $s->execute($d);$id=(int)$this->pdo->lastInsertId();
            foreach(($d['roles']??[]) as $code){$label=ucfirst(str_replace('_',' ',$code));$r=$this->pdo->prepare('INSERT IGNORE INTO axiom_identity_roles(identity_id,role_code,role_label) VALUES(:id,:code,:label)');$r->execute(['id'=>$id,'code'=>$code,'label'=>$label]);}
            foreach(['email','telephone'] as $type){if(!empty($d[$type])){$c=$this->pdo->prepare('INSERT INTO axiom_identity_contacts(identity_id,type_contact,valeur,principal) VALUES(:id,:type,:valeur,1)');$c->execute(['id'=>$id,'type'=>$type,'valeur'=>$d[$type]]);}}
            if(!empty($d['ligne1'])){$a=$this->pdo->prepare('INSERT INTO axiom_identity_addresses(identity_id,ligne1,ligne2,code_postal,ville,pays) VALUES(:id,:ligne1,:ligne2,:cp,:ville,:pays)');$a->execute(['id'=>$id,'ligne1'=>$d['ligne1'],'ligne2'=>$d['ligne2'],'cp'=>$d['code_postal'],'ville'=>$d['ville'],'pays'=>$d['pays']]);}
            $h=$this->pdo->prepare('INSERT INTO axiom_identity_history(identity_id,action_code,details_json,user_id) VALUES(:id,"creation",:details,:user)');$h->execute(['id'=>$id,'details'=>json_encode(['source'=>'identity_engine'],JSON_UNESCAPED_UNICODE),'user'=>$userId?:null]);
            $this->pdo->commit();return $id;
        }catch(\Throwable $e){$this->pdo->rollBack();throw $e;}
    }
    public function archive(int $id,int $userId):void{$s=$this->pdo->prepare("UPDATE axiom_identities SET statut='archive', archived_at=NOW() WHERE id=:id");$s->execute(['id'=>$id]);$h=$this->pdo->prepare('INSERT INTO axiom_identity_history(identity_id,action_code,user_id) VALUES(:id,"archivage",:user)');$h->execute(['id'=>$id,'user'=>$userId?:null]);}
}
