<?php

/**
 * Migration des utilisateurs d'opérations (ope_users)
 *
 * Gère la création des utilisateurs par opération et le mapping
 * oldUserId (users.rowid) → newOpeUserId (ope_users.id)
 */
class UserMigrator
{
    private PDO $sourceDb;
    private PDO $targetDb;
    private MigrationLogger $logger;
    private array $userMapping = [];

    /**
     * Constructeur
     *
     * @param PDO $sourceDb Connexion source
     * @param PDO $targetDb Connexion cible
     * @param MigrationLogger $logger Logger
     */
    public function __construct(PDO $sourceDb, PDO $targetDb, MigrationLogger $logger)
    {
        $this->sourceDb = $sourceDb;
        $this->targetDb = $targetDb;
        $this->logger = $logger;
    }

    /**
     * Migre les utilisateurs d'une opération
     * - Si opération active : TOUS les users actifs de l'entité
     * - Si opération inactive : Uniquement ceux dans ope_users_sectors
     *
     * @param int $oldOperationId ID ancienne opération
     * @param int $newOperationId ID nouvelle opération
     * @param int $entityId ID de l'entité
     * @param bool $isActiveOperation True si opération active
     * @return array ['mapping' => array, 'count' => int]
     */
    public function migrateOperationUsers(
        int $oldOperationId,
        int $newOperationId,
        int $entityId,
        bool $isActiveOperation
    ): array {
        $this->logger->info("👥 Migration des utilisateurs de l'opération...");

        // Réinitialiser le mapping pour cette opération
        $this->userMapping = [];

        // Récupérer les utilisateurs selon le type d'opération
        if ($isActiveOperation) {
            // Pour l'opération active : TOUS les users actifs de l'entité
            $this->logger->info("  ℹ Opération ACTIVE : migration de tous les users actifs de l'entité");
            $stmt = $this->sourceDb->prepare("
                SELECT rowid
                FROM users
                WHERE fk_entite = :entity_id AND active = 1
            ");
            $stmt->execute([':entity_id' => $entityId]);
            $userIds = $stmt->fetchAll(PDO::FETCH_COLUMN);
        } else {
            // Pour les opérations inactives : uniquement ceux dans ope_users_sectors
            $this->logger->info("  ℹ Opération INACTIVE : migration des users affectés aux secteurs");
            $stmt = $this->sourceDb->prepare("
                SELECT DISTINCT fk_user
                FROM ope_users_sectors
                WHERE fk_operation = :operation_id AND active = 1
            ");
            $stmt->execute([':operation_id' => $oldOperationId]);
            $userIds = $stmt->fetchAll(PDO::FETCH_COLUMN);
        }

        if (empty($userIds)) {
            $this->logger->warning("Aucun utilisateur trouvé pour l'opération {$oldOperationId}");
            return ['mapping' => [], 'count' => 0];
        }

        $count = 0;
        foreach ($userIds as $oldUserId) {
            // Récupérer les infos utilisateur depuis la table users
            $stmt = $this->sourceDb->prepare("
                SELECT * FROM users WHERE rowid = :id AND active = 1
            ");
            $stmt->execute([':id' => $oldUserId]);
            $user = $stmt->fetch(PDO::FETCH_ASSOC);

            if (!$user) {
                $this->logger->warning("  ⚠ Utilisateur {$oldUserId} non trouvé ou inactif");
                continue;
            }

            // Créer dans ope_users de la nouvelle base
            $stmt = $this->targetDb->prepare("
                INSERT INTO ope_users (
                    fk_operation, fk_user, fk_role,
                    first_name, encrypted_name, sect_name,
                    created_at, fk_user_creat, updated_at, fk_user_modif, chk_active
                ) VALUES (
                    :fk_operation, :fk_user, :fk_role,
                    :first_name, :encrypted_name, :sect_name,
                    :created_at, :fk_user_creat, :updated_at, :fk_user_modif, :chk_active
                )
            ");

            $stmt->execute([
                ':fk_operation' => $newOperationId,
                ':fk_user' => $oldUserId, // Référence vers users.id
                ':fk_role' => $user['fk_role'],
                ':first_name' => $user['prenom'],
                ':encrypted_name' => ApiService::encryptData($user['libelle']), // Chiffrer le nom avec IV aléatoire
                ':sect_name' => $user['nom_tournee'],
                ':created_at' => $user['date_creat'],
                ':fk_user_creat' => $user['fk_user_creat'],
                ':updated_at' => $user['date_modif'],
                ':fk_user_modif' => $user['fk_user_modif'],
                ':chk_active' => $user['active']
            ]);

            $newOpeUserId = (int)$this->targetDb->lastInsertId();

            // Mapper oldUserId → newOpeUserId
            $this->userMapping[$oldUserId] = $newOpeUserId;
            $count++;
        }

        $this->logger->success("  ✓ {$count} utilisateur(s) migré(s)");

        return ['mapping' => $this->userMapping, 'count' => $count];
    }

    /**
     * Retourne le mapping des utilisateurs
     *
     * @return array oldUserId => newOpeUserId
     */
    public function getUserMapping(): array
    {
        return $this->userMapping;
    }

    /**
     * Définit le mapping des utilisateurs (utile pour réutilisation)
     *
     * @param array $mapping oldUserId => newOpeUserId
     */
    public function setUserMapping(array $mapping): void
    {
        $this->userMapping = $mapping;
    }

    /**
     * Récupère le nouvel ID ope_users depuis le mapping
     *
     * @param int $oldUserId ID ancien utilisateur
     * @return int|null Nouvel ID ope_users ou null si non trouvé
     */
    public function getMappedUserId(int $oldUserId): ?int
    {
        return $this->userMapping[$oldUserId] ?? null;
    }
}
