import type { PrismaClient } from '@prisma/client';
import { Decimal } from '@prisma/client/runtime/library';
import {
  WC2026_LEAGUE_CODE,
  WC2026_OUTRIGHT_TEAMS,
  type Wc2026OutrightTeam,
} from './wc2026-outright-teams';

const PLACEHOLDER_TEAM_CODE = 'OUT';

const CANONICAL_CODES = new Set(WC2026_OUTRIGHT_TEAMS.map((t) => t.code));

export type Wc2026OutrightSyncOptions = {
  /** true：赔率/队名/排序与 wc2026-outright-teams.ts 完全一致，并关闭不在表内的选项 */
  forceCanonical?: boolean;
};

function oddsEqual(a: Decimal | number, b: number) {
  return Number(a) === b;
}

async function upsertTeamTranslations(
  prisma: PrismaClient,
  teamId: bigint,
  names: Wc2026OutrightTeam['names'],
) {
  for (const [locale, value] of Object.entries(names)) {
    await prisma.entityTranslation.upsert({
      where: {
        entityType_entityId_locale_fieldName: {
          entityType: 'TEAM',
          entityId: teamId,
          locale,
          fieldName: 'name',
        },
      },
      create: {
        entityType: 'TEAM',
        entityId: teamId,
        locale,
        fieldName: 'name',
        value,
      },
      update: { value },
    });
  }
}

async function upsertTeam(prisma: PrismaClient, entry: Wc2026OutrightTeam) {
  const team = await prisma.team.upsert({
    where: { code: entry.code },
    create: { code: entry.code },
    update: {},
  });
  await upsertTeamTranslations(prisma, team.id, entry.names);
  return team;
}

/** 确保 WC2026 夺冠盘存在；forceCanonical 时与基准表完全一致 */
export async function syncWc2026OutrightMarket(
  prisma: PrismaClient,
  options: Wc2026OutrightSyncOptions = {},
) {
  const forceCanonical = options.forceCanonical ?? false;
  const league = await prisma.league.findUnique({ where: { code: WC2026_LEAGUE_CODE } });
  if (!league) {
    throw new Error(`League ${WC2026_LEAGUE_CODE} not found — run seedCatalog first`);
  }

  const placeholder = await upsertTeam(prisma, {
    rank: 0,
    code: PLACEHOLDER_TEAM_CODE,
    names: { 'zh-CN': '冠军盘', 'en-US': 'Outright' },
    defaultOdds: 1,
  });

  for (const entry of WC2026_OUTRIGHT_TEAMS) {
    await upsertTeam(prisma, entry);
  }

  let match = await prisma.match.findFirst({
    where: { leagueId: league.id, isOutright: true, deletedAt: null },
  });
  if (!match) {
    match = await prisma.match.create({
      data: {
        leagueId: league.id,
        homeTeamId: placeholder.id,
        awayTeamId: placeholder.id,
        isOutright: true,
        matchName: '2026 FIFA World Cup Winner',
        startTime: new Date('2027-07-01T00:00:00Z'),
        status: 'PUBLISHED',
        publishTime: new Date(),
        isHot: false,
        displayOrder: 0,
      },
    });
  } else {
    const shouldPublish =
      match.status === 'DRAFT' || match.status === 'SETTLED' || match.status === 'CLOSED';
    if (match.isHot || shouldPublish) {
      const updateData: {
        isHot: boolean;
        status?: string;
        publishTime?: Date;
        closeTime?: null;
      } = { isHot: false };
      if (shouldPublish) {
        updateData.status = 'PUBLISHED';
        updateData.publishTime = match.publishTime ?? new Date();
        updateData.closeTime = null;
      }
      match = await prisma.match.update({
        where: { id: match.id },
        data: updateData,
      });
    }
  }

  let market = await prisma.market.findFirst({
    where: { matchId: match.id, marketType: 'OUTRIGHT_WINNER' },
    include: { selections: true },
  });
  if (!market) {
    market = await prisma.market.create({
      data: {
        matchId: match.id,
        marketType: 'OUTRIGHT_WINNER',
        period: 'OUTRIGHT',
        allowSingle: true,
        allowParlay: false,
        sortOrder: 1,
        status: 'OPEN',
      },
      include: { selections: true },
    });
  }

  const existingByCode = new Map(market.selections.map((s) => [s.selectionCode, s]));

  for (const entry of WC2026_OUTRIGHT_TEAMS) {
    const sortOrder = entry.rank - 1;
    const existing = existingByCode.get(entry.code);
    if (!existing) {
      await prisma.marketSelection.create({
        data: {
          marketId: market.id,
          selectionCode: entry.code,
          selectionName: entry.names['zh-CN'],
          odds: entry.defaultOdds,
          sortOrder,
          status: 'OPEN',
        },
      });
      continue;
    }

    const updateData: {
      selectionName: string;
      sortOrder: number;
      status: string;
      odds?: number;
      oddsVersion?: bigint;
    } = {
      selectionName: entry.names['zh-CN'],
      sortOrder,
      status: 'OPEN',
    };

    if (forceCanonical && !oddsEqual(existing.odds, entry.defaultOdds)) {
      updateData.odds = entry.defaultOdds;
      updateData.oddsVersion = existing.oddsVersion + BigInt(1);
    }

    await prisma.marketSelection.update({
      where: { id: existing.id },
      data: updateData,
    });
  }

  if (forceCanonical) {
    for (const sel of market.selections) {
      if (CANONICAL_CODES.has(sel.selectionCode)) continue;
      if (sel.selectionCode === PLACEHOLDER_TEAM_CODE) continue;
      await prisma.marketSelection.update({
        where: { id: sel.id },
        data: { status: 'CLOSED' },
      });
    }
  }

  return { matchId: match.id, marketId: market.id };
}
