import { describe, it, expect } from 'vitest';
import {
  getOverQuotaResourceIds,
  getOverQuotaServiceIds,
  isResourceOverQuota,
  isServiceOverQuota,
} from '../quotaUtils';
import { Resource, Service, QuotaOverage } from '../../types';

// Helper to create mock resources
const createResource = (id: string, createdAt: string, isArchived = false): Resource => ({
  id,
  name: `Resource ${id}`,
  type: 'STAFF',
  is_archived_by_quota: isArchived,
  created_at: createdAt,
} as Resource);

// Helper to create mock services
const createService = (id: string, createdAt: string, isArchived = false): Service => ({
  id,
  name: `Service ${id}`,
  is_archived_by_quota: isArchived,
  created_at: createdAt,
} as Service);

// Helper to create quota overage
const createOverage = (quotaType: string, amount: number): QuotaOverage => ({
  id: 1,
  quota_type: quotaType,
  overage_amount: amount,
  grace_period_ends_at: '2024-12-31T00:00:00Z',
  will_auto_archive: true,
} as QuotaOverage);

describe('quotaUtils', () => {
  describe('getOverQuotaResourceIds', () => {
    it('returns empty set when no overages', () => {
      const resources = [createResource('1', '2024-01-01')];
      const result = getOverQuotaResourceIds(resources, []);
      expect(result.size).toBe(0);
    });

    it('returns empty set when overages is undefined', () => {
      const resources = [createResource('1', '2024-01-01')];
      const result = getOverQuotaResourceIds(resources, undefined);
      expect(result.size).toBe(0);
    });

    it('returns empty set when no MAX_RESOURCES overage', () => {
      const resources = [createResource('1', '2024-01-01')];
      const overages = [createOverage('MAX_SERVICES', 1)];
      const result = getOverQuotaResourceIds(resources, overages);
      expect(result.size).toBe(0);
    });

    it('identifies oldest resources as over quota', () => {
      const resources = [
        createResource('3', '2024-03-01'), // newest
        createResource('1', '2024-01-01'), // oldest - over quota
        createResource('2', '2024-02-01'), // middle - over quota
      ];
      const overages = [createOverage('MAX_RESOURCES', 2)];

      const result = getOverQuotaResourceIds(resources, overages);

      expect(result.size).toBe(2);
      expect(result.has('1')).toBe(true); // oldest
      expect(result.has('2')).toBe(true); // second oldest
      expect(result.has('3')).toBe(false); // newest - not over quota
    });

    it('excludes already archived resources from consideration', () => {
      const resources = [
        createResource('1', '2024-01-01', true), // archived - excluded
        createResource('2', '2024-02-01'), // oldest active - over quota
        createResource('3', '2024-03-01'), // safe
      ];
      const overages = [createOverage('MAX_RESOURCES', 1)];

      const result = getOverQuotaResourceIds(resources, overages);

      expect(result.size).toBe(1);
      expect(result.has('1')).toBe(false); // already archived
      expect(result.has('2')).toBe(true); // oldest active
      expect(result.has('3')).toBe(false); // safe
    });

    it('handles overage larger than resource count', () => {
      const resources = [createResource('1', '2024-01-01')];
      const overages = [createOverage('MAX_RESOURCES', 5)];

      const result = getOverQuotaResourceIds(resources, overages);

      expect(result.size).toBe(1);
      expect(result.has('1')).toBe(true);
    });

    it('handles resources without created_at', () => {
      const resources = [
        { id: '1', name: 'R1', type: 'STAFF', is_archived_by_quota: false } as Resource,
        createResource('2', '2024-02-01'),
      ];
      const overages = [createOverage('MAX_RESOURCES', 1)];

      const result = getOverQuotaResourceIds(resources, overages);

      // Resource without date should be sorted first (timestamp 0)
      expect(result.has('1')).toBe(true);
    });
  });

  describe('getOverQuotaServiceIds', () => {
    it('returns empty set when no overages', () => {
      const services = [createService('1', '2024-01-01')];
      const result = getOverQuotaServiceIds(services, []);
      expect(result.size).toBe(0);
    });

    it('returns empty set when no MAX_SERVICES overage', () => {
      const services = [createService('1', '2024-01-01')];
      const overages = [createOverage('MAX_RESOURCES', 1)];
      const result = getOverQuotaServiceIds(services, overages);
      expect(result.size).toBe(0);
    });

    it('identifies oldest services as over quota', () => {
      const services = [
        createService('3', '2024-03-01'),
        createService('1', '2024-01-01'),
        createService('2', '2024-02-01'),
      ];
      const overages = [createOverage('MAX_SERVICES', 2)];

      const result = getOverQuotaServiceIds(services, overages);

      expect(result.size).toBe(2);
      expect(result.has('1')).toBe(true);
      expect(result.has('2')).toBe(true);
      expect(result.has('3')).toBe(false);
    });

    it('excludes already archived services', () => {
      const services = [
        createService('1', '2024-01-01', true),
        createService('2', '2024-02-01'),
        createService('3', '2024-03-01'),
      ];
      const overages = [createOverage('MAX_SERVICES', 1)];

      const result = getOverQuotaServiceIds(services, overages);

      expect(result.has('1')).toBe(false);
      expect(result.has('2')).toBe(true);
    });
  });

  describe('isResourceOverQuota', () => {
    it('returns true for over-quota resource', () => {
      const resources = [
        createResource('1', '2024-01-01'),
        createResource('2', '2024-02-01'),
      ];
      const overages = [createOverage('MAX_RESOURCES', 1)];

      expect(isResourceOverQuota('1', resources, overages)).toBe(true);
    });

    it('returns false for safe resource', () => {
      const resources = [
        createResource('1', '2024-01-01'),
        createResource('2', '2024-02-01'),
      ];
      const overages = [createOverage('MAX_RESOURCES', 1)];

      expect(isResourceOverQuota('2', resources, overages)).toBe(false);
    });

    it('returns false when no overages', () => {
      const resources = [createResource('1', '2024-01-01')];
      expect(isResourceOverQuota('1', resources, undefined)).toBe(false);
    });
  });

  describe('isServiceOverQuota', () => {
    it('returns true for over-quota service', () => {
      const services = [
        createService('1', '2024-01-01'),
        createService('2', '2024-02-01'),
      ];
      const overages = [createOverage('MAX_SERVICES', 1)];

      expect(isServiceOverQuota('1', services, overages)).toBe(true);
    });

    it('returns false for safe service', () => {
      const services = [
        createService('1', '2024-01-01'),
        createService('2', '2024-02-01'),
      ];
      const overages = [createOverage('MAX_SERVICES', 1)];

      expect(isServiceOverQuota('2', services, overages)).toBe(false);
    });

    it('returns false when no overages', () => {
      const services = [createService('1', '2024-01-01')];
      expect(isServiceOverQuota('1', services, [])).toBe(false);
    });
  });
});
