import { chantierService as apiChantierService, apiService } from './api';
import { Chantier } from '../types/btp';
import { ChantierFormData } from '../types/chantier-form';

class ChantierService {
    /**
     * Récupérer tous les chantiers
     */
    async getAll(): Promise<Chantier[]> {
        return await apiChantierService.getAll();
    }

    /**
     * Récupérer un chantier par ID
     */
    async getById(id: string): Promise<Chantier> {
        return await apiChantierService.getById(id);
    }

    /**
     * Créer un nouveau chantier
     */
    async create(chantier: ChantierFormData): Promise<Chantier> {
        return await apiChantierService.create(chantier as any);
    }

    /**
     * Modifier un chantier existant
     */
    async update(id: string, chantier: ChantierFormData): Promise<Chantier> {
        return await apiChantierService.update(id, chantier as any);
    }

    /**
     * Supprimer un chantier
     * @param id - ID du chantier
     * @param permanent - Si true, suppression physique définitive. Si false, suppression logique (défaut)
     */
    async delete(id: string, permanent: boolean = false): Promise<void> {
        await apiChantierService.delete(id, permanent);
    }

    /**
     * Récupérer les chantiers d'un client
     */
    async getByClient(clientId: string): Promise<Chantier[]> {
        try {
            return await apiChantierService.getByClient(clientId);
        } catch (error: any) {
            // Si l'endpoint spécifique n'existe pas (404), essayer de filtrer tous les chantiers
            if (error.status === 404 || error.response?.status === 404) {
                try {
                    const tousLesChantiers = await this.getAll();
                    return tousLesChantiers.filter(chantier =>
                        (chantier.client as any)?.id === clientId || (chantier as any).clientId === clientId
                    );
                } catch (fallbackError) {
                    console.debug('Fallback sur filtrage côté client également impossible, retour liste vide');
                    // Retourner une liste vide plutôt qu'une erreur si pas de chantiers
                    return [];
                }
            }
            // Pour toute autre erreur, la remonter
            throw error;
        }
    }

    /**
     * Récupérer les chantiers récents
     */
    async getRecents(): Promise<Chantier[]> {
        return await apiChantierService.getRecents() as any;
    }

    /**
     * Récupérer les chantiers par statut
     */
    async getByStatut(statut: string): Promise<Chantier[]> {
        const allChantiers = await this.getAll();
        return allChantiers.filter(c => c.statut === statut);
    }

    /**
     * Récupérer les chantiers en retard
     */
    async getEnRetard(): Promise<Chantier[]> {
        const allChantiers = await this.getAll();
        return allChantiers.filter(c => this.isEnRetard(c));
    }

    /**
     * Récupérer les chantiers actifs
     */
    async getActifs(): Promise<Chantier[]> {
        return await this.getByStatut('EN_COURS');
    }

    /**
     * Actions sur les chantiers (nécessitent des endpoints spécifiques)
     */
    async demarrer(id: string): Promise<void> {
        // Ces méthodes nécessiteraient des endpoints spécifiques dans l'API
        throw new Error('Méthode non implémentée côté API');
    }

    async terminer(id: string): Promise<void> {
        throw new Error('Méthode non implémentée côté API');
    }

    async suspendre(id: string): Promise<void> {
        throw new Error('Méthode non implémentée côté API');
    }

    async reprendre(id: string): Promise<void> {
        throw new Error('Méthode non implémentée côté API');
    }

    async annuler(id: string): Promise<void> {
        throw new Error('Méthode non implémentée côté API');
    }

    /**
     * Valider les données d'un chantier
     */
    validateChantier(chantier: ChantierFormData): string[] {
        const errors: string[] = [];

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

        if (!chantier.adresse || chantier.adresse.trim().length === 0) {
            errors.push('L\'adresse est obligatoire');
        }

        if (!chantier.clientId) {
            errors.push('Le client est obligatoire');
        }

        if (!chantier.dateDebut) {
            errors.push('La date de début est obligatoire');
        }

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

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

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

        return errors;
    }

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

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

    /**
     * Vérifier si un chantier est en retard
     */
    isEnRetard(chantier: Chantier): boolean {
        if (chantier.statut === 'TERMINE') return false;
        if (!chantier.dateFinPrevue) return false;
        
        return new Date() > new Date(chantier.dateFinPrevue);
    }

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

    /**
     * Calculer l'avancement du chantier en pourcentage
     */
    calculateAvancement(chantier: Chantier): number {
        if (chantier.statut === 'TERMINE') return 100;
        if (chantier.statut === 'ANNULE') return 0;
        if (!chantier.dateDebut || !chantier.dateFinPrevue) return 0;

        const now = new Date();
        const start = new Date(chantier.dateDebut);
        const end = new Date(chantier.dateFinPrevue);
        
        if (now < start) return 0;
        if (now > end) return 100;
        
        const totalDays = (end.getTime() - start.getTime()) / (1000 * 60 * 60 * 24);
        const elapsedDays = (now.getTime() - start.getTime()) / (1000 * 60 * 60 * 24);
        
        return Math.min(Math.max((elapsedDays / totalDays) * 100, 0), 100);
    }

    /**
     * Obtenir le libellé d'un statut
     */
    getStatutLabel(statut: string): string {
        const labels: Record<string, string> = {
            PLANIFIE: 'Planifié',
            EN_COURS: 'En cours',
            TERMINE: 'Terminé',
            ANNULE: 'Annulé',
            SUSPENDU: 'Suspendu'
        };
        return labels[statut] || statut;
    }

    /**
     * Obtenir la couleur d'un statut
     */
    getStatutColor(statut: string): string {
        const colors: Record<string, string> = {
            PLANIFIE: '#6c757d',
            EN_COURS: '#0d6efd',
            TERMINE: '#198754',
            ANNULE: '#dc3545',
            SUSPENDU: '#fd7e14'
        };
        return colors[statut] || '#6c757d';
    }

    /**
     * Calculer les statistiques des chantiers
     */
    calculateStatistiques(chantiers: Chantier[]): {
        total: number;
        planifies: number;
        enCours: number;
        termines: number;
        annules: number;
        suspendus: number;
        enRetard: number;
        montantTotal: number;
        coutTotal: number;
    } {
        const stats = {
            total: chantiers.length,
            planifies: 0,
            enCours: 0,
            termines: 0,
            annules: 0,
            suspendus: 0,
            enRetard: 0,
            montantTotal: 0,
            coutTotal: 0
        };

        chantiers.forEach(chantier => {
            // Compter par statut
            switch (chantier.statut) {
                case 'PLANIFIE':
                    stats.planifies++;
                    break;
                case 'EN_COURS':
                    stats.enCours++;
                    break;
                case 'TERMINE':
                    stats.termines++;
                    break;
                case 'ANNULE':
                    stats.annules++;
                    break;
                case 'SUSPENDU':
                    stats.suspendus++;
                    break;
            }

            // Vérifier les retards
            if (this.isEnRetard(chantier)) {
                stats.enRetard++;
            }

            // Calculer montants
            stats.montantTotal += chantier.montantPrevu || 0;
            stats.coutTotal += chantier.montantReel || 0;
        });

        return stats;
    }

    /**
     * Exporter les chantiers au format CSV
     */
    async exportToCsv(): Promise<Blob> {
        const chantiers = await this.getAll();
        
        const headers = [
            'ID', 'Nom', 'Description', 'Adresse', 'Client', 'Statut',
            'Date Début', 'Date Fin Prévue', 'Date Fin Réelle', 
            'Montant Prévu', 'Montant Réel', 'Actif'
        ];

        const csvContent = [
            headers.join(';'),
            ...chantiers.map(c => [
                c.id || '',
                c.nom || '',
                c.description || '',
                c.adresse || '',
                c.client ? `${c.client.prenom} ${c.client.nom}` : '',
                this.getStatutLabel(c.statut),
                c.dateDebut ? new Date(c.dateDebut).toLocaleDateString('fr-FR') : '',
                c.dateFinPrevue ? new Date(c.dateFinPrevue).toLocaleDateString('fr-FR') : '',
                c.dateFinReelle ? new Date(c.dateFinReelle).toLocaleDateString('fr-FR') : '',
                c.montantPrevu || 0,
                c.montantReel || 0,
                c.actif ? 'Oui' : 'Non'
            ].join(';'))
        ].join('\n');

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

export default new ChantierService();