<?php

/**
 * Migration des opérations complètes
 *
 * Orchestre la migration d'une opération avec tous ses utilisateurs,
 * secteurs, passages et médias. Utilise UserMigrator et SectorMigrator.
 */
class OperationMigrator
{
    private PDO $sourceDb;
    private PDO $targetDb;
    private MigrationLogger $logger;
    private UserMigrator $userMigrator;
    private SectorMigrator $sectorMigrator;

    /**
     * Constructeur
     *
     * @param PDO $sourceDb Connexion source
     * @param PDO $targetDb Connexion cible
     * @param MigrationLogger $logger Logger
     * @param UserMigrator $userMigrator Migrator d'utilisateurs
     * @param SectorMigrator $sectorMigrator Migrator de secteurs
     */
    public function __construct(
        PDO $sourceDb,
        PDO $targetDb,
        MigrationLogger $logger,
        UserMigrator $userMigrator,
        SectorMigrator $sectorMigrator
    ) {
        $this->sourceDb = $sourceDb;
        $this->targetDb = $targetDb;
        $this->logger = $logger;
        $this->userMigrator = $userMigrator;
        $this->sectorMigrator = $sectorMigrator;
    }

    /**
     * Récupère les opérations à migrer pour une entité
     * - 1 opération active
     * - 2 dernières opérations inactives avec au moins 10 passages effectués
     *
     * @param int $entityId ID de l'entité
     * @return array Liste des IDs d'opérations à migrer
     */
    public function getOperationsToMigrate(int $entityId): array
    {
        $operationIds = [];

        // 1. Récupérer l'opération active (pour vérification)
        $stmt = $this->sourceDb->prepare("
            SELECT rowid
            FROM operations
            WHERE fk_entite = :entity_id AND active = 1
            LIMIT 1
        ");
        $stmt->execute([':entity_id' => $entityId]);
        $activeOp = $stmt->fetch(PDO::FETCH_COLUMN);

        // 2. Récupérer les 2 dernières opérations inactives avec >= 10 passages effectués
        // ORDER BY DESC pour avoir les plus récentes, puis on inverse
        $stmt = $this->sourceDb->prepare("
            SELECT o.rowid, COUNT(p.rowid) as nb_passages
            FROM operations o
            LEFT JOIN ope_pass p ON p.fk_operation = o.rowid AND p.fk_type = 1
            WHERE o.fk_entite = :entity_id
            AND o.active = 0
            " . ($activeOp ? "AND o.rowid != :active_id" : "") . "
            GROUP BY o.rowid
            HAVING nb_passages >= 10
            ORDER BY o.rowid DESC
            LIMIT 2
        ");

        $params = [':entity_id' => $entityId];
        if ($activeOp) {
            $params[':active_id'] = $activeOp;
        }

        $stmt->execute($params);
        $inactiveOps = $stmt->fetchAll(PDO::FETCH_ASSOC);

        // Inverser pour avoir l'ordre chronologique (plus ancienne → plus récente)
        $inactiveOps = array_reverse($inactiveOps);

        foreach ($inactiveOps as $op) {
            $operationIds[] = $op['rowid'];
            $this->logger->info("✓ Opération inactive trouvée: {$op['rowid']} ({$op['nb_passages']} passages)");
        }

        // 3. Ajouter l'opération active EN DERNIER
        if ($activeOp) {
            $operationIds[] = $activeOp;
            $this->logger->info("✓ Opération active trouvée: {$activeOp}");
        }

        $this->logger->info("📊 Total: " . count($operationIds) . " opération(s) à migrer");

        return $operationIds;
    }

    /**
     * Migre une opération complète avec tous ses utilisateurs et secteurs
     *
     * @param int $oldOperationId ID de l'opération dans l'ancienne base
     * @return array|null Tableau de statistiques ou null en cas d'erreur
     */
    public function migrateOperation(int $oldOperationId): ?array
    {
        $this->logger->separator();
        $this->logger->info("🔄 Migration de l'opération ID: {$oldOperationId}");

        try {
            // 1. Récupérer l'opération source
            $stmt = $this->sourceDb->prepare("
                SELECT * FROM operations
                WHERE rowid = :id
            ");
            $stmt->execute([':id' => $oldOperationId]);
            $operation = $stmt->fetch(PDO::FETCH_ASSOC);

            if (!$operation) {
                $this->logger->warning("Opération {$oldOperationId} non trouvée");
                return null;
            }

            // 2. Créer l'opération dans la nouvelle base
            $newOperationId = $this->createOperation($operation);

            if (!$newOperationId) {
                return null;
            }

            $this->logger->success("✓ Opération créée avec ID: {$newOperationId}");

            // 3. Migrer les utilisateurs de l'opération
            // Pour opération active : tous les users actifs de l'entité
            // Pour opération inactive : uniquement ceux dans ope_users_sectors
            $entityId = (int)$operation['fk_entite'];
            $isActiveOperation = (int)$operation['active'] === 1;

            $userResult = $this->userMigrator->migrateOperationUsers(
                $oldOperationId,
                $newOperationId,
                $entityId,
                $isActiveOperation
            );
            $userMapping = $userResult['mapping'];
            $usersCount = $userResult['count'];

            if (empty($userMapping)) {
                $this->logger->warning("Aucun utilisateur migré, abandon de l'opération {$oldOperationId}");
                return null;
            }

            // 4. Récupérer les secteurs DISTINCTS de l'opération
            $stmt = $this->sourceDb->prepare("
                SELECT DISTINCT fk_sector
                FROM ope_users_sectors
                WHERE fk_operation = :operation_id AND active = 1
            ");
            $stmt->execute([':operation_id' => $oldOperationId]);
            $sectors = $stmt->fetchAll(PDO::FETCH_COLUMN);

            $this->logger->info("📍 " . count($sectors) . " secteur(s) distinct(s) à migrer");

            // 5. Migrer chaque secteur et collecter les stats
            $sectorsDetail = [];
            $totalPassages = 0;

            foreach ($sectors as $oldSectorId) {
                $sectorStats = $this->sectorMigrator->migrateSector(
                    $oldOperationId,
                    $newOperationId,
                    $oldSectorId,
                    $userMapping
                );

                if ($sectorStats) {
                    $sectorsDetail[] = $sectorStats;
                    $totalPassages += $sectorStats['passages'];
                }
            }

            // 6. Migrer les médias de l'opération (support='operations')
            $this->migrateOperationMedias($oldOperationId, $newOperationId);

            $this->logger->success("✅ Migration de l'opération {$oldOperationId} terminée");

            // 7. Retourner les statistiques
            return [
                'id' => $newOperationId,
                'name' => $operation['libelle'],
                'users' => $usersCount,
                'sectors' => count($sectorsDetail),
                'total_passages' => $totalPassages,
                'sectors_detail' => $sectorsDetail
            ];

        } catch (Exception $e) {
            $this->logger->error("❌ Erreur migration opération {$oldOperationId}: " . $e->getMessage());
            return null;
        }
    }

    /**
     * Crée une opération dans la nouvelle base
     *
     * @param array $operation Données de l'opération
     * @return int|null ID de la nouvelle opération ou null en cas d'erreur
     */
    private function createOperation(array $operation): ?int
    {
        try {
            $stmt = $this->targetDb->prepare("
                INSERT INTO operations (
                    fk_entite, libelle, date_deb, date_fin,
                    chk_distinct_sectors,
                    created_at, fk_user_creat, updated_at, fk_user_modif, chk_active
                ) VALUES (
                    :fk_entite, :libelle, :date_deb, :date_fin,
                    :chk_distinct_sectors,
                    :created_at, :fk_user_creat, :updated_at, :fk_user_modif, :chk_active
                )
            ");

            $stmt->execute([
                ':fk_entite' => $operation['fk_entite'],
                ':libelle' => $operation['libelle'],
                ':date_deb' => $operation['date_deb'],
                ':date_fin' => $operation['date_fin'],
                ':chk_distinct_sectors' => $operation['chk_distinct_sectors'],
                ':created_at' => $operation['date_creat'],
                ':fk_user_creat' => $operation['fk_user_creat'],
                ':updated_at' => $operation['date_modif'],
                ':fk_user_modif' => $operation['fk_user_modif'] ?? 0,
                ':chk_active' => $operation['active']
            ]);

            return (int)$this->targetDb->lastInsertId();

        } catch (Exception $e) {
            $this->logger->error("❌ Erreur création opération: " . $e->getMessage());
            return null;
        }
    }

    /**
     * Migre les médias d'une opération
     *
     * @param int $oldOperationId ID ancienne opération
     * @param int $newOperationId ID nouvelle opération
     * @return int Nombre de médias migrés
     */
    private function migrateOperationMedias(int $oldOperationId, int $newOperationId): int
    {
        $stmt = $this->sourceDb->prepare("
            SELECT * FROM medias
            WHERE support = 'operations' AND support_rowid = :operation_id
        ");
        $stmt->execute([':operation_id' => $oldOperationId]);
        $medias = $stmt->fetchAll(PDO::FETCH_ASSOC);

        if (empty($medias)) {
            return 0;
        }

        $count = 0;
        foreach ($medias as $media) {
            $stmt = $this->targetDb->prepare("
                INSERT INTO medias (
                    dir0, dir1, dir2, support, support_rowid,
                    fichier, type_fichier, description, position,
                    hauteur, largeur, niveaugris,
                    created_at, fk_user_creat, updated_at, fk_user_modif
                ) VALUES (
                    :dir0, :dir1, :dir2, :support, :support_rowid,
                    :fichier, :type_fichier, :description, :position,
                    :hauteur, :largeur, :niveaugris,
                    :created_at, :fk_user_creat, :updated_at, :fk_user_modif
                )
            ");

            $stmt->execute([
                ':dir0' => $media['dir0'],
                ':dir1' => $media['dir1'],
                ':dir2' => $media['dir2'],
                ':support' => $media['support'],
                ':support_rowid' => $newOperationId,
                ':fichier' => $media['fichier'],
                ':type_fichier' => $media['type_fichier'],
                ':description' => $media['description'],
                ':position' => $media['position'],
                ':hauteur' => $media['hauteur'],
                ':largeur' => $media['largeur'],
                ':niveaugris' => $media['niveaugris'],
                ':created_at' => $media['date_creat'],
                ':fk_user_creat' => $media['fk_user_creat'],
                ':updated_at' => $media['date_modif'],
                ':fk_user_modif' => $media['fk_user_modif']
            ]);

            $count++;
        }

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

        return $count;
    }
}
