import { Component, inject, OnInit, Output, EventEmitter, ChangeDetectorRef, Input, OnDestroy } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { NgIcon } from '@ng-icons/core';
import { NgbPaginationModule } from '@ng-bootstrap/ng-bootstrap';
import { Observable, Subject, map, of } from 'rxjs';
import { catchError, takeUntil } from 'rxjs/operators';

import { 
  SubscriptionPayment,
  SubscriptionPaymentsResponse,
  Currency
} from '@core/models/dcb-bo-hub-subscription.model';

import { SubscriptionsService } from '../subscriptions.service';
import { AuthService } from '@core/services/auth.service';
import { UiCard } from '@app/components/ui-card';

@Component({
  selector: 'app-subscription-payments-list',
  standalone: true,
  imports: [
    CommonModule,
    FormsModule,
    NgIcon,
    UiCard, 
    NgbPaginationModule
  ],
  templateUrl: './subscription-payments-list.html',
})
export class SubscriptionPaymentsList implements OnInit, OnDestroy {
  private authService = inject(AuthService);
  private subscriptionsService = inject(SubscriptionsService);
  private cdRef = inject(ChangeDetectorRef);
  private destroy$ = new Subject<void>();
  
  // Configuration
  readonly Currency = Currency;
  
  // Inputs
  @Input() subscriptionId!: string;

  // Outputs
  @Output() paymentSelected = new EventEmitter<string>();
  @Output() viewSubscriptionDetails = new EventEmitter<string>();

  // Données
  allPayments: SubscriptionPayment[] = [];
  filteredPayments: SubscriptionPayment[] = [];
  displayedPayments: SubscriptionPayment[] = [];
  
  // États
  loading = false;
  error = '';

  // Recherche et filtres
  searchTerm = '';
  statusFilter: 'all' | 'SUCCESS' | 'FAILED' | 'PENDING' = 'all';
  dateFilter: 'all' | 'week' | 'month' | 'quarter' = 'all';

  // Pagination
  currentPage = 1;
  itemsPerPage = 10;
  totalItems = 0;
  totalPages = 0;

  // Tri
  sortField: keyof SubscriptionPayment = 'createdAt';
  sortDirection: 'asc' | 'desc' = 'desc';

  // Filtres disponibles
  availableStatuses: { value: 'all' | 'SUCCESS' | 'FAILED' | 'PENDING'; label: string }[] = [
    { value: 'all', label: 'Tous les statuts' },
    { value: 'SUCCESS', label: 'Réussis' },
    { value: 'FAILED', label: 'Échoués' },
    { value: 'PENDING', label: 'En attente' }
  ];

  availableDateRanges: { value: 'all' | 'week' | 'month' | 'quarter'; label: string }[] = [
    { value: 'all', label: 'Toute période' },
    { value: 'week', label: '7 derniers jours' },
    { value: 'month', label: '30 derniers jours' },
    { value: 'quarter', label: '3 derniers mois' }
  ];

  // Informations de l'abonnement
  subscriptionDetails: any = null;

  // Gestion des permissions
  currentUserRole: string | null = null;
  currentMerchantPartnerId: string = '';

  // Getters pour la logique conditionnelle
  get showSubscriptionColumn(): boolean {
    return !this.subscriptionId; // Afficher la colonne abonnement seulement si on est dans la vue globale
  }

  get showAmountColumn(): boolean {
    return true;
  }

  ngOnInit() {
    if (this.subscriptionId) {
      this.loadCurrentUserPermissions();
      this.loadPayments();
      this.loadSubscriptionDetails();
    }
  }

  ngOnDestroy(): void {
    this.destroy$.next();
    this.destroy$.complete();
  }

  private loadCurrentUserPermissions() {
    this.authService.getUserProfile()
      .pipe(takeUntil(this.destroy$))
      .subscribe({
        next: (user) => {
          this.currentUserRole = this.extractUserRole(user);
          this.currentMerchantPartnerId = this.extractMerchantPartnerId(user);

          console.log('Payments Context Loaded:', {
            role: this.currentUserRole,
            merchantPartnerId: this.currentMerchantPartnerId
          });
        },
        error: (error) => {
          console.error('Error loading current user permissions:', error);
          this.fallbackPermissions();
        }
      });
  }

  private extractUserRole(user: any): string | null {
    const userRoles = this.authService.getCurrentUserRoles();
    if (userRoles && userRoles.length > 0) {
      return userRoles[0];
    }
    return null;
  }

  private extractMerchantPartnerId(user: any): string {
    if (user?.merchantPartnerId) {
      return user.merchantPartnerId;
    }
    return this.authService.getCurrentMerchantPartnerId() || '';
  }

  private fallbackPermissions(): void {
    this.currentUserRole = this.authService.getCurrentUserRole();
    this.currentMerchantPartnerId = this.authService.getCurrentMerchantPartnerId() || '';
  }

  private loadSubscriptionDetails() {
    if (this.subscriptionId) {
      this.subscriptionsService.getSubscriptionById(this.subscriptionId)
        .pipe(takeUntil(this.destroy$))
        .subscribe({
          next: (subscription) => {
            this.subscriptionDetails = subscription;
          },
          error: (error) => {
            console.error('Error loading subscription details:', error);
          }
        });
    }
  }

  loadPayments() {
    this.loading = true;
    this.error = '';

    let paymentsObservable: Observable<SubscriptionPayment[]>;

    if (this.subscriptionId) {
      // Paiements d'un abonnement spécifique
      paymentsObservable = this.subscriptionsService.getSubscriptionPayments(this.currentMerchantPartnerId, this.subscriptionId).pipe(
        map((response: SubscriptionPaymentsResponse) => response.payments)
      );
    } else {
      // Vue globale des paiements (à implémenter si nécessaire)
      paymentsObservable = of([]);
    }
  
    paymentsObservable
      .pipe(
        takeUntil(this.destroy$),
        catchError(error => {
          console.error('Error loading subscription payments:', error);
          this.error = 'Erreur lors du chargement des paiements';
          return of([] as SubscriptionPayment[]);
        })
      )
      .subscribe({
        next: (payments) => {
          this.allPayments = payments || [];
          console.log(`✅ Loaded ${this.allPayments.length} payments`);
          this.applyFiltersAndPagination();
          this.loading = false;
          this.cdRef.detectChanges();
        },
        error: () => {
          this.error = 'Erreur lors du chargement des paiements';
          this.loading = false;
          this.allPayments = [];
          this.filteredPayments = [];
          this.displayedPayments = [];
          this.cdRef.detectChanges();
        }
      });
  }

  // Recherche et filtres
  onSearch() {
    this.currentPage = 1;
    this.applyFiltersAndPagination();
  }

  onClearFilters() {
    this.searchTerm = '';
    this.statusFilter = 'all';
    this.dateFilter = 'all';
    this.currentPage = 1;
    this.applyFiltersAndPagination();
  }

  applyFiltersAndPagination() {
    if (!this.allPayments) {
      this.allPayments = [];
    }

    // Appliquer les filtres
    this.filteredPayments = this.allPayments.filter(payment => {
      const matchesSearch = !this.searchTerm || 
        payment.reference.toLowerCase().includes(this.searchTerm.toLowerCase()) ||
        payment.description.toLowerCase().includes(this.searchTerm.toLowerCase()) ||
        (payment.metadata?.internatRef && payment.metadata.internatRef.toLowerCase().includes(this.searchTerm.toLowerCase()));

      const matchesStatus = this.statusFilter === 'all' || 
        payment.status === this.statusFilter;

      const matchesDate = this.applyDateFilter(payment);

      return matchesSearch && matchesStatus && matchesDate;
    });

    // Appliquer le tri
    this.filteredPayments.sort((a, b) => {
      const aValue = a[this.sortField];
      const bValue = b[this.sortField];
      
      if (aValue === bValue) return 0;
      
      let comparison = 0;
      if (typeof aValue === 'string' && typeof bValue === 'string') {
        comparison = aValue.localeCompare(bValue);
      } else if (typeof aValue === 'number' && typeof bValue === 'number') {
        comparison = aValue - bValue;
      } else if (aValue instanceof Date && bValue instanceof Date) {
        comparison = aValue.getTime() - bValue.getTime();
      }
      
      return this.sortDirection === 'asc' ? comparison : -comparison;
    });

    // Calculer la pagination
    this.totalItems = this.filteredPayments.length;
    this.totalPages = Math.ceil(this.totalItems / this.itemsPerPage);
    
    // Appliquer la pagination
    const startIndex = (this.currentPage - 1) * this.itemsPerPage;
    const endIndex = startIndex + this.itemsPerPage;
    this.displayedPayments = this.filteredPayments.slice(startIndex, endIndex);
  }

  private applyDateFilter(payment: SubscriptionPayment): boolean {
    if (this.dateFilter === 'all') return true;

    const paymentDate = new Date(payment.createdAt);
    const now = new Date();
    let startDate = new Date();

    switch (this.dateFilter) {
      case 'week':
        startDate.setDate(now.getDate() - 7);
        break;
      case 'month':
        startDate.setMonth(now.getMonth() - 1);
        break;
      case 'quarter':
        startDate.setMonth(now.getMonth() - 3);
        break;
    }

    return paymentDate >= startDate;
  }

  // Tri
  sort(field: keyof SubscriptionPayment) {
    if (this.sortField === field) {
      this.sortDirection = this.sortDirection === 'asc' ? 'desc' : 'asc';
    } else {
      this.sortField = field;
      this.sortDirection = 'desc'; // Par défaut, tri décroissant pour les dates
    }
    this.applyFiltersAndPagination();
  }

  getSortIcon(field: string): string {
    if (this.sortField !== field) return 'lucideArrowUpDown';
    return this.sortDirection === 'asc' ? 'lucideArrowUp' : 'lucideArrowDown';
  }

  // Pagination
  onPageChange(page: number) {
    this.currentPage = page;
    this.applyFiltersAndPagination();
  }

  getStartIndex(): number {
    return (this.currentPage - 1) * this.itemsPerPage + 1;
  }

  getEndIndex(): number {
    return Math.min(this.currentPage * this.itemsPerPage, this.totalItems);
  }

  // Actions
  viewPaymentDetails(paymentId: string | number) {
    this.paymentSelected.emit(paymentId.toString());
  }

  navigateToSubscription(subscriptionId: string | number) {
    this.viewSubscriptionDetails.emit(subscriptionId.toString());
  }

  // Utilitaires d'affichage
  getPaymentStatusBadgeClass(status: string): string {
    const statusClasses: { [key: string]: string } = {
      'SUCCESS': 'badge bg-success',
      'FAILED': 'badge bg-danger',
      'PENDING': 'badge bg-warning'
    };
    return statusClasses[status] || 'badge bg-secondary';
  }

  getPaymentStatusDisplayName(status: string): string {
    const statusNames: { [key: string]: string } = {
      'SUCCESS': 'Réussi',
      'FAILED': 'Échoué',
      'PENDING': 'En attente'
    };
    return statusNames[status] || status;
  }

  getPaymentStatusIcon(status: string): string {
    const statusIcons: { [key: string]: string } = {
      'SUCCESS': 'lucideCheckCircle',
      'FAILED': 'lucideXCircle',
      'PENDING': 'lucideClock'
    };
    return statusIcons[status] || 'lucideHelpCircle';
  }

  formatAmount(amount: number, currency: Currency): string {
    return new Intl.NumberFormat('fr-FR', {
      style: 'currency',
      currency: currency
    }).format(amount);
  }

  formatDate(dateString: string): string {
    return new Date(dateString).toLocaleDateString('fr-FR', {
      year: 'numeric',
      month: 'short',
      day: 'numeric'
    });
  }

  formatDateTime(dateString: string): string {
    return new Date(dateString).toLocaleDateString('fr-FR', {
      year: 'numeric',
      month: 'short',
      day: 'numeric',
      hour: '2-digit',
      minute: '2-digit'
    });
  }

  // Statistiques
  getTotalPaymentsCount(): number {
    return this.allPayments.length;
  }

  getSuccessfulPaymentsCount(): number {
    return this.allPayments.filter(payment => payment.status === 'SUCCESS').length;
  }

  getFailedPaymentsCount(): number {
    return this.allPayments.filter(payment => payment.status === 'FAILED').length;
  }

  getPendingPaymentsCount(): number {
    return this.allPayments.filter(payment => payment.status === 'PENDING').length;
  }

  getTotalAmount(): number {
    return this.allPayments
      .filter(payment => payment.status === 'SUCCESS')
      .reduce((sum, payment) => sum + payment.amount, 0);
  }

  getSuccessRate(): number {
    if (this.allPayments.length === 0) return 0;
    return (this.getSuccessfulPaymentsCount() / this.allPayments.length) * 100;
  }

  // Recherche rapide par statut
  filterByStatus(status: 'all' | 'SUCCESS' | 'FAILED' | 'PENDING') {
    this.statusFilter = status;
    this.currentPage = 1;
    this.applyFiltersAndPagination();
  }

  // Recharger les données
  refreshData() {
    this.loadPayments();
    if (this.subscriptionId) {
      this.loadSubscriptionDetails();
    }
  }

  // Méthodes pour le template
  getCardTitle(): string {
    if (this.subscriptionId && this.subscriptionDetails) {
      return `Paiements - Abonnement #${this.subscriptionDetails.id}`;
    }
    return 'Historique des Paiements';
  }

  getHelperText(): string {
    if (this.subscriptionId) {
      return 'Historique des paiements pour cet abonnement';
    }
    return 'Vue globale de tous les paiements';
  }

  getHelperIcon(): string {
    return 'lucideCreditCard';
  }

  getLoadingText(): string {
    return 'Chargement des paiements...';
  }

  getEmptyStateTitle(): string {
    return 'Aucun paiement trouvé';
  }

  getEmptyStateDescription(): string {
    return 'Aucun paiement ne correspond à vos critères de recherche.';
  }

  getColumnCount(): number {
    let count = 5; // Référence, Date, Montant, Statut, Actions
    if (this.showSubscriptionColumn) count++;
    return count;
  }

  // Méthodes pour les résumés
  getPaymentsSummary(): { total: number; success: number; failed: number; pending: number; amount: number } {
    return {
      total: this.getTotalPaymentsCount(),
      success: this.getSuccessfulPaymentsCount(),
      failed: this.getFailedPaymentsCount(),
      pending: this.getPendingPaymentsCount(),
      amount: this.getTotalAmount()
    };
  }

  // Formatage pour l'affichage
  truncateText(text: string, maxLength: number = 20): string {
    if (!text) return '';
    return text.length > maxLength ? text.substring(0, maxLength) + '...' : text;
  }

  getInternalReference(payment: SubscriptionPayment): string {
    return payment.metadata?.internatRef || 'N/A';
  }
}