import { PlantingOrder } from './planting-order.aggregate';
import { PlantingOrderStatus } from '../value-objects/planting-order-status.enum';
import { FundAllocation } from '../value-objects/fund-allocation.vo';
import { FundAllocationTargetType } from '../value-objects/fund-allocation-target-type.enum';

describe('PlantingOrder', () => {
  describe('create', () => {
    it('应该成功创建认种订单', () => {
      const order = PlantingOrder.create(BigInt(1), 5);

      expect(order.orderNo).toMatch(/^PLT/);
      expect(order.userId).toBe(BigInt(1));
      expect(order.treeCount.value).toBe(5);
      expect(order.totalAmount).toBe(5 * 2199);
      expect(order.status).toBe(PlantingOrderStatus.CREATED);
      expect(order.domainEvents.length).toBe(1);
      expect(order.domainEvents[0].type).toBe('PlantingOrderCreated');
    });

    it('应该拒绝0棵树', () => {
      expect(() => PlantingOrder.create(BigInt(1), 0)).toThrow(
        '认种数量必须大于0',
      );
    });

    it('应该拒绝负数', () => {
      expect(() => PlantingOrder.create(BigInt(1), -1)).toThrow(
        '认种数量必须大于0',
      );
    });
  });

  describe('selectProvinceCity', () => {
    it('应该成功选择省市', () => {
      const order = PlantingOrder.create(BigInt(1), 1);
      order.selectProvinceCity('440000', '广东省', '440100', '广州市');

      expect(order.provinceCitySelection).not.toBeNull();
      expect(order.provinceCitySelection?.provinceCode).toBe('440000');
      expect(order.provinceCitySelection?.cityCode).toBe('440100');
      expect(order.provinceCitySelection?.isConfirmed).toBe(false);
    });

    it('应该允许在确认前修改省市', () => {
      const order = PlantingOrder.create(BigInt(1), 1);
      order.selectProvinceCity('440000', '广东省', '440100', '广州市');
      order.selectProvinceCity('110000', '北京市', '110100', '北京市');

      expect(order.provinceCitySelection?.provinceCode).toBe('110000');
    });
  });

  describe('confirmProvinceCity', () => {
    it('应该在5秒后成功确认省市', () => {
      jest.useFakeTimers();

      const order = PlantingOrder.create(BigInt(1), 1);
      order.selectProvinceCity('440000', '广东省', '440100', '广州市');

      jest.advanceTimersByTime(5000);

      order.confirmProvinceCity();

      expect(order.status).toBe(PlantingOrderStatus.PROVINCE_CITY_CONFIRMED);
      expect(order.provinceCitySelection?.isConfirmed).toBe(true);

      jest.useRealTimers();
    });

    it('应该在5秒前拒绝确认', () => {
      const order = PlantingOrder.create(BigInt(1), 1);
      order.selectProvinceCity('440000', '广东省', '440100', '广州市');

      expect(() => order.confirmProvinceCity()).toThrow('请等待5秒确认时间');
    });

    it('应该拒绝未选择省市的确认', () => {
      const order = PlantingOrder.create(BigInt(1), 1);

      expect(() => order.confirmProvinceCity()).toThrow('请先选择省市');
    });
  });

  describe('markAsPaid', () => {
    it('应该在省市确认后成功标记为已支付', () => {
      jest.useFakeTimers();

      const order = PlantingOrder.create(BigInt(1), 1);
      order.selectProvinceCity('440000', '广东省', '440100', '广州市');
      jest.advanceTimersByTime(5000);
      order.confirmProvinceCity();

      order.markAsPaid('D25121300001');

      expect(order.status).toBe(PlantingOrderStatus.PAID);
      expect(order.paidAt).not.toBeNull();

      jest.useRealTimers();
    });

    it('应该拒绝未确认省市的支付', () => {
      const order = PlantingOrder.create(BigInt(1), 1);

      expect(() => order.markAsPaid('D25121300001')).toThrow('订单状态错误');
    });
  });

  describe('allocateFunds', () => {
    it('应该成功分配资金', () => {
      jest.useFakeTimers();

      const order = PlantingOrder.create(BigInt(1), 1);
      order.selectProvinceCity('440000', '广东省', '440100', '广州市');
      jest.advanceTimersByTime(5000);
      order.confirmProvinceCity();
      order.markAsPaid('D25121300001');

      const allocations = [
        new FundAllocation(FundAllocationTargetType.COST_ACCOUNT, 400, 'ACC1'),
        new FundAllocation(
          FundAllocationTargetType.OPERATION_ACCOUNT,
          300,
          'ACC2',
        ),
        new FundAllocation(
          FundAllocationTargetType.HEADQUARTERS_COMMUNITY,
          9,
          'ACC3',
        ),
        new FundAllocation(
          FundAllocationTargetType.REFERRAL_RIGHTS,
          500,
          'ACC4',
        ),
        new FundAllocation(
          FundAllocationTargetType.PROVINCE_AREA_RIGHTS,
          15,
          'ACC5',
        ),
        new FundAllocation(
          FundAllocationTargetType.PROVINCE_TEAM_RIGHTS,
          20,
          'ACC6',
        ),
        new FundAllocation(
          FundAllocationTargetType.CITY_AREA_RIGHTS,
          35,
          'ACC7',
        ),
        new FundAllocation(
          FundAllocationTargetType.CITY_TEAM_RIGHTS,
          40,
          'ACC8',
        ),
        new FundAllocation(
          FundAllocationTargetType.COMMUNITY_RIGHTS,
          80,
          'ACC9',
        ),
        new FundAllocation(FundAllocationTargetType.RWAD_POOL, 800, 'ACC10'),
      ];

      order.allocateFunds(allocations);

      expect(order.status).toBe(PlantingOrderStatus.FUND_ALLOCATED);
      expect(order.fundAllocations.length).toBe(10);

      jest.useRealTimers();
    });

    it('应该拒绝金额不匹配的分配', () => {
      jest.useFakeTimers();

      const order = PlantingOrder.create(BigInt(1), 1);
      order.selectProvinceCity('440000', '广东省', '440100', '广州市');
      jest.advanceTimersByTime(5000);
      order.confirmProvinceCity();
      order.markAsPaid('D25121300001');

      const allocations = [
        new FundAllocation(FundAllocationTargetType.COST_ACCOUNT, 100, 'ACC1'),
      ];

      expect(() => order.allocateFunds(allocations)).toThrow(
        '资金分配总额不匹配',
      );

      jest.useRealTimers();
    });
  });

  describe('cancel', () => {
    it('应该成功取消未支付的订单', () => {
      const order = PlantingOrder.create(BigInt(1), 1);
      order.cancel();

      expect(order.status).toBe(PlantingOrderStatus.CANCELLED);
    });

    it('应该拒绝取消已支付的订单', () => {
      jest.useFakeTimers();

      const order = PlantingOrder.create(BigInt(1), 1);
      order.selectProvinceCity('440000', '广东省', '440100', '广州市');
      jest.advanceTimersByTime(5000);
      order.confirmProvinceCity();
      order.markAsPaid('D25121300001');

      expect(() => order.cancel()).toThrow('只有未支付的订单才能取消');

      jest.useRealTimers();
    });
  });
});
