import { SubscriptionEntity } from '../entities/subscription.entity';

describe('SubscriptionEntity — lifecycle edge cases', () => {
  const makeSub = (status?: 'ACTIVE' | 'PAST_DUE' | 'CANCELLED' | 'EXPIRED') => {
    const sub = SubscriptionEntity.createNew(
      'sub-1',
      'user-1',
      'plan-1',
      'AGENT_PRO',
      new Date('2026-01-01'),
      new Date('2026-02-01'),
    );
    sub.clearDomainEvents();

    if (status === 'PAST_DUE') sub.markPastDue();
    if (status === 'CANCELLED') sub.cancel();
    if (status === 'EXPIRED') sub.markExpired();

    return sub;
  };

  describe('markExpired', () => {
    it('transitions ACTIVE to EXPIRED', () => {
      const sub = makeSub('ACTIVE');
      const result = sub.markExpired();
      expect(result.isOk).toBe(true);
      expect(sub.status).toBe('EXPIRED');
    });

    it('transitions PAST_DUE to EXPIRED', () => {
      const sub = makeSub('PAST_DUE');
      const result = sub.markExpired();
      expect(result.isOk).toBe(true);
      expect(sub.status).toBe('EXPIRED');
    });

    it('returns error when marking CANCELLED as expired', () => {
      const sub = makeSub('CANCELLED');
      const result = sub.markExpired();
      expect(result.isErr).toBe(true);
      expect(result.unwrapErr().message).toContain('Không thể đánh dấu hết hạn');
    });

    it('returns error when already expired', () => {
      const sub = makeSub('EXPIRED');
      const result = sub.markExpired();
      expect(result.isErr).toBe(true);
      expect(result.unwrapErr().message).toContain('Không thể đánh dấu hết hạn');
    });
  });

  describe('markPastDue', () => {
    it('transitions ACTIVE to PAST_DUE', () => {
      const sub = makeSub('ACTIVE');
      const result = sub.markPastDue();
      expect(result.isOk).toBe(true);
      expect(sub.status).toBe('PAST_DUE');
    });

    it('returns error when marking PAST_DUE as past due again', () => {
      const sub = makeSub('PAST_DUE');
      const result = sub.markPastDue();
      expect(result.isErr).toBe(true);
      expect(result.unwrapErr().message).toContain('Không thể đánh dấu quá hạn');
    });

    it('returns error when marking CANCELLED as past due', () => {
      const sub = makeSub('CANCELLED');
      const result = sub.markPastDue();
      expect(result.isErr).toBe(true);
      expect(result.unwrapErr().message).toContain('Không thể đánh dấu quá hạn');
    });

    it('returns error when marking EXPIRED as past due', () => {
      const sub = makeSub('EXPIRED');
      const result = sub.markPastDue();
      expect(result.isErr).toBe(true);
      expect(result.unwrapErr().message).toContain('Không thể đánh dấu quá hạn');
    });
  });

  describe('renewPeriod', () => {
    it('renews from PAST_DUE back to ACTIVE with new dates', () => {
      const sub = makeSub('PAST_DUE');
      const newStart = new Date('2026-02-01');
      const newEnd = new Date('2026-03-01');

      sub.renewPeriod(newStart, newEnd);

      expect(sub.status).toBe('ACTIVE');
      expect(sub.currentPeriodStart).toEqual(newStart);
      expect(sub.currentPeriodEnd).toEqual(newEnd);
    });

    it('renews from ACTIVE (extending period)', () => {
      const sub = makeSub('ACTIVE');
      const newStart = new Date('2026-03-01');
      const newEnd = new Date('2026-04-01');

      sub.renewPeriod(newStart, newEnd);

      expect(sub.status).toBe('ACTIVE');
      expect(sub.currentPeriodStart).toEqual(newStart);
      expect(sub.currentPeriodEnd).toEqual(newEnd);
    });

    it('renews from EXPIRED back to ACTIVE', () => {
      const sub = makeSub('EXPIRED');
      const newStart = new Date('2026-04-01');
      const newEnd = new Date('2026-05-01');

      sub.renewPeriod(newStart, newEnd);

      expect(sub.status).toBe('ACTIVE');
    });

    it('renews from CANCELLED back to ACTIVE', () => {
      const sub = makeSub('CANCELLED');
      const newStart = new Date('2026-04-01');
      const newEnd = new Date('2026-05-01');

      sub.renewPeriod(newStart, newEnd);

      expect(sub.status).toBe('ACTIVE');
    });
  });

  describe('isExpired', () => {
    it('returns true when period end is in the past', () => {
      const sub = SubscriptionEntity.createNew(
        'sub-2',
        'user-1',
        'plan-1',
        'FREE',
        new Date('2020-01-01'),
        new Date('2020-02-01'),
      );
      expect(sub.isExpired()).toBe(true);
    });

    it('returns false when period end is in the future', () => {
      const sub = SubscriptionEntity.createNew(
        'sub-3',
        'user-1',
        'plan-1',
        'FREE',
        new Date('2030-01-01'),
        new Date('2030-02-01'),
      );
      expect(sub.isExpired()).toBe(false);
    });
  });

  describe('upgrade constraints', () => {
    it('returns error when upgrading from PAST_DUE', () => {
      const sub = makeSub('PAST_DUE');
      const result = sub.upgrade('plan-2', 'ENTERPRISE');
      expect(result.isErr).toBe(true);
    });

    it('returns error when upgrading from EXPIRED', () => {
      const sub = makeSub('EXPIRED');
      const result = sub.upgrade('plan-2', 'ENTERPRISE');
      expect(result.isErr).toBe(true);
    });
  });

  describe('cancel constraints', () => {
    it('cancels from PAST_DUE', () => {
      const sub = makeSub('PAST_DUE');
      sub.cancel();
      expect(sub.status).toBe('CANCELLED');
      expect(sub.cancelledAt).not.toBeNull();
    });

    it('cancels from ACTIVE', () => {
      const sub = makeSub('ACTIVE');
      sub.cancel();
      expect(sub.status).toBe('CANCELLED');
    });
  });
});
