jest.mock('@thebet365/shared', () => ({
  isPreMatchKickoff: jest.fn(() => true),
  PARLAY_MARKET_TYPES: [],
  resolveTranslationFallback: jest.fn(
    (translations: Map<string, string>, locale: string) =>
      translations.get(locale) ?? translations.get('zh-CN') ?? translations.get('en-US') ?? null,
  ),
}));

import { MatchesService } from './matches.service';

describe('MatchesService publish/unpublish', () => {
  const leagueId = BigInt(1);
  const matchId = BigInt(10);

  let prisma: {
    league: { findFirst: jest.Mock; findUniqueOrThrow: jest.Mock; update: jest.Mock };
    match: { findFirst: jest.Mock; update: jest.Mock };
    entityTranslation: { findFirst: jest.Mock; upsert: jest.Mock };
    settlementBatch: { deleteMany: jest.Mock };
  };
  let outright: { syncWithLeaguePublished: jest.Mock };
  let matchBetStats: { betStatsForMatches: jest.Mock };
  let service: MatchesService;

  beforeEach(() => {
    prisma = {
      league: {
        findFirst: jest.fn(),
        findUniqueOrThrow: jest.fn(),
        update: jest.fn(),
      },
      match: {
        findFirst: jest.fn(),
        update: jest.fn(),
      },
      entityTranslation: { findFirst: jest.fn().mockResolvedValue(null), upsert: jest.fn().mockResolvedValue({}) },
      settlementBatch: { deleteMany: jest.fn().mockResolvedValue({ count: 0 }) },
    };
    outright = { syncWithLeaguePublished: jest.fn().mockResolvedValue(undefined) };
    matchBetStats = { betStatsForMatches: jest.fn().mockResolvedValue(new Map()) };
    service = new MatchesService(prisma as never, outright as never, matchBetStats as never);
  });

  describe('updatePlatformLeague unpublish', () => {
    const baseLeague = { id: leagueId, code: 'EPL', isActive: true, logoUrl: null, displayOrder: 0 };

    beforeEach(() => {
      prisma.league.findFirst.mockResolvedValue(baseLeague);
      prisma.league.update.mockResolvedValue({});
      prisma.league.findUniqueOrThrow.mockResolvedValue({ ...baseLeague, isActive: false });
    });

    it('rejects unpublish when outright is settled', async () => {
      prisma.match.findFirst.mockResolvedValue({ status: 'SETTLED' });

      await expect(
        service.updatePlatformLeague(leagueId, {
          leagueEn: 'EPL',
          leagueZh: '英超',
          isActive: false,
        }),
      ).rejects.toMatchObject({
        response: expect.objectContaining({ code: 'LEAGUE_UNPUBLISH_SETTLED' }),
      });
      expect(prisma.league.update).not.toHaveBeenCalled();
    });

    it('allows unpublish when outright is not settled', async () => {
      prisma.match.findFirst.mockResolvedValue({ status: 'PUBLISHED' });

      const result = await service.updatePlatformLeague(leagueId, {
        leagueEn: 'EPL',
        leagueZh: '英超',
        isActive: false,
      });

      expect(prisma.league.update).toHaveBeenCalledWith({
        where: { id: leagueId },
        data: { isActive: false },
      });
      expect(result.isPublished).toBe(false);
    });
  });

  describe('unpublishMatch', () => {
    const baseMatch = {
      id: matchId,
      status: 'PUBLISHED',
      isOutright: false,
      deletedAt: null,
    };

    beforeEach(() => {
      prisma.match.findFirst.mockResolvedValue(baseMatch);
      prisma.match.update.mockResolvedValue({ ...baseMatch, status: 'DRAFT' });
    });

    it('unpublishes published fixture to draft', async () => {
      await service.unpublishMatch(matchId);

      expect(prisma.match.update).toHaveBeenCalledWith({
        where: { id: matchId },
        data: { status: 'DRAFT', closeTime: null },
      });
    });

    it('rejects unpublish when settled', async () => {
      prisma.match.findFirst.mockResolvedValue({ ...baseMatch, status: 'SETTLED' });

      await expect(service.unpublishMatch(matchId)).rejects.toMatchObject({
        response: expect.objectContaining({ code: 'MATCH_UNPUBLISH_FORBIDDEN' }),
      });
    });

    it('clears preview settlement batch when pending settlement', async () => {
      prisma.match.findFirst.mockResolvedValue({ ...baseMatch, status: 'PENDING_SETTLEMENT' });

      await service.unpublishMatch(matchId);

      expect(prisma.settlementBatch.deleteMany).toHaveBeenCalledWith({
        where: { matchId, status: 'PREVIEW' },
      });
    });
  });
});
