import axios from 'axios';
import { API_CONFIG } from '../config/api';
import { 
    PhaseChantier, 
    PhaseChantierFormData, 
    PhaseFilters,
    JalonPhase,
    PointagePhase,
    StatutPhase,
    ApiResponse 
} from '../types/btp-extended';

class PhaseChantierService {
    private readonly basePath = '/phases-chantier';
    private api = axios.create({
        baseURL: API_CONFIG.baseURL,
        timeout: API_CONFIG.timeout,
        headers: API_CONFIG.headers,
    });

    constructor() {
        // Interceptor pour ajouter le token Keycloak
        this.api.interceptors.request.use(
            async (config) => {
                // Vérifier si Keycloak est initialisé et l'utilisateur authentifié
                if (typeof window !== 'undefined') {
                    const { keycloak, KEYCLOAK_TIMEOUTS } = await import('../config/keycloak');

                    if (keycloak.authenticated) {
                        try {
                            // Rafraîchir le token si nécessaire
                            await keycloak.updateToken(KEYCLOAK_TIMEOUTS.TOKEN_REFRESH_BEFORE_EXPIRY);

                            // Ajouter le token Bearer à l'en-tête Authorization
                            if (keycloak.token) {
                                config.headers['Authorization'] = `Bearer ${keycloak.token}`;
                            }
                        } catch (error) {
                            console.error('Erreur lors de la mise à jour du token Keycloak:', error);
                            keycloak.login();
                            throw error;
                        }
                    } else {
                        // Fallback vers l'ancien système pour la rétrocompatibilité
                        let token = null;
                        try {
                            const authTokenItem = sessionStorage.getItem('auth_token') || localStorage.getItem('auth_token');
                            if (authTokenItem) {
                                const parsed = JSON.parse(authTokenItem);
                                token = parsed.value;
                            }
                        } catch (e) {
                            token = localStorage.getItem('token');
                        }

                        if (token) {
                            config.headers['Authorization'] = `Bearer ${token}`;
                        }
                    }
                }
                return config;
            },
            (error) => Promise.reject(error)
        );

        // Interceptor pour les réponses
        this.api.interceptors.response.use(
            (response) => response,
            (error) => {
                if (error.response?.status === 401) {
                    localStorage.removeItem('token');
                    localStorage.removeItem('user');
                    window.location.href = '/api/auth/login';
                }
                return Promise.reject(error);
            }
        );
    }

    /**
     * Récupérer les phases d'un chantier
     */
    async getByChantier(chantierId: number): Promise<PhaseChantier[]> {
        const response = await this.api.get(`${this.basePath}/chantier/${chantierId}`);
        return response.data;
    }

    /**
     * Récupérer une phase par ID
     */
    async getById(id: number): Promise<PhaseChantier> {
        const response = await this.api.get(`${this.basePath}/${id}`);
        return response.data;
    }

    /**
     * Créer une nouvelle phase
     */
    async create(phase: PhaseChantierFormData): Promise<PhaseChantier> {
        const response = await this.api.post(this.basePath, phase);
        return response.data;
    }

    /**
     * Modifier une phase existante
     */
    async update(id: number, phase: PhaseChantierFormData): Promise<PhaseChantier> {
        const response = await this.api.put(`${this.basePath}/${id}`, phase);
        return response.data;
    }

    /**
     * Supprimer une phase
     */
    async delete(id: number): Promise<void> {
        await this.api.delete(`${this.basePath}/${id}`);
    }

    /**
     * Démarrer une phase
     */
    async start(id: number): Promise<void> {
        await this.api.post(`${this.basePath}/${id}/demarrer`);
    }

    /**
     * Terminer une phase
     */
    async complete(id: number): Promise<void> {
        await this.api.post(`${this.basePath}/${id}/terminer`);
    }

    /**
     * Suspendre une phase
     */
    async suspend(id: number): Promise<void> {
        await this.api.post(`${this.basePath}/${id}/suspendre`);
    }

    /**
     * Reprendre une phase suspendue
     */
    async resume(id: number): Promise<void> {
        await this.api.post(`${this.basePath}/${id}/reprendre`);
    }

    /**
     * Mettre à jour l'avancement d'une phase
     */
    async updateProgress(id: number, pourcentage: number): Promise<void> {
        await this.api.put(`${this.basePath}/${id}/avancement?pourcentage=${pourcentage}`);
    }

    /**
     * Récupérer les statuts disponibles
     */
    async getStatuts(): Promise<StatutPhase[]> {
        const response = await this.api.get(`${this.basePath}/statuts`);
        return response.data;
    }

    /**
     * Récupérer les phases en retard
     */
    async getEnRetard(): Promise<PhaseChantier[]> {
        const response = await this.api.get(`${this.basePath}/en-retard`);
        return response.data;
    }

    /**
     * Récupérer les phases d'un responsable
     */
    async getByResponsable(employeId: number): Promise<PhaseChantier[]> {
        const response = await this.api.get(`${this.basePath}/responsable/${employeId}`);
        return response.data;
    }

    /**
     * Récupérer les jalons d'une phase
     */
    async getJalons(phaseId: number): Promise<JalonPhase[]> {
        const response = await this.api.get(`${this.basePath}/${phaseId}/jalons`);
        return response.data;
    }

    /**
     * Récupérer les pointages d'une phase
     */
    async getPointages(phaseId: number): Promise<PointagePhase[]> {
        const response = await this.api.get(`${this.basePath}/${phaseId}/pointages`);
        return response.data;
    }

    /**
     * Valider les données d'une phase
     */
    validatePhase(phase: PhaseChantierFormData): string[] {
        const errors: string[] = [];

        if (!phase.nom || phase.nom.trim().length === 0) {
            errors.push('Le nom de la phase est obligatoire');
        }

        if (phase.nom && phase.nom.length > 100) {
            errors.push('Le nom ne peut pas dépasser 100 caractères');
        }

        if (!phase.dateDebutPrevue) {
            errors.push('La date de début prévue est obligatoire');
        }

        if (!phase.dateFinPrevue) {
            errors.push('La date de fin prévue est obligatoire');
        }

        if (phase.dateDebutPrevue && phase.dateFinPrevue) {
            const debut = new Date(phase.dateDebutPrevue);
            const fin = new Date(phase.dateFinPrevue);
            if (debut >= fin) {
                errors.push('La date de fin doit être postérieure à la date de début');
            }
        }

        if (phase.budgetPrevu !== undefined && phase.budgetPrevu < 0) {
            errors.push('Le budget prévu doit être positif');
        }

        return errors;
    }

    /**
     * Calculer la durée prévue d'une phase en jours
     */
    calculateDureePrevue(phase: PhaseChantier): number {
        if (!phase.dateDebutPrevue || !phase.dateFinPrevue) return 0;
        
        const debut = new Date(phase.dateDebutPrevue);
        const fin = new Date(phase.dateFinPrevue);
        const diffTime = Math.abs(fin.getTime() - debut.getTime());
        return Math.ceil(diffTime / (1000 * 60 * 60 * 24));
    }

    /**
     * Calculer la durée réelle d'une phase en jours
     */
    calculateDureeReelle(phase: PhaseChantier): number {
        if (!phase.dateDebutReelle) return 0;
        
        const debut = new Date(phase.dateDebutReelle);
        const fin = phase.dateFinReelle ? new Date(phase.dateFinReelle) : new Date();
        const diffTime = Math.abs(fin.getTime() - debut.getTime());
        return Math.ceil(diffTime / (1000 * 60 * 60 * 24));
    }

    /**
     * Vérifier si une phase est en retard
     */
    isEnRetard(phase: PhaseChantier): boolean {
        if (phase.statut === 'TERMINEE') return false;
        if (!phase.dateFinPrevue) return false;
        
        return new Date() > new Date(phase.dateFinPrevue);
    }

    /**
     * Calculer le retard en jours
     */
    calculateRetard(phase: PhaseChantier): number {
        if (!this.isEnRetard(phase)) return 0;
        
        const dateFinPrevue = new Date(phase.dateFinPrevue!);
        const maintenant = new Date();
        const diffTime = maintenant.getTime() - dateFinPrevue.getTime();
        return Math.ceil(diffTime / (1000 * 60 * 60 * 24));
    }

    /**
     * Obtenir le libellé d'un statut
     */
    getStatutLabel(statut: StatutPhase): string {
        const labels: Record<StatutPhase, string> = {
            PLANIFIEE: 'Planifiée',
            EN_ATTENTE: 'En attente',
            EN_COURS: 'En cours',
            EN_PAUSE: 'En pause',
            TERMINEE: 'Terminée',
            ANNULEE: 'Annulée',
            EN_RETARD: 'En retard'
        };
        return labels[statut] || statut;
    }

    /**
     * Obtenir la couleur d'un statut
     */
    getStatutColor(statut: StatutPhase): string {
        const colors: Record<StatutPhase, string> = {
            PLANIFIEE: '#6c757d',
            EN_ATTENTE: '#ffc107',
            EN_COURS: '#0d6efd',
            EN_PAUSE: '#fd7e14',
            TERMINEE: '#198754',
            ANNULEE: '#dc3545',
            EN_RETARD: '#dc3545'
        };
        return colors[statut] || '#6c757d';
    }

    /**
     * Calculer les statistiques des phases d'un chantier
     */
    calculateStatistiques(phases: PhaseChantier[]): {
        total: number;
        planifiees: number;
        enCours: number;
        terminees: number;
        enRetard: number;
        avancementMoyen: number;
        budgetTotal: number;
        coutTotal: number;
    } {
        const stats = {
            total: phases.length,
            planifiees: 0,
            enCours: 0,
            terminees: 0,
            enRetard: 0,
            avancementMoyen: 0,
            budgetTotal: 0,
            coutTotal: 0
        };

        let avancementTotal = 0;

        phases.forEach(phase => {
            // Compter par statut
            switch (phase.statut) {
                case 'PLANIFIEE':
                case 'EN_ATTENTE':
                    stats.planifiees++;
                    break;
                case 'EN_COURS':
                case 'EN_PAUSE':
                    stats.enCours++;
                    break;
                case 'TERMINEE':
                    stats.terminees++;
                    break;
                case 'EN_RETARD':
                    stats.enRetard++;
                    break;
            }

            // Calculer avancement moyen
            avancementTotal += phase.pourcentageAvancement || 0;

            // Calculer budget et coût
            stats.budgetTotal += phase.budgetPrevu || 0;
            stats.coutTotal += phase.coutReel || 0;
        });

        stats.avancementMoyen = phases.length > 0 ? avancementTotal / phases.length : 0;

        return stats;
    }

    /**
     * Générer un planning Gantt simple
     */
    generateGanttData(phases: PhaseChantier[]): any[] {
        return phases.map(phase => ({
            id: phase.id,
            name: phase.nom,
            start: phase.dateDebutPrevue,
            end: phase.dateFinPrevue,
            progress: (phase.pourcentageAvancement || 0) / 100,
            status: phase.statut,
            parent: phase.phaseParent,
            dependencies: [], // TODO: Implémenter les dépendances
            color: this.getStatutColor(phase.statut)
        }));
    }

    /**
     * Exporter les phases au format CSV
     */
    async exportToCsv(chantierId: number): Promise<Blob> {
        const phases = await this.getByChantier(chantierId);
        
        const headers = [
            'ID', 'Nom', 'Statut', 'Date Début Prévue', 'Date Fin Prévue',
            'Date Début Réelle', 'Date Fin Réelle', 'Avancement (%)', 
            'Budget Prévu', 'Coût Réel', 'Responsable', 'Critique'
        ];

        const csvContent = [
            headers.join(';'),
            ...phases.map(p => [
                p.id || '',
                p.nom || '',
                this.getStatutLabel(p.statut),
                p.dateDebutPrevue ? new Date(p.dateDebutPrevue).toLocaleDateString('fr-FR') : '',
                p.dateFinPrevue ? new Date(p.dateFinPrevue).toLocaleDateString('fr-FR') : '',
                p.dateDebutReelle ? new Date(p.dateDebutReelle).toLocaleDateString('fr-FR') : '',
                p.dateFinReelle ? new Date(p.dateFinReelle).toLocaleDateString('fr-FR') : '',
                p.pourcentageAvancement || 0,
                p.budgetPrevu || 0,
                p.coutReel || 0,
                p.responsable ? `${p.responsable.nom} ${p.responsable.prenom}` : '',
                p.critique ? 'Oui' : 'Non'
            ].join(';'))
        ].join('\n');

        return new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
    }
}

export default new PhaseChantierService();