import type { TenantPackageSummary } from '../api';

export type PackageUsageMetricKey = 'events' | 'guests' | 'photos' | 'gallery';

export type PackageUsageMetric = {
  key: PackageUsageMetricKey;
  limit: number | null;
  used: number | null;
  remaining: number | null;
};

export type PackageUsageState = 'ok' | 'warning' | 'danger';

const toNumber = (value: unknown): number | null => {
  if (typeof value === 'number' && Number.isFinite(value)) {
    return value;
  }

  if (typeof value === 'string' && value.trim() !== '') {
    const parsed = Number(value);
    if (Number.isFinite(parsed)) {
      return parsed;
    }
  }

  return null;
};

const resolveLimitValue = (limits: Record<string, unknown> | null, key: string): number | null => {
  const value = limits ? toNumber(limits[key]) : null;
  if (value === null || value <= 0) {
    return null;
  }
  return value;
};

const resolveUsageValue = (value: unknown): number | null => {
  const normalized = toNumber(value);
  if (normalized === null || normalized < 0) {
    return null;
  }
  return normalized;
};

const deriveUsedFromRemaining = (limit: number | null, remaining: number | null): number | null => {
  if (limit === null || remaining === null) {
    return null;
  }

  return Math.max(limit - remaining, 0);
};

const deriveRemainingFromUsed = (limit: number | null, used: number | null): number | null => {
  if (limit === null || used === null) {
    return null;
  }

  return Math.max(limit - used, 0);
};

const normalizeCount = (value: number | null, precision: 'round' | 'floor' = 'round'): number | null => {
  if (value === null) {
    return null;
  }

  const safe = Number.isFinite(value) ? value : null;
  if (safe === null) {
    return null;
  }

  return Math.max(0, precision === 'floor' ? Math.floor(safe) : Math.round(safe));
};

export const buildPackageUsageMetrics = (pkg: TenantPackageSummary): PackageUsageMetric[] => {
  const limits = pkg.package_limits ?? {};

  const eventLimit = resolveLimitValue(limits, 'max_events_per_year');
  const eventRemaining = resolveUsageValue(pkg.remaining_events);
  const eventUsed = resolveUsageValue(pkg.used_events) ?? deriveUsedFromRemaining(eventLimit, eventRemaining);
  const resolvedEventRemaining = eventRemaining ?? deriveRemainingFromUsed(eventLimit, eventUsed);

  const guestLimit = resolveLimitValue(limits, 'max_guests');
  const guestRemaining = resolveUsageValue(limits['remaining_guests']);
  const guestUsed = resolveUsageValue(limits['used_guests']) ?? deriveUsedFromRemaining(guestLimit, guestRemaining);
  const resolvedGuestRemaining = guestRemaining ?? deriveRemainingFromUsed(guestLimit, guestUsed);

  const photoLimit = resolveLimitValue(limits, 'max_photos');
  const photoRemaining = resolveUsageValue(limits['remaining_photos']);
  const photoUsed = resolveUsageValue(limits['used_photos']) ?? deriveUsedFromRemaining(photoLimit, photoRemaining);
  const resolvedPhotoRemaining = photoRemaining ?? deriveRemainingFromUsed(photoLimit, photoUsed);

  const galleryLimit = resolveLimitValue(limits, 'gallery_days');
  const galleryRemaining = resolveUsageValue(limits['remaining_gallery_days']);
  const galleryUsed = resolveUsageValue(limits['used_gallery_days']) ?? deriveUsedFromRemaining(galleryLimit, galleryRemaining);
  const resolvedGalleryRemaining = normalizeCount(galleryRemaining ?? deriveRemainingFromUsed(galleryLimit, galleryUsed));
  const resolvedGalleryUsed = normalizeCount(galleryUsed);

  return [
    { key: 'events' as const, limit: eventLimit, used: eventUsed, remaining: resolvedEventRemaining },
    { key: 'guests' as const, limit: guestLimit, used: guestUsed, remaining: resolvedGuestRemaining },
    { key: 'photos' as const, limit: photoLimit, used: photoUsed, remaining: resolvedPhotoRemaining },
    { key: 'gallery' as const, limit: galleryLimit, used: resolvedGalleryUsed, remaining: resolvedGalleryRemaining },
  ].filter((metric) => metric.limit !== null);
};

export const formatPackageEventAllowance = (
  pkg: TenantPackageSummary,
  t: (key: string, options?: Record<string, unknown>) => string
): string => {
  if (pkg.package_type !== 'reseller') {
    return t('mobileBilling.eventPerPurchase', { defaultValue: '1 event per purchase' });
  }

  const limits = (pkg.package_limits ?? {}) as Record<string, unknown>;
  const limitMaxEvents =
    typeof limits.max_events_per_year === 'number' ? (limits.max_events_per_year as number) : null;
  const remaining = pkg.remaining_events ?? limitMaxEvents ?? 0;

  if (remaining === 0) {
    return t('mobileBilling.remainingEventsZero', { defaultValue: 'No events remaining' });
  }

  if (limitMaxEvents) {
    return t('mobileBilling.remainingEventsOf', {
      remaining,
      limit: limitMaxEvents,
      defaultValue: '{{remaining}} of {{limit}} events remaining',
    });
  }

  return t('mobileBilling.remainingEvents', {
    count: remaining,
    defaultValue: '{{count}} events',
  });
};

export const usagePercent = (metric: PackageUsageMetric): number => {
  if (!metric.limit || metric.limit <= 0) {
    return 0;
  }

  if (metric.used === null || metric.used < 0) {
    return 100;
  }

  return Math.min(100, Math.max(0, Math.round((metric.used / metric.limit) * 100)));
};

export const getUsageState = (metric: PackageUsageMetric): PackageUsageState => {
  if (!metric.limit || metric.limit <= 0) {
    return 'ok';
  }

  if (metric.remaining !== null && metric.remaining <= 0) {
    return 'danger';
  }

  if (metric.used === null) {
    return 'ok';
  }

  const percent = usagePercent(metric);
  if (percent >= 95) {
    return 'danger';
  }

  if (percent >= 80) {
    return 'warning';
  }

  return 'ok';
};
