import axios from 'axios';
import { API_CONFIG } from '../config/api';
import { 
    FournisseurPhase, 
    ApiResponse 
} from '../types/btp-extended';

class FournisseurPhaseService {
    private readonly basePath = '/fournisseurs-phases';
    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 fournisseurs d'une phase
     */
    async getByPhase(phaseId: string): Promise<FournisseurPhase[]> {
        if (!phaseId || phaseId === 'undefined' || phaseId === 'null' || phaseId === 'NaN') {
            console.warn(`ID de phase invalide: ${phaseId}`);
            return [];
        }

        try {
            const response = await this.api.get(`${this.basePath}/phase/${phaseId}`);
            return response.data;
        } catch (error) {
            console.warn(`Endpoint ${this.basePath}/phase/${phaseId} non disponible:`, error);
            return [];
        }
    }

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

    /**
     * Créer un nouveau fournisseur de phase
     */
    async create(fournisseurPhase: Omit<FournisseurPhase, 'id'>): Promise<FournisseurPhase> {
        console.log('Creating fournisseur phase with data:', fournisseurPhase);
        const response = await this.api.post(this.basePath, fournisseurPhase);
        return response.data;
    }

    /**
     * Modifier un fournisseur de phase existant
     */
    async update(id: number, fournisseurPhase: Partial<FournisseurPhase>): Promise<FournisseurPhase> {
        const response = await this.api.put(`${this.basePath}/${id}`, fournisseurPhase);
        return response.data;
    }

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

    /**
     * Obtenir les fournisseurs par type de contribution
     */
    async getByTypeContribution(phaseId: string, type: string): Promise<FournisseurPhase[]> {
        try {
            const fournisseurs = await this.getByPhase(phaseId);
            return fournisseurs.filter(f => f.typeContribution === type);
        } catch (error) {
            console.error('Erreur lors de la récupération par type:', error);
            return [];
        }
    }

    /**
     * Calculer les économies réalisées avec les négociations
     */
    async calculerEconomies(phaseId: string): Promise<number> {
        try {
            const fournisseurs = await this.getByPhase(phaseId);
            return fournisseurs.reduce((total, fournisseur) => {
                const prixCatalogue = fournisseur.prixCatalogue || 0;
                const prixNegocie = fournisseur.prixNegocie || prixCatalogue;
                return total + (prixCatalogue - prixNegocie);
            }, 0);
        } catch (error) {
            console.error('Erreur lors du calcul des économies:', error);
            return 0;
        }
    }

    /**
     * Obtenir le fournisseur principal d'une phase
     */
    async getFournisseurPrincipal(phaseId: string): Promise<FournisseurPhase | null> {
        try {
            const fournisseurs = await this.getByPhase(phaseId);
            return fournisseurs.find(f => f.priorite === 1) || null;
        } catch (error) {
            console.error('Erreur lors de la récupération du fournisseur principal:', error);
            return null;
        }
    }

    /**
     * Lancer un appel d'offres pour une phase
     */
    async lancerAppelOffres(phaseId: string, fournisseurIds: number[]): Promise<FournisseurPhase[]> {
        try {
            const response = await this.api.post(`${this.basePath}/appel-offres`, {
                phaseId,
                fournisseurIds
            });
            return response.data;
        } catch (error) {
            console.warn('Appel d\'offres non disponible:', error);
            return [];
        }
    }

    /**
     * Comparer les offres de fournisseurs
     */
    async comparerOffres(phaseId: string): Promise<FournisseurPhase[]> {
        try {
            const fournisseurs = await this.getByPhase(phaseId);
            // Tri par prix négocié croissant
            return fournisseurs.sort((a, b) => {
                const prixA = a.prixNegocie || a.prixCatalogue || Infinity;
                const prixB = b.prixNegocie || b.prixCatalogue || Infinity;
                return prixA - prixB;
            });
        } catch (error) {
            console.error('Erreur lors de la comparaison des offres:', error);
            return [];
        }
    }

    /**
     * Valider une négociation
     */
    async validerNegociation(id: number, validePar: string): Promise<FournisseurPhase> {
        const response = await this.api.post(`${this.basePath}/${id}/valider`, {
            validePar,
            dateValidation: new Date()
        });
        return response.data;
    }

    /**
     * Calculer le score d'un fournisseur (prix, délai, qualité)
     */
    calculerScoreFournisseur(fournisseur: FournisseurPhase): number {
        let score = 0;
        
        // Score prix (40% du total)
        const prixFinal = fournisseur.prixNegocie || fournisseur.prixCatalogue || 0;
        const remise = fournisseur.remise || 0;
        const scoreRemise = Math.min(remise / 100, 0.3); // Max 30% de remise
        score += scoreRemise * 40;
        
        // Score délai (30% du total)
        const delai = fournisseur.delaiLivraison || 30;
        const scoreDelai = Math.max(0, (30 - delai) / 30); // Meilleur si délai < 30 jours
        score += scoreDelai * 30;
        
        // Score priorité/historique (30% du total)
        const priorite = fournisseur.priorite || 5;
        const scorePriorite = Math.max(0, (6 - priorite) / 5); // Meilleur si priorité = 1
        score += scorePriorite * 30;
        
        return Math.round(score);
    }
}

export default new FournisseurPhaseService();