import { Decimal } from '@prisma/client/runtime/library';
import {
  AGENT_SUSPEND_BLOCK_PLAYER_LOGIN,
  AGENT_SUSPEND_FREEZE_DIRECT_PLAYERS,
} from '../../../shared/config/system-config.service';
import type { AgentsService } from '../../agent/agents.service';
import type { PrismaService } from '../../../shared/prisma/prisma.service';
import { expectEqual, expectTrue } from './smoke-test.helpers';
import type { SmokeTestCaseDef } from './smoke-test.cases';

export const CONFIG_PROBE_COUNT = 2;

export type ConfigProbeDeps = {
  prisma: PrismaService;
  agents: AgentsService;
};

async function upsertBooleanConfig(
  prisma: PrismaService,
  key: string,
  value: boolean,
  snapshots: Array<{ key: string; value: string | null }>,
) {
  const row = await prisma.systemConfig.findUnique({ where: { configKey: key } });
  snapshots.push({ key, value: row?.configValue ?? null });
  await prisma.systemConfig.upsert({
    where: { configKey: key },
    create: {
      configKey: key,
      configValue: value ? 'true' : 'false',
      description: 'smoke config probe',
    },
    update: { configValue: value ? 'true' : 'false' },
  });
}

async function restoreConfigs(
  prisma: PrismaService,
  snapshots: Array<{ key: string; value: string | null }>,
) {
  for (const snap of snapshots) {
    if (snap.value === null) {
      await prisma.systemConfig.deleteMany({ where: { configKey: snap.key } });
    } else {
      await prisma.systemConfig.upsert({
        where: { configKey: snap.key },
        create: {
          configKey: snap.key,
          configValue: snap.value,
          description: 'smoke config restore',
        },
        update: { configValue: snap.value },
      });
    }
  }
}

export function createConfigProbes(deps: ConfigProbeDeps): SmokeTestCaseDef[] {
  return [
    {
      id: 'CFG001',
      suite: 'config',
      name: '代理停用默认：全局 freeze 级联冻结直属玩家',
      description: 'AgentsService.updateAgentAdmin 未传 flag 时读取 agent.suspend_freeze_direct_players',
      run: async () => {
        const runId = `${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
        const snapshots: Array<{ key: string; value: string | null }> = [];
        let agentId: bigint | undefined;
        let playerId: bigint | undefined;

        try {
          await upsertBooleanConfig(
            deps.prisma,
            AGENT_SUSPEND_FREEZE_DIRECT_PLAYERS,
            true,
            snapshots,
          );
          await upsertBooleanConfig(
            deps.prisma,
            AGENT_SUSPEND_BLOCK_PLAYER_LOGIN,
            false,
            snapshots,
          );

          const agent = await deps.prisma.user.create({
            data: {
              username: `smoke_cfg_ag_${runId}`,
              userType: 'AGENT',
              status: 'ACTIVE',
              auth: { create: { passwordHash: 'smoke' } },
              agentProfile: {
                create: { level: 1, creditLimit: new Decimal(10000) },
              },
            },
          });
          agentId = agent.id;
          await deps.prisma.agentClosure.create({
            data: { ancestorId: agent.id, descendantId: agent.id, depth: 0 },
          });

          const player = await deps.prisma.user.create({
            data: {
              username: `smoke_cfg_pl_${runId}`,
              userType: 'PLAYER',
              status: 'ACTIVE',
              parentId: agent.id,
              auth: { create: { passwordHash: 'smoke' } },
            },
          });
          playerId = player.id;

          await deps.agents.updateAgentAdmin(agent.id, { status: 'SUSPENDED' });

          const frozen = await deps.prisma.user.findUnique({ where: { id: player.id } });
          expectEqual('player status after suspend', frozen?.status, 'SUSPENDED');
        } finally {
          if (playerId) {
            await deps.prisma.userAuth.deleteMany({ where: { userId: playerId } });
            await deps.prisma.user.deleteMany({ where: { id: playerId } });
          }
          if (agentId) {
            await deps.prisma.agentClosure.deleteMany({
              where: { OR: [{ ancestorId: agentId }, { descendantId: agentId }] },
            });
            await deps.prisma.agentProfile.deleteMany({ where: { userId: agentId } });
            await deps.prisma.userAuth.deleteMany({ where: { userId: agentId } });
            await deps.prisma.user.deleteMany({ where: { id: agentId } });
          }
          await restoreConfigs(deps.prisma, snapshots);
        }
      },
    },
    {
      id: 'CFG002',
      suite: 'config',
      name: '代理停用默认：全局 block 禁止直属玩家登录',
      description: 'AgentsService.updateAgentAdmin 未传 flag 时写入 blockDirectPlayerLogin',
      run: async () => {
        const runId = `${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
        const snapshots: Array<{ key: string; value: string | null }> = [];
        let agentId: bigint | undefined;

        try {
          await upsertBooleanConfig(
            deps.prisma,
            AGENT_SUSPEND_FREEZE_DIRECT_PLAYERS,
            false,
            snapshots,
          );
          await upsertBooleanConfig(
            deps.prisma,
            AGENT_SUSPEND_BLOCK_PLAYER_LOGIN,
            true,
            snapshots,
          );

          const agent = await deps.prisma.user.create({
            data: {
              username: `smoke_cfg2_ag_${runId}`,
              userType: 'AGENT',
              status: 'ACTIVE',
              auth: { create: { passwordHash: 'smoke' } },
              agentProfile: {
                create: { level: 1, creditLimit: new Decimal(10000) },
              },
            },
          });
          agentId = agent.id;
          await deps.prisma.agentClosure.create({
            data: { ancestorId: agent.id, descendantId: agent.id, depth: 0 },
          });

          await deps.agents.updateAgentAdmin(agent.id, { status: 'SUSPENDED' });

          const profile = await deps.prisma.agentProfile.findUnique({
            where: { userId: agent.id },
          });
          expectTrue(
            'blockDirectPlayerLogin persisted',
            profile?.blockDirectPlayerLogin === true,
            { value: profile?.blockDirectPlayerLogin },
          );
        } finally {
          if (agentId) {
            await deps.prisma.agentClosure.deleteMany({
              where: { OR: [{ ancestorId: agentId }, { descendantId: agentId }] },
            });
            await deps.prisma.agentProfile.deleteMany({ where: { userId: agentId } });
            await deps.prisma.userAuth.deleteMany({ where: { userId: agentId } });
            await deps.prisma.user.deleteMany({ where: { id: agentId } });
          }
          await restoreConfigs(deps.prisma, snapshots);
        }
      },
    },
  ];
}
