import { describe, it, expect } from 'vitest';
import { ListingEntity } from '../entities/listing.entity';
import { ModerationService } from '../services/moderation.service';
import { Price } from '../value-objects/price.vo';

describe('ModerationService', () => {
  const service = new ModerationService();

  const makeListingInReview = () => {
    const price = Price.create(5_000_000_000n).unwrap();
    const listing = ListingEntity.createNew(
      'listing-1',
      'property-1',
      'seller-1',
      'SALE',
      price,
      100,
      'agent-1',
    );
    listing.submitForReview();
    listing.clearDomainEvents();
    return listing;
  };

  describe('applyModeration', () => {
    it('should approve a listing', () => {
      const listing = makeListingInReview();

      service.applyModeration(listing, { action: 'approve' });

      expect(listing.status).toBe('ACTIVE');
      expect(listing.publishedAt).toBeTruthy();
    });

    it('should reject a listing with default notes', () => {
      const listing = makeListingInReview();

      service.applyModeration(listing, { action: 'reject' });

      expect(listing.status).toBe('REJECTED');
      expect(listing.moderationNotes).toBe('Bị từ chối bởi moderator');
    });

    it('should reject a listing with custom notes', () => {
      const listing = makeListingInReview();

      service.applyModeration(listing, {
        action: 'reject',
        notes: 'Ảnh không rõ ràng',
      });

      expect(listing.status).toBe('REJECTED');
      expect(listing.moderationNotes).toBe('Ảnh không rõ ràng');
    });

    it('should set moderation score when provided on approve', () => {
      const listing = makeListingInReview();

      service.applyModeration(listing, {
        action: 'approve',
        moderationScore: 95,
        notes: 'Tin đăng chất lượng',
      });

      expect(listing.status).toBe('ACTIVE');
      expect(listing.moderationScore).toBe(95);
      expect(listing.moderationNotes).toBe('Tin đăng chất lượng');
    });

    it('should set moderation score when provided on reject', () => {
      const listing = makeListingInReview();

      service.applyModeration(listing, {
        action: 'reject',
        moderationScore: 20,
        notes: 'Nội dung vi phạm',
      });

      expect(listing.status).toBe('REJECTED');
      expect(listing.moderationScore).toBe(20);
    });
  });

  describe('applyStatusTransition', () => {
    it('should reject with moderation notes', () => {
      const listing = makeListingInReview();

      service.applyStatusTransition(listing, 'REJECTED', 'Vi phạm chính sách');

      expect(listing.status).toBe('REJECTED');
      expect(listing.moderationNotes).toBe('Vi phạm chính sách');
    });

    it('should approve a PENDING_REVIEW listing transitioning to ACTIVE', () => {
      const listing = makeListingInReview();

      service.applyStatusTransition(listing, 'ACTIVE');

      expect(listing.status).toBe('ACTIVE');
      expect(listing.publishedAt).toBeTruthy();
    });

    it('should use generic transitionTo for non-moderation transitions', () => {
      const price = Price.create(5_000_000_000n).unwrap();
      const listing = ListingEntity.createNew(
        'listing-2',
        'property-2',
        'seller-2',
        'SALE',
        price,
        100,
      );
      listing.submitForReview();
      listing.approve();
      listing.clearDomainEvents();

      service.applyStatusTransition(listing, 'SOLD');

      expect(listing.status).toBe('SOLD');
    });

    it('should use generic transitionTo for REJECTED without notes', () => {
      const listing = makeListingInReview();

      // REJECTED without moderationNotes falls into the generic transitionTo branch
      service.applyStatusTransition(listing, 'REJECTED');

      expect(listing.status).toBe('REJECTED');
    });
  });
});
