import axios from 'axios';
import { API_CONFIG } from '../config/api';
import { 
    Fournisseur, 
    FournisseurFormData, 
    FournisseurFilters, 
    CommandeFournisseur,
    CatalogueItem,
    TypeFournisseur,
    ApiResponse, 
    PaginatedResponse 
} from '../types/btp-extended';

class FournisseurService {
    private readonly basePath = '/api/v1/fournisseurs';
    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 tous les fournisseurs
     */
    async getAll(filters?: FournisseurFilters): Promise<Fournisseur[]> {
        const params = new URLSearchParams();
        
        if (filters?.actif !== undefined) {
            params.append('actifs', filters.actif.toString());
        }
        if (filters?.type) {
            params.append('type', filters.type);
        }

        const response = await this.api.get(`${this.basePath}?${params}`);
        return response.data;
    }

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

    /**
     * Créer un nouveau fournisseur
     */
    async create(fournisseur: FournisseurFormData): Promise<Fournisseur> {
        const response = await this.api.post(this.basePath, fournisseur);
        return response.data;
    }

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

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

    /**
     * Désactiver un fournisseur
     */
    async deactivate(id: number): Promise<void> {
        await this.api.post(`${this.basePath}/${id}/desactiver`);
    }

    /**
     * Activer un fournisseur
     */
    async activate(id: number): Promise<void> {
        await this.api.post(`${this.basePath}/${id}/activer`);
    }

    /**
     * Rechercher des fournisseurs
     */
    async search(terme: string): Promise<Fournisseur[]> {
        const response = await this.api.get(`${this.basePath}/recherche?q=${encodeURIComponent(terme)}`);
        return response.data;
    }

    /**
     * Récupérer les types de fournisseurs
     */
    async getTypes(): Promise<TypeFournisseur[]> {
        const response = await this.api.get(`${this.basePath}/types`);
        return response.data;
    }

    /**
     * Récupérer les commandes d'un fournisseur
     */
    async getCommandes(id: number): Promise<CommandeFournisseur[]> {
        const response = await this.api.get(`${this.basePath}/${id}/commandes`);
        return response.data;
    }

    /**
     * Récupérer le catalogue d'un fournisseur
     */
    async getCatalogue(id: number): Promise<CatalogueItem[]> {
        const response = await this.api.get(`${this.basePath}/${id}/catalogue`);
        return response.data;
    }

    /**
     * Récupérer les fournisseurs actifs uniquement
     */
    async getActifs(): Promise<Fournisseur[]> {
        return this.getAll({ actif: true });
    }

    /**
     * Récupérer les fournisseurs par type
     */
    async getByType(type: TypeFournisseur): Promise<Fournisseur[]> {
        return this.getAll({ type });
    }

    /**
     * Valider les données d'un fournisseur
     */
    validateFournisseur(fournisseur: FournisseurFormData): string[] {
        const errors: string[] = [];

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

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

        if (fournisseur.email && !this.isValidEmail(fournisseur.email)) {
            errors.push('L\'adresse email n\'est pas valide');
        }

        if (fournisseur.siret && fournisseur.siret.length > 20) {
            errors.push('Le numéro SIRET ne peut pas dépasser 20 caractères');
        }

        if (fournisseur.telephone && fournisseur.telephone.length > 20) {
            errors.push('Le numéro de téléphone ne peut pas dépasser 20 caractères');
        }

        return errors;
    }

    /**
     * Valider une adresse email
     */
    private isValidEmail(email: string): boolean {
        const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
        return emailRegex.test(email);
    }

    /**
     * Formater l'adresse complète d'un fournisseur
     */
    formatAdresseComplete(fournisseur: Fournisseur): string {
        const parties: string[] = [];

        if (fournisseur.adresse) {
            parties.push(fournisseur.adresse);
        }

        if (fournisseur.codePostal || fournisseur.ville) {
            const ligneVille = [fournisseur.codePostal, fournisseur.ville]
                .filter(Boolean)
                .join(' ');
            if (ligneVille) {
                parties.push(ligneVille);
            }
        }

        if (fournisseur.pays && fournisseur.pays !== 'France') {
            parties.push(fournisseur.pays);
        }

        return parties.join(', ');
    }

    /**
     * Obtenir le libellé d'un type de fournisseur
     */
    getTypeLabel(type: TypeFournisseur): string {
        const labels: Record<TypeFournisseur, string> = {
            MATERIEL: 'Matériel',
            SERVICE: 'Service',
            SOUS_TRAITANT: 'Sous-traitant',
            LOCATION: 'Location',
            TRANSPORT: 'Transport',
            CONSOMMABLE: 'Consommable'
        };
        return labels[type] || type;
    }

    /**
     * Exporter la liste des fournisseurs au format CSV
     */
    async exportToCsv(filters?: FournisseurFilters): Promise<Blob> {
        const fournisseurs = await this.getAll(filters);
        
        const headers = [
            'ID', 'Nom', 'Type', 'SIRET', 'Email', 'Téléphone', 
            'Adresse', 'Code Postal', 'Ville', 'Pays', 'Actif'
        ];

        const csvContent = [
            headers.join(';'),
            ...fournisseurs.map(f => [
                f.id || '',
                f.nom || '',
                this.getTypeLabel(f.type),
                f.siret || '',
                f.email || '',
                f.telephone || '',
                f.adresse || '',
                f.codePostal || '',
                f.ville || '',
                f.pays || '',
                f.actif ? 'Oui' : 'Non'
            ].join(';'))
        ].join('\n');

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

    /**
     * Importer des fournisseurs depuis un fichier CSV
     */
    async importFromCsv(file: File): Promise<{ success: number; errors: string[] }> {
        return new Promise((resolve, reject) => {
            const reader = new FileReader();
            reader.onload = async (e) => {
                try {
                    const csv = e.target?.result as string;
                    const lines = csv.split('\n');
                    const headers = lines[0].split(';');
                    
                    let successCount = 0;
                    const errors: string[] = [];

                    for (let i = 1; i < lines.length; i++) {
                        if (lines[i].trim()) {
                            try {
                                const values = lines[i].split(';');
                                const fournisseur: FournisseurFormData = {
                                    nom: values[1] || '',
                                    type: (values[2] as TypeFournisseur) || 'MATERIEL',
                                    siret: values[3] || undefined,
                                    email: values[4] || undefined,
                                    telephone: values[5] || undefined,
                                    adresse: values[6] || undefined,
                                    codePostal: values[7] || undefined,
                                    ville: values[8] || undefined,
                                    pays: values[9] || 'France',
                                    actif: values[10] === 'Oui'
                                };

                                const validationErrors = this.validateFournisseur(fournisseur);
                                if (validationErrors.length === 0) {
                                    await this.create(fournisseur);
                                    successCount++;
                                } else {
                                    errors.push(`Ligne ${i + 1}: ${validationErrors.join(', ')}`);
                                }
                            } catch (error) {
                                errors.push(`Ligne ${i + 1}: Erreur lors de la création`);
                            }
                        }
                    }

                    resolve({ success: successCount, errors });
                } catch (error) {
                    reject(error);
                }
            };
            reader.readAsText(file);
        });
    }
}

export default new FournisseurService();