import { Injectable } from '@angular/core';
import { HttpClient, HttpParams } from '@angular/common/http';
import { Observable } from 'rxjs';
import { environment } from '../../../environments/environment';
import {
  DashboardResponse,
  ReportFilters,
  ReportDetail,
  RefreshLinksResponse,
  BanqueMouvementsReport,
  FinancialRequestsReport,
  CreditLimitsReport,
  SoldesBmpReport,
  BmpEtatsdeventesReport,
  BspDetailEtatsdeventesReport
} from '../models/reports.models';

@Injectable({
  providedIn: 'root'
})
export class ReportsService {
  private apiUrl = `${environment.DATA_URL}admin/reports`;

  constructor(private http: HttpClient) {}

  /**
   * Récupère le dashboard global avec tous les rapports
   */
  getDashboard(filters: ReportFilters): Observable<DashboardResponse> {
    console.log('📊 Chargement du dashboard des rapports:', filters);
    console.log('📊 URL complète:', `${this.apiUrl}/dashboard`);
    console.log('📊 DATA_URL:', environment.DATA_URL);
    const params = this.buildParams(filters);
    return this.http.get<DashboardResponse>(`${this.apiUrl}/dashboard`, { params });
  }

  /**
   * Rapport Banque ↔ Mouvements
   */
  getBanqueMouvementsReport(filters: ReportFilters): Observable<BanqueMouvementsReport> {
    const params = this.buildParams(filters);
    console.log('📦 Chargement rapport Banque ↔ Mouvements:', filters);

    return this.http.get<BanqueMouvementsReport>(`${this.apiUrl}/banques_mouvements`, { params });
  }

  /**
   * Rapport Financial Requests ↔ Mouvements
   */
  getFinancialRequestsReport(filters: ReportFilters): Observable<FinancialRequestsReport> {
    const params = this.buildParams(filters);
    console.log('💰 Chargement rapport Financial Requests:', filters);

    return this.http.get<FinancialRequestsReport>(`${this.apiUrl}/financial_requests_mouvements`, { params });
  }

  /**
   * Rapport CreditLimits ↔ Mouvements
   */
  getCreditLimitsReport(filters: ReportFilters): Observable<CreditLimitsReport> {
    const params = this.buildParams(filters);
    console.log('💳 Chargement rapport CreditLimits:', filters);

    return this.http.get<CreditLimitsReport>(`${this.apiUrl}/creditlimits`, { params });
  }

  /**
   * Rapport Soldes BMP ↔ Soldes Estair
   */
  getSoldesBmpReport(filters: ReportFilters): Observable<SoldesBmpReport> {
    const params = this.buildParams(filters);
    console.log('💵 Chargement rapport Soldes BMP:', filters);

    return this.http.get<SoldesBmpReport>(`${this.apiUrl}/soldesbmp_soldes`, { params });
  }

  /**
   * Rapport BMP ↔ Etatsdeventes
   */
  getBmpEtatsdeventesReport(filters: ReportFilters): Observable<BmpEtatsdeventesReport> {
    const params = this.buildParams(filters);
    console.log('📋 Chargement rapport BMP ↔ Etatsdeventes:', filters);

    return this.http.get<BmpEtatsdeventesReport>(`${this.apiUrl}/bmps_etatsdeventes`, { params });
  }

  /**
   * Rapport BspDetail ↔ Etatsdeventes
   */
  getBspDetailEtatsdeventesReport(filters: ReportFilters): Observable<BspDetailEtatsdeventesReport> {
    const params = this.buildParams(filters);
    console.log('📄 Chargement rapport BspDetail ↔ Etatsdeventes:', filters);

    return this.http.get<BspDetailEtatsdeventesReport>(`${this.apiUrl}/bspdetails_etatsdeventes`, { params });
  }

  /**
   * Rapport Etatsdeventes ↔ Mouvements
   */
  getEtatsdeventesMouvementsReport(filters: ReportFilters): Observable<any> {
    const params = this.buildParams(filters);
    console.log('📋 Chargement rapport Etatsdeventes ↔ Mouvements:', filters);

    return this.http.get<any>(`${this.apiUrl}/etatsdeventes_mouvements`, { params });
  }

  /**
   * Exporte un rapport dans le format spécifié
   */
  exportReport(
    reportType: string,
    format: 'csv' | 'excel' | 'pdf',
    filters: ReportFilters
  ): Observable<Blob> {
    const params = this.buildParams(filters);
    console.log(`📥 Export rapport ${reportType} en ${format}:`, filters);

    const slug = this.toUrlSlug(reportType);
    return this.http.post(
      `${this.apiUrl}/${slug}/export`,
      { format },
      {
        params,
        responseType: 'blob'
      }
    );
  }

  /**
   * Rafraîchit les liens de données pour un type de rapport spécifique
   */
  refreshLinks(reportType: string, filters: ReportFilters): Observable<RefreshLinksResponse> {
    const linkSlug = this.toLinksSlug(reportType);
    if (!linkSlug) {
      throw new Error(`Pas de liens disponibles pour le type: ${reportType}`);
    }

    const params = this.buildParams(filters);
    console.log(`🔗 Rafraîchissement des liens pour ${reportType} → ${linkSlug}:`, filters);

    return this.http.post<RefreshLinksResponse>(
      `${environment.DATA_URL}admin/links/${linkSlug}`,
      null,
      { params }
    );
  }

  /**
   * Récupère le rapport détaillé pour un type donné (dispatch dynamique)
   */
  getReportDetail(reportType: string, filters: ReportFilters): Observable<ReportDetail> {
    switch (reportType) {
      case 'banques_mouvements':
        return this.getBanqueMouvementsReport(filters);
      case 'financial_requests_mouvements':
        return this.getFinancialRequestsReport(filters);
      case 'etatsdeventes_mouvements':
        return this.getEtatsdeventesMouvementsReport(filters);
      case 'soldesbmp_soldes':
        return this.getSoldesBmpReport(filters);
      case 'bmps_etatsdeventes':
        return this.getBmpEtatsdeventesReport(filters);
      case 'bspdetails_etatsdeventes':
        return this.getBspDetailEtatsdeventesReport(filters);
      default:
        throw new Error(`Type de rapport inconnu: ${reportType}`);
    }
  }

  /**
   * Vérifie si un type de rapport supporte le refresh des liens
   */
  hasRefreshableLinks(reportType: string): boolean {
    return this.toLinksSlug(reportType) !== null;
  }

  /**
   * Convertit le type de rapport en slug pour l'endpoint /admin/links/
   */
  private toLinksSlug(reportType: string): string | null {
    const mapping: Record<string, string> = {
      'banques_mouvements': 'banques_mouvements',
      'financial_requests_mouvements': 'financial_requests_mouvements',
      'soldesbmp_soldes': 'soldesbmp_soldes',
      'bmps_etatsdeventes': 'bmps_etatsdeventes',
      'bspdetails_etatsdeventes': 'bspdetails_etatsdeventes',
      'etatsdeventes_mouvements': 'etatsdeventes_mouvements',
    };
    return mapping[reportType] || null;
  }

  /**
   * Convertit le type de rapport (underscores) en slug URL (tirets)
   */
  private toUrlSlug(reportType: string): string {
    const mapping: Record<string, string> = {
      'banques_mouvements': 'banques_mouvements',
      'financial_requests_mouvements': 'financial_requests_mouvements',
      'etatsdeventes_mouvements': 'etatsdeventes_mouvements',
      'soldesbmp_soldes': 'soldesbmp_soldes',
      'bmps_etatsdeventes': 'bmps_etatsdeventes',
      'bspdetails_etatsdeventes': 'bspdetails_etatsdeventes'
    };
    return mapping[reportType] || reportType.replace(/_/g, '-');
  }

  /**
   * Construit les paramètres HTTP à partir des filtres
   */
  private buildParams(filters: ReportFilters): HttpParams {
    let params = new HttpParams()
      .set('date_from', filters.date_from)
      .set('date_to', filters.date_to);

    if (filters.account_id) {
      params = params.set('account_id', filters.account_id.toString());
    }

    return params;
  }

  /**
   * Détermine le statut de santé basé sur le pourcentage
   */
  getHealthStatus(percentage: number): 'good' | 'warning' | 'critical' {
    if (percentage >= 95) return 'good';
    if (percentage >= 85) return 'warning';
    return 'critical';
  }

  /**
   * Détermine la couleur basée sur le statut
   */
  getHealthColor(status: 'good' | 'warning' | 'critical'): string {
    switch (status) {
      case 'good': return '#00E396';
      case 'warning': return '#FEB019';
      case 'critical': return '#FF4560';
      default: return '#999999';
    }
  }

  /**
   * Formatte un montant en affichage
   */
  formatAmount(amount: number): string {
    return new Intl.NumberFormat('fr-FR', {
      style: 'currency',
      currency: 'XOF',
      minimumFractionDigits: 0
    }).format(amount);
  }

  /**
   * Formatte un pourcentage
   */
  formatPercentage(percentage: number): string {
    return `${percentage.toFixed(2)}%`;
  }
}
