import { describe, expect, it } from 'vitest';
import type { TenantPackageSummary } from '../../api';
import { buildPackageUsageMetrics, formatPackageEventAllowance, getUsageState, usagePercent } from '../billingUsage';

const basePackage: TenantPackageSummary = {
  id: 1,
  package_id: 1,
  package_name: 'Pro',
  package_type: 'reseller',
  included_package_slug: 'pro',
  active: true,
  used_events: 2,
  remaining_events: 3,
  price: 120,
  currency: 'EUR',
  purchased_at: null,
  expires_at: null,
  package_limits: {
    max_events_per_year: 5,
    max_guests: 150,
    max_photos: 1000,
    gallery_days: 90,
    remaining_gallery_days: 30,
  },
  branding_allowed: true,
  watermark_allowed: true,
  features: null,
};

describe('buildPackageUsageMetrics', () => {
  it('builds usage metrics for event, guest, and photo limits', () => {
    const metrics = buildPackageUsageMetrics(basePackage);
    const keys = metrics.map((metric) => metric.key);
    expect(keys).toEqual(['events', 'guests', 'photos', 'gallery']);

    const eventMetric = metrics.find((metric) => metric.key === 'events');
    expect(eventMetric?.used).toBe(2);
    expect(eventMetric?.limit).toBe(5);
    expect(eventMetric?.remaining).toBe(3);

    const galleryMetric = metrics.find((metric) => metric.key === 'gallery');
    expect(galleryMetric?.remaining).toBe(30);
  });

  it('derives remaining when only usage is known', () => {
    const metrics = buildPackageUsageMetrics({
      ...basePackage,
      remaining_events: null,
      package_limits: { max_events_per_year: 10, gallery_days: 60 },
      used_events: 4,
    });
    expect(metrics[0].remaining).toBe(6);
  });

  it('filters metrics without limits', () => {
    const metrics = buildPackageUsageMetrics({
      ...basePackage,
      package_limits: { max_events_per_year: 0 },
    });
    expect(metrics).toHaveLength(0);
  });
});

describe('usagePercent', () => {
  it('calculates usage percent when usage is known', () => {
    const metrics = buildPackageUsageMetrics(basePackage);
    const eventMetric = metrics.find((metric) => metric.key === 'events');
    expect(eventMetric).toBeTruthy();
    expect(usagePercent(eventMetric!)).toBe(40);
  });

  it('defaults to full bar when usage is unknown', () => {
    const metrics = buildPackageUsageMetrics({
      ...basePackage,
      used_events: NaN,
      remaining_events: null,
      package_limits: { max_events_per_year: 10 },
    });
    expect(usagePercent(metrics[0])).toBe(100);
  });
});

describe('getUsageState', () => {
  it('returns warning and danger based on thresholds', () => {
    const metrics = buildPackageUsageMetrics({
      ...basePackage,
      used_events: 8,
      remaining_events: null,
      package_limits: { max_events_per_year: 10 },
    });
    expect(getUsageState(metrics[0])).toBe('warning');
    expect(getUsageState({ ...metrics[0], used: 10, remaining: 0 })).toBe('danger');
  });
});

describe('formatPackageEventAllowance', () => {
  const t = (key: string, options?: Record<string, unknown>) => {
    if (key === 'mobileBilling.eventPerPurchase') {
      return String(options?.defaultValue ?? '1 event per purchase');
    }
    if (key === 'mobileBilling.remainingEventsZero') {
      return String(options?.defaultValue ?? 'No events remaining');
    }
    if (key === 'mobileBilling.remainingEventsOf') {
      return `${options?.remaining} of ${options?.limit} events remaining`;
    }
    if (key === 'mobileBilling.remainingEvents') {
      return `${options?.count} events`;
    }
    return key;
  };

  it('returns event-per-purchase for endcustomer packages', () => {
    const label = formatPackageEventAllowance(
      { ...basePackage, package_type: 'endcustomer', remaining_events: null },
      t
    );
    expect(label).toBe('1 event per purchase');
  });

  it('returns remaining events for reseller packages', () => {
    const label = formatPackageEventAllowance(basePackage, t);
    expect(label).toBe('3 of 5 events remaining');
  });
});
