<?php

declare(strict_types=1);

namespace App\Controllers;

require_once __DIR__ . '/../Services/LogService.php';
require_once __DIR__ . '/../Services/MigrationService.php';

use PDO;
use PDOException;
use Database;
use AppConfig;
use Request;
use Response;
use Session;
use App\Services\LogService;
use App\Services\MigrationService;
use Exception;

class MigrationController {
    private PDO $db;
    private AppConfig $appConfig;
    private MigrationService $migrationService;

    public function __construct() {
        $this->db = Database::getInstance();
        $this->appConfig = AppConfig::getInstance();
        $this->migrationService = new MigrationService();
    }

    /**
     * Teste les connexions aux bases de données source et cible
     *
     * GET /api/migrations/test-connections
     *
     * @return void
     */
    public function testConnections(): void {
        try {
            $result = $this->migrationService->testConnections();

            Response::json([
                'status' => 'success',
                'connections' => $result
            ]);
        } catch (Exception $e) {
            LogService::log('Erreur lors du test des connexions', [
                'level' => 'error',
                'error' => $e->getMessage()
            ]);

            Response::json([
                'status' => 'error',
                'message' => $e->getMessage()
            ], 500);
        }
    }

    /**
     * Liste les entités disponibles à migrer depuis la base source
     *
     * GET /api/migrations/entities/available
     *
     * @return void
     */
    public function getAvailableEntities(): void {
        try {
            $entities = $this->migrationService->getAvailableEntities();

            Response::json([
                'status' => 'success',
                'count' => count($entities),
                'entities' => $entities
            ]);
        } catch (Exception $e) {
            LogService::log('Erreur lors de la récupération des entités disponibles', [
                'level' => 'error',
                'error' => $e->getMessage()
            ]);

            Response::json([
                'status' => 'error',
                'message' => $e->getMessage()
            ], 500);
        }
    }

    /**
     * Récupère les détails d'une entité source
     *
     * GET /api/migrations/entities/:id
     *
     * @param int $id ID de l'entité dans la base source
     * @return void
     */
    public function getEntityDetails(int $id): void {
        try {
            $entity = $this->migrationService->getEntityDetails($id);

            if (!$entity) {
                Response::json([
                    'status' => 'error',
                    'message' => 'Entité non trouvée'
                ], 404);
                return;
            }

            Response::json([
                'status' => 'success',
                'entity' => $entity
            ]);
        } catch (Exception $e) {
            LogService::log('Erreur lors de la récupération des détails de l\'entité', [
                'level' => 'error',
                'error' => $e->getMessage(),
                'entity_id' => $id
            ]);

            Response::json([
                'status' => 'error',
                'message' => $e->getMessage()
            ], 500);
        }
    }

    /**
     * Migre une entité complète ou par étapes
     *
     * POST /api/migrations/entity
     * Body: {
     *   "entity_id": 45,
     *   "steps": ["users", "operations"],  // Optionnel
     *   "dry_run": false,                   // Optionnel
     *   "truncate": false                   // Optionnel
     * }
     *
     * @return void
     */
    public function migrateEntity(): void {
        try {
            $data = Request::getJsonBody();

            // Validation
            if (!isset($data['entity_id'])) {
                Response::json([
                    'status' => 'error',
                    'message' => 'Le champ entity_id est requis'
                ], 400);
                return;
            }

            $entityId = (int) $data['entity_id'];
            $steps = $data['steps'] ?? null;
            $dryRun = $data['dry_run'] ?? false;
            $truncate = $data['truncate'] ?? false;

            // Vérifier les permissions (admin uniquement)
            $userRole = Session::get('fk_role');
            if ($userRole != 3) { // 3 = admin
                Response::json([
                    'status' => 'error',
                    'message' => 'Accès refusé. Cette action nécessite les droits administrateur.'
                ], 403);
                return;
            }

            LogService::log('Début de migration d\'entité', [
                'level' => 'info',
                'entity_id' => $entityId,
                'steps' => $steps,
                'dry_run' => $dryRun,
                'truncate' => $truncate,
                'user_id' => Session::get('user_id')
            ]);

            // Exécuter la migration
            $result = $this->migrationService->migrateEntity(
                $entityId,
                $steps,
                $dryRun,
                $truncate
            );

            Response::json([
                'status' => 'success',
                'entity_id' => $entityId,
                'entity_name' => $result['entity_name'],
                'migration_id' => $result['migration_id'],
                'steps_completed' => $result['steps_completed'],
                'total_duration_ms' => $result['total_duration_ms'],
                'summary' => $result['summary']
            ]);
        } catch (Exception $e) {
            LogService::log('Erreur lors de la migration d\'entité', [
                'level' => 'error',
                'error' => $e->getMessage(),
                'entity_id' => $data['entity_id'] ?? null
            ]);

            Response::json([
                'status' => 'error',
                'message' => $e->getMessage()
            ], 500);
        }
    }

    /**
     * Migre une étape spécifique pour une entité
     *
     * POST /api/migrations/entity/step
     * Body: {
     *   "entity_id": 45,
     *   "step": "users",
     *   "dry_run": false,
     *   "options": {}
     * }
     *
     * @return void
     */
    public function migrateEntityStep(): void {
        try {
            $data = Request::getJsonBody();

            // Validation
            if (!isset($data['entity_id']) || !isset($data['step'])) {
                Response::json([
                    'status' => 'error',
                    'message' => 'Les champs entity_id et step sont requis'
                ], 400);
                return;
            }

            $entityId = (int) $data['entity_id'];
            $step = $data['step'];
            $dryRun = $data['dry_run'] ?? false;
            $options = $data['options'] ?? [];

            // Vérifier les permissions (admin uniquement)
            $userRole = Session::get('fk_role');
            if ($userRole != 3) {
                Response::json([
                    'status' => 'error',
                    'message' => 'Accès refusé. Cette action nécessite les droits administrateur.'
                ], 403);
                return;
            }

            LogService::log('Début de migration d\'étape', [
                'level' => 'info',
                'entity_id' => $entityId,
                'step' => $step,
                'dry_run' => $dryRun,
                'options' => $options,
                'user_id' => Session::get('user_id')
            ]);

            // Exécuter l'étape de migration
            $result = $this->migrationService->migrateStep(
                $entityId,
                $step,
                $dryRun,
                $options
            );

            Response::json([
                'status' => 'success',
                'entity_id' => $entityId,
                'step' => $step,
                'records_migrated' => $result['records_migrated'],
                'duration_ms' => $result['duration_ms'],
                'warnings' => $result['warnings'] ?? [],
                'details' => $result['details'] ?? []
            ]);
        } catch (Exception $e) {
            LogService::log('Erreur lors de la migration d\'étape', [
                'level' => 'error',
                'error' => $e->getMessage(),
                'entity_id' => $data['entity_id'] ?? null,
                'step' => $data['step'] ?? null
            ]);

            Response::json([
                'status' => 'error',
                'message' => $e->getMessage()
            ], 500);
        }
    }

    /**
     * Récupère le statut de migration d'une entité
     *
     * GET /api/migrations/entity/:id/status
     *
     * @param int $id ID de l'entité
     * @return void
     */
    public function getMigrationStatus(int $id): void {
        try {
            $status = $this->migrationService->getMigrationStatus($id);

            Response::json([
                'status' => 'success',
                'entity_id' => $id,
                'migration_status' => $status
            ]);
        } catch (Exception $e) {
            LogService::log('Erreur lors de la récupération du statut de migration', [
                'level' => 'error',
                'error' => $e->getMessage(),
                'entity_id' => $id
            ]);

            Response::json([
                'status' => 'error',
                'message' => $e->getMessage()
            ], 500);
        }
    }

    /**
     * Récupère les logs de migration d'une entité
     *
     * GET /api/migrations/entity/:id/logs
     *
     * @param int $id ID de l'entité
     * @return void
     */
    public function getMigrationLogs(int $id): void {
        try {
            $logs = $this->migrationService->getMigrationLogs($id);

            Response::json([
                'status' => 'success',
                'entity_id' => $id,
                'logs' => $logs
            ]);
        } catch (Exception $e) {
            LogService::log('Erreur lors de la récupération des logs de migration', [
                'level' => 'error',
                'error' => $e->getMessage(),
                'entity_id' => $id
            ]);

            Response::json([
                'status' => 'error',
                'message' => $e->getMessage()
            ], 500);
        }
    }

    /**
     * Génère un rapport de migration pour une entité
     *
     * GET /api/migrations/entity/:id/report
     *
     * @param int $id ID de l'entité
     * @return void
     */
    public function getMigrationReport(int $id): void {
        try {
            $report = $this->migrationService->generateMigrationReport($id);

            Response::json([
                'status' => 'success',
                'entity_id' => $id,
                'report' => $report
            ]);
        } catch (Exception $e) {
            LogService::log('Erreur lors de la génération du rapport de migration', [
                'level' => 'error',
                'error' => $e->getMessage(),
                'entity_id' => $id
            ]);

            Response::json([
                'status' => 'error',
                'message' => $e->getMessage()
            ], 500);
        }
    }

    /**
     * Compare les données source vs cible pour une entité
     *
     * GET /api/migrations/entity/:id/compare
     *
     * @param int $id ID de l'entité
     * @return void
     */
    public function compareEntityData(int $id): void {
        try {
            $comparison = $this->migrationService->compareEntityData($id);

            Response::json([
                'status' => 'success',
                'entity_id' => $id,
                'comparison' => $comparison
            ]);
        } catch (Exception $e) {
            LogService::log('Erreur lors de la comparaison des données', [
                'level' => 'error',
                'error' => $e->getMessage(),
                'entity_id' => $id
            ]);

            Response::json([
                'status' => 'error',
                'message' => $e->getMessage()
            ], 500);
        }
    }

    /**
     * Vérifie l'intégrité des données migrées pour une entité
     *
     * GET /api/migrations/entity/:id/verify
     *
     * @param int $id ID de l'entité
     * @return void
     */
    public function verifyMigration(int $id): void {
        try {
            $verification = $this->migrationService->verifyMigration($id);

            Response::json([
                'status' => 'success',
                'entity_id' => $id,
                'verification' => $verification
            ]);
        } catch (Exception $e) {
            LogService::log('Erreur lors de la vérification de la migration', [
                'level' => 'error',
                'error' => $e->getMessage(),
                'entity_id' => $id
            ]);

            Response::json([
                'status' => 'error',
                'message' => $e->getMessage()
            ], 500);
        }
    }

    /**
     * Annule la migration d'une entité (rollback)
     *
     * DELETE /api/migrations/entity/:id
     *
     * @param int $id ID de l'entité
     * @return void
     */
    public function rollbackEntity(int $id): void {
        try {
            // Vérifier les permissions (admin uniquement)
            $userRole = Session::get('fk_role');
            if ($userRole != 3) {
                Response::json([
                    'status' => 'error',
                    'message' => 'Accès refusé. Cette action nécessite les droits administrateur.'
                ], 403);
                return;
            }

            LogService::log('Début de rollback d\'entité', [
                'level' => 'warning',
                'entity_id' => $id,
                'user_id' => Session::get('user_id')
            ]);

            $result = $this->migrationService->rollbackEntity($id);

            Response::json([
                'status' => 'success',
                'entity_id' => $id,
                'message' => 'Migration annulée avec succès',
                'deleted_records' => $result['deleted_records']
            ]);
        } catch (Exception $e) {
            LogService::log('Erreur lors du rollback de la migration', [
                'level' => 'error',
                'error' => $e->getMessage(),
                'entity_id' => $id
            ]);

            Response::json([
                'status' => 'error',
                'message' => $e->getMessage()
            ], 500);
        }
    }

    /**
     * Supprime une étape spécifique de la migration
     *
     * DELETE /api/migrations/entity/:id/step/:step
     *
     * @param int $id ID de l'entité
     * @param string $step Nom de l'étape
     * @return void
     */
    public function rollbackStep(int $id, string $step): void {
        try {
            // Vérifier les permissions (admin uniquement)
            $userRole = Session::get('fk_role');
            if ($userRole != 3) {
                Response::json([
                    'status' => 'error',
                    'message' => 'Accès refusé. Cette action nécessite les droits administrateur.'
                ], 403);
                return;
            }

            LogService::log('Début de rollback d\'étape', [
                'level' => 'warning',
                'entity_id' => $id,
                'step' => $step,
                'user_id' => Session::get('user_id')
            ]);

            $result = $this->migrationService->rollbackStep($id, $step);

            Response::json([
                'status' => 'success',
                'entity_id' => $id,
                'step' => $step,
                'message' => 'Étape annulée avec succès',
                'deleted_records' => $result['deleted_records']
            ]);
        } catch (Exception $e) {
            LogService::log('Erreur lors du rollback de l\'étape', [
                'level' => 'error',
                'error' => $e->getMessage(),
                'entity_id' => $id,
                'step' => $step
            ]);

            Response::json([
                'status' => 'error',
                'message' => $e->getMessage()
            ], 500);
        }
    }
}
