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 { 
  Subscription,
  SubscriptionsResponse,
  SubscriptionStatus,
  SubscriptionPeriodicity,
  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-subscriptions-list',
  standalone: true,
  imports: [
    CommonModule,
    FormsModule,
    NgIcon,
    UiCard, 
    NgbPaginationModule
  ],
  templateUrl: './subscriptions-list.html',
})
export class SubscriptionsList implements OnInit, OnDestroy {
  private authService = inject(AuthService);
  private subscriptionsService = inject(SubscriptionsService);
  private cdRef = inject(ChangeDetectorRef);
  private destroy$ = new Subject<void>();
  
  // Configuration
  readonly SubscriptionStatus = SubscriptionStatus;
  readonly SubscriptionPeriodicity = SubscriptionPeriodicity;
  readonly Currency = Currency;
  
  // Outputs
  @Output() subscriptionSelected = new EventEmitter<string>();
  @Output() viewPaymentsRequested = new EventEmitter<string>();

  // Données
  allSubscriptions: Subscription[] = [];
  filteredSubscriptions: Subscription[] = [];
  displayedSubscriptions: Subscription[] = [];
  
  // États
  loading = false;
  error = '';

  // Recherche et filtres
  searchTerm = '';
  statusFilter: SubscriptionStatus | 'all' = 'all';
  periodicityFilter: SubscriptionPeriodicity | 'all' = 'all';
  merchantFilter: number | 'all' = 'all';

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

  // Tri
  sortField: keyof Subscription = 'startDate';
  sortDirection: 'asc' | 'desc' = 'desc';

  // Filtres disponibles
  availableStatuses: { value: SubscriptionStatus | 'all'; label: string }[] = [
    { value: 'all', label: 'Tous les statuts' },
    { value: SubscriptionStatus.ACTIVE, label: 'Actif' },
    { value: SubscriptionStatus.SUSPENDED, label: 'Suspendu' },
    { value: SubscriptionStatus.CANCELLED, label: 'Annulé' },
    { value: SubscriptionStatus.EXPIRED, label: 'Expiré' },
    { value: SubscriptionStatus.PENDING, label: 'En attente' }
  ];

  availablePeriodicities: { value: SubscriptionPeriodicity | 'all'; label: string }[] = [
    { value: 'all', label: 'Toutes les périodicités' },
    { value: SubscriptionPeriodicity.DAILY, label: 'Quotidien' },
    { value: SubscriptionPeriodicity.WEEKLY, label: 'Hebdomadaire' },
    { value: SubscriptionPeriodicity.MONTHLY, label: 'Mensuel' },
    { value: SubscriptionPeriodicity.YEARLY, label: 'Annuel' }
  ];
  
  // ID du merchant partner courant et permissions
  currentMerchantPartnerId: string = '';
  currentUserRole: string | null = null;
  canViewAllMerchants = false;

  // Merchants disponibles pour le filtre
  availableMerchants: { value: number | 'all'; label: string }[] = [];

  ngOnInit() {
    this.loadCurrentUserPermissions();
  }

  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);
          this.canViewAllMerchants = this.canViewAllMerchantsCheck(this.currentUserRole);

          console.log('Subscriptions Context Loaded:', {
            role: this.currentUserRole,
            merchantPartnerId: this.currentMerchantPartnerId,
            canViewAllMerchants: this.canViewAllMerchants
          });

          this.loadSubscriptions();
        },
        error: (error) => {
          console.error('Error loading current user permissions:', error);
          this.fallbackPermissions();
          this.loadSubscriptions();
        }
      });
  }

  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 canViewAllMerchantsCheck(role: string | null): boolean {
    if (!role) return false;
    
    const canViewAllRoles = [
      'DCB_ADMIN',
      'DCB_SUPPORT',
      'DCB_PARTNER_ADMIN'
    ];
    
    return canViewAllRoles.includes(role);
  }

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

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

    let subscriptionsObservable: Observable<SubscriptionsResponse>;

    if (this.canViewAllMerchants) {
      // Admin/Support - tous les abonnements
      subscriptionsObservable = this.subscriptionsService.getSubscriptions({
        page: this.currentPage,
        limit: this.itemsPerPage
      });
    } else if (this.currentMerchantPartnerId) {
      // Merchant régulier - ses abonnements
      subscriptionsObservable = this.subscriptionsService.getSubscriptionsByMerchant(
        parseInt(this.currentMerchantPartnerId),
        { page: this.currentPage, limit: this.itemsPerPage }
      );
    } else {
      // Fallback - abonnements généraux
      subscriptionsObservable = this.subscriptionsService.getSubscriptions({
        page: this.currentPage,
        limit: this.itemsPerPage
      });
    }
  
    subscriptionsObservable
      .pipe(
        takeUntil(this.destroy$),
        catchError(error => {
          console.error('Error loading subscriptions:', error);
          this.error = 'Erreur lors du chargement des abonnements';
          return of({ subscriptions: [], statistics: { total: 0, active: 0, totalRevenue: 0, averageAmount: 0 } } as SubscriptionsResponse);
        })
      )
      .subscribe({
        next: (response) => {
          this.allSubscriptions = response.subscriptions || [];
          console.log(`✅ Loaded ${this.allSubscriptions.length} subscriptions`);
          this.applyFiltersAndPagination();
          this.loading = false;
          this.cdRef.detectChanges();
        },
        error: () => {
          this.error = 'Erreur lors du chargement des abonnements';
          this.loading = false;
          this.allSubscriptions = [];
          this.filteredSubscriptions = [];
          this.displayedSubscriptions = [];
          this.cdRef.detectChanges();
        }
      });
  }

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

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

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

    // Appliquer les filtres
    this.filteredSubscriptions = this.allSubscriptions.filter(subscription => {
      const matchesSearch = !this.searchTerm || 
        subscription.id.toString().includes(this.searchTerm) ||
        subscription.token.toLowerCase().includes(this.searchTerm.toLowerCase()) ||
        (subscription.externalReference && subscription.externalReference.toLowerCase().includes(this.searchTerm.toLowerCase()));

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

      const matchesPeriodicity = this.periodicityFilter === 'all' || 
        subscription.periodicity === this.periodicityFilter;

      const matchesMerchant = this.merchantFilter === 'all' || 
        subscription.merchantPartnerId === this.merchantFilter;

      return matchesSearch && matchesStatus && matchesPeriodicity && matchesMerchant;
    });

    // Appliquer le tri
    this.filteredSubscriptions.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.filteredSubscriptions.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.displayedSubscriptions = this.filteredSubscriptions.slice(startIndex, endIndex);
  }

  // Tri
  sort(field: keyof Subscription) {
    if (this.sortField === field) {
      this.sortDirection = this.sortDirection === 'asc' ? 'desc' : 'asc';
    } else {
      this.sortField = field;
      this.sortDirection = 'asc';
    }
    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
  viewSubscriptionDetails(subscriptionId: string | number) {
    this.subscriptionSelected.emit(subscriptionId.toString());
  }

  viewSubscriptionPayments(subscriptionId: string | number) {
    this.viewPaymentsRequested.emit(subscriptionId.toString());
  }

  // Utilitaires d'affichage
  getStatusBadgeClass(status: SubscriptionStatus): string {
    const statusClasses = {
      [SubscriptionStatus.ACTIVE]: 'badge bg-success',
      [SubscriptionStatus.SUSPENDED]: 'badge bg-warning',
      [SubscriptionStatus.CANCELLED]: 'badge bg-danger',
      [SubscriptionStatus.EXPIRED]: 'badge bg-secondary',
      [SubscriptionStatus.PENDING]: 'badge bg-info'
    };
    return statusClasses[status] || 'badge bg-secondary';
  }

  getStatusDisplayName(status: SubscriptionStatus): string {
    const statusNames = {
      [SubscriptionStatus.ACTIVE]: 'Actif',
      [SubscriptionStatus.SUSPENDED]: 'Suspendu',
      [SubscriptionStatus.CANCELLED]: 'Annulé',
      [SubscriptionStatus.EXPIRED]: 'Expiré',
      [SubscriptionStatus.PENDING]: 'En attente'
    };
    return statusNames[status] || status;
  }

  getPeriodicityDisplayName(periodicity: SubscriptionPeriodicity): string {
    const periodicityNames = {
      [SubscriptionPeriodicity.DAILY]: 'Quotidien',
      [SubscriptionPeriodicity.WEEKLY]: 'Hebdomadaire',
      [SubscriptionPeriodicity.MONTHLY]: 'Mensuel',
      [SubscriptionPeriodicity.YEARLY]: 'Annuel'
    };
    return periodicityNames[periodicity] || periodicity;
  }

  // Méthodes pour compter les abonnements par périodicité
  getDailySubscriptionsCount(): number {
    if (!this.allSubscriptions || this.allSubscriptions.length === 0) return 0;
    return this.allSubscriptions.filter(s => s.periodicity === SubscriptionPeriodicity.DAILY).length;
  }

  getWeeklySubscriptionsCount(): number {
    if (!this.allSubscriptions || this.allSubscriptions.length === 0) return 0;
    return this.allSubscriptions.filter(s => s.periodicity === SubscriptionPeriodicity.WEEKLY).length;
  }

  getMonthlySubscriptionsCount(): number {
    if (!this.allSubscriptions || this.allSubscriptions.length === 0) return 0;
    return this.allSubscriptions.filter(s => s.periodicity === SubscriptionPeriodicity.MONTHLY).length;
  }

  getYearlySubscriptionsCount(): number {
    if (!this.allSubscriptions || this.allSubscriptions.length === 0) return 0;
    return this.allSubscriptions.filter(s => s.periodicity === SubscriptionPeriodicity.YEARLY).length;
  }


  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'
    });
  }

  // Recharger les données
  refreshData() {
    this.loadSubscriptions();
  }

  // Méthodes pour le template
  getCardTitle(): string {
    return 'Abonnements';
  }

  getHelperText(): string {
    return this.canViewAllMerchants 
      ? 'Vue administrative - Tous les abonnements' 
      : 'Vos abonnements';
  }

  getHelperIcon(): string {
    return this.canViewAllMerchants ? 'lucideShield' : 'lucideRepeat';
  }

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

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

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

  // Statistiques
  getTotalSubscriptionsCount(): number {
    return this.allSubscriptions.length;
  }

  // Méthodes pour exposer les valeurs d'énumération au template
  getActiveStatus(): SubscriptionStatus {
    return SubscriptionStatus.ACTIVE;
  }

  getSuspendedStatus(): SubscriptionStatus {
    return SubscriptionStatus.SUSPENDED;
  }

  getCancelledStatus(): SubscriptionStatus {
    return SubscriptionStatus.CANCELLED;
  }

  getExpiredStatus(): SubscriptionStatus {
    return SubscriptionStatus.EXPIRED;
  }

  getPendingStatus(): SubscriptionStatus {
    return SubscriptionStatus.PENDING;
  }

  // Méthodes pour compter les abonnements par statut
  getActiveSubscriptionsCount(): number {
    if (!this.allSubscriptions || this.allSubscriptions.length === 0) return 0;
    return this.allSubscriptions.filter(s => s.status === SubscriptionStatus.ACTIVE).length;
  }

  getSuspendedSubscriptionsCount(): number {
    if (!this.allSubscriptions || this.allSubscriptions.length === 0) return 0;
    return this.allSubscriptions.filter(s => s.status === SubscriptionStatus.SUSPENDED).length;
  }

  getCancelledSubscriptionsCount(): number {
    if (!this.allSubscriptions || this.allSubscriptions.length === 0) return 0;
    return this.allSubscriptions.filter(s => s.status === SubscriptionStatus.CANCELLED).length;
  }

  getExpiredSubscriptionsCount(): number {
    if (!this.allSubscriptions || this.allSubscriptions.length === 0) return 0;
    return this.allSubscriptions.filter(s => s.status === SubscriptionStatus.EXPIRED).length;
  }

  getPendingSubscriptionsCount(): number {
    if (!this.allSubscriptions || this.allSubscriptions.length === 0) return 0;
    return this.allSubscriptions.filter(s => s.status === SubscriptionStatus.PENDING).length;
  }

  getTotalRevenue(): number {
    return this.allSubscriptions.reduce((sum, sub) => sum + sub.amount, 0);
  }

  // Getters pour la logique conditionnelle
  get showMerchantColumn(): boolean {
    return this.canViewAllMerchants;
  }

  get showCustomerColumn(): boolean {
    return this.canViewAllMerchants;
  }

  getColumnCount(): number {
    let count = 6; // ID, Montant, Périodicité, Statut, Date début, Actions
    if (this.showMerchantColumn) count++;
    if (this.showCustomerColumn) count++;
    return count;
  }

  // Filtrage rapide par statut
  filterByStatus(status: SubscriptionStatus | 'all') {
    this.statusFilter = status;
    this.currentPage = 1;
    this.applyFiltersAndPagination();
  }

  // Filtrage rapide par périodicité
  filterByPeriodicity(periodicity: SubscriptionPeriodicity | 'all') {
    this.periodicityFilter = periodicity;
    this.currentPage = 1;
    this.applyFiltersAndPagination();
  }

  // Calculer les jours jusqu'au prochain paiement
  getDaysUntilNextPayment(subscription: Subscription): number {
    const nextPayment = new Date(subscription.nextPaymentDate);
    const today = new Date();
    const diffTime = nextPayment.getTime() - today.getTime();
    return Math.ceil(diffTime / (1000 * 60 * 60 * 24));
  }

  // Vérifier si un abonnement est sur le point d'expirer (dans les 7 jours)
  isExpiringSoon(subscription: Subscription): boolean {
    if (!subscription.endDate) return false;
    const endDate = new Date(subscription.endDate);
    const today = new Date();
    const diffTime = endDate.getTime() - today.getTime();
    const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
    return diffDays <= 7 && diffDays > 0;
  }

  // Vérifier si un abonnement est expiré
  isExpired(subscription: Subscription): boolean {
    if (!subscription.endDate) return false;
    return new Date(subscription.endDate) < new Date();
  }
}