/**
 * Billing View Model
 *
 * View model for sponsor billing data with UI-specific transformations.
 */
export class BillingViewModel {
  paymentMethods: PaymentMethodViewModel[];
  invoices: InvoiceViewModel[];
  stats: BillingStatsViewModel;

  constructor(data: {
    paymentMethods: unknown[];
    invoices: unknown[];
    stats: unknown;
  }) {
    this.paymentMethods = data.paymentMethods.map(pm => new PaymentMethodViewModel(pm));
    this.invoices = data.invoices.map(inv => new InvoiceViewModel(inv));
    this.stats = new BillingStatsViewModel(data.stats);
  }
}

export class PaymentMethodViewModel {
  id: string;
  type: 'card' | 'bank' | 'sepa';
  last4: string;
  brand?: string;
  isDefault: boolean;
  expiryMonth?: number;
  expiryYear?: number;
  bankName?: string;

  constructor(data: unknown) {
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    const d = data as any;
    this.id = d.id;
    this.type = d.type;
    this.last4 = d.last4;
    this.brand = d.brand;
    this.isDefault = d.isDefault;
    this.expiryMonth = d.expiryMonth;
    this.expiryYear = d.expiryYear;
    this.bankName = d.bankName;
  }

  get displayLabel(): string {
    if (this.type === 'sepa' && this.bankName) {
      return `${this.bankName} •••• ${this.last4}`;
    }
    return `${this.brand} •••• ${this.last4}`;
  }

  get expiryDisplay(): string | null {
    if (this.expiryMonth && this.expiryYear) {
      return `${String(this.expiryMonth).padStart(2, '0')}/${this.expiryYear}`;
    }
    return null;
  }
}

export class InvoiceViewModel {
  id: string;
  invoiceNumber: string;
  date: Date;
  dueDate: Date;
  amount: number;
  vatAmount: number;
  totalAmount: number;
  status: 'paid' | 'pending' | 'overdue' | 'failed';
  description: string;
  sponsorshipType: 'league' | 'team' | 'driver' | 'race' | 'platform';
  pdfUrl: string;

  constructor(data: unknown) {
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    const d = data as any;
    this.id = d.id;
    this.invoiceNumber = d.invoiceNumber;
    this.date = new Date(d.date);
    this.dueDate = new Date(d.dueDate);
    this.amount = d.amount;
    this.vatAmount = d.vatAmount;
    this.totalAmount = d.totalAmount;
    this.status = d.status;
    this.description = d.description;
    this.sponsorshipType = d.sponsorshipType;
    this.pdfUrl = d.pdfUrl;
  }

  get formattedTotalAmount(): string {
    return `€${this.totalAmount.toLocaleString('de-DE', { minimumFractionDigits: 2 })}`;
  }

  get formattedVatAmount(): string {
    return `€${this.vatAmount.toLocaleString('de-DE', { minimumFractionDigits: 2 })}`;
  }

  get formattedDate(): string {
    return this.date.toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' });
  }

  get isOverdue(): boolean {
    return this.status === 'overdue' || (this.status === 'pending' && new Date() > this.dueDate);
  }
}

export class BillingStatsViewModel {
  totalSpent: number;
  pendingAmount: number;
  nextPaymentDate: Date;
  nextPaymentAmount: number;
  activeSponsorships: number;
  averageMonthlySpend: number;

  constructor(data: unknown) {
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    const d = data as any;
    this.totalSpent = d.totalSpent;
    this.pendingAmount = d.pendingAmount;
    this.nextPaymentDate = new Date(d.nextPaymentDate);
    this.nextPaymentAmount = d.nextPaymentAmount;
    this.activeSponsorships = d.activeSponsorships;
    this.averageMonthlySpend = d.averageMonthlySpend;
  }

  get formattedTotalSpent(): string {
    return `€${this.totalSpent.toLocaleString('de-DE')}`;
  }

  get formattedPendingAmount(): string {
    return `€${this.pendingAmount.toLocaleString('de-DE', { minimumFractionDigits: 2 })}`;
  }

  get formattedNextPaymentAmount(): string {
    return `€${this.nextPaymentAmount.toLocaleString('de-DE', { minimumFractionDigits: 2 })}`;
  }

  get formattedAverageMonthlySpend(): string {
    return `€${this.averageMonthlySpend.toLocaleString('de-DE')}`;
  }

  get formattedNextPaymentDate(): string {
    return this.nextPaymentDate.toLocaleDateString('en-US', { month: 'short', day: 'numeric' });
  }
}