import { Decimal } from '@prisma/client/runtime/library';
import { BET_LIMIT_KEYS } from '../../betting/betting-limits.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 DATABASE_PROBE_COUNT = 8;

export function createDatabaseProbes(prisma: PrismaService): SmokeTestCaseDef[] {
  return [
    {
      id: 'DB001',
      suite: 'database',
      name: '数据库连接',
      description: 'SELECT 1 探活',
      run: async () => {
        const rows = await prisma.$queryRaw<Array<{ ok: number }>>`SELECT 1 AS ok`;
        expectEqual('ping', rows[0]?.ok, 1, { query: 'SELECT 1' });
      },
    },
    {
      id: 'DB002',
      suite: 'database',
      name: '演示管理员账号',
      description: 'seed admin / Admin@123',
      run: async () => {
        const user = await prisma.user.findUnique({
          where: { username: 'admin' },
          select: { id: true, userType: true, deletedAt: true },
        });
        expectTrue('admin exists', !!user, { username: 'admin' });
        expectEqual('userType', user?.userType, 'ADMIN', { username: 'admin' });
        expectEqual('not deleted', user?.deletedAt ?? null, null, { username: 'admin' });
      },
    },
    {
      id: 'DB003',
      suite: 'database',
      name: '演示代理账号与额度',
      description: 'seed agent1 授信额度',
      run: async () => {
        const agent = await prisma.user.findUnique({
          where: { username: 'agent1' },
          select: {
            id: true,
            userType: true,
            agentProfile: { select: { creditLimit: true, level: true } },
          },
        });
        expectTrue('agent1 exists', !!agent, { username: 'agent1' });
        expectEqual('userType', agent?.userType, 'AGENT', { username: 'agent1' });
        const credit = agent?.agentProfile?.creditLimit;
        expectTrue('creditLimit > 0', !!credit && credit.gt(0), {
          username: 'agent1',
          creditLimit: credit?.toString(),
        });
      },
    },
    {
      id: 'DB004',
      suite: 'database',
      name: '演示玩家与钱包',
      description: 'seed player1 钱包余额',
      run: async () => {
        const player = await prisma.user.findUnique({
          where: { username: 'player1' },
          select: {
            id: true,
            userType: true,
            wallet: { select: { availableBalance: true, frozenBalance: true } },
          },
        });
        expectTrue('player1 exists', !!player, { username: 'player1' });
        expectEqual('userType', player?.userType, 'PLAYER', { username: 'player1' });
        expectTrue('wallet exists', !!player?.wallet, { username: 'player1' });
        expectTrue('availableBalance >= 0', !!player?.wallet && player.wallet.availableBalance.gte(0), {
          availableBalance: player?.wallet?.availableBalance.toString(),
          frozenBalance: player?.wallet?.frozenBalance.toString(),
        });
      },
    },
    {
      id: 'DB005',
      suite: 'database',
      name: '演示赛事与盘口',
      description: '至少一场 OPEN 赛事且含 FT_1X2 盘口',
      run: async () => {
        const matchCount = await prisma.match.count({
          where: { deletedAt: null, status: { in: ['OPEN', 'PUBLISHED', 'SUSPENDED', 'CLOSED'] } },
        });
        expectTrue('match count > 0', matchCount > 0, { matchCount });

        const market = await prisma.market.findFirst({
          where: {
            marketType: 'FT_1X2',
            match: { deletedAt: null, status: { in: ['OPEN', 'PUBLISHED'] } },
          },
          select: {
            id: true,
            marketType: true,
            selections: { select: { id: true, selectionCode: true, odds: true }, take: 3 },
          },
        });
        expectTrue('FT_1X2 market exists', !!market, { marketType: 'FT_1X2' });
        expectTrue('has 3 selections', (market?.selections.length ?? 0) >= 3, {
          selectionCount: market?.selections.length,
        });
      },
    },
    {
      id: 'DB006',
      suite: 'database',
      name: '投注限额配置完整',
      description: '6 项 bet.* 限额键可读',
      run: async () => {
        const keys = Object.values(BET_LIMIT_KEYS);
        for (const key of keys) {
          const row = await prisma.systemConfig.findUnique({ where: { configKey: key } });
          const value = row?.configValue ?? '(default)';
          const n = row ? Number(row.configValue) : NaN;
          const valid = !row || (Number.isFinite(n) && n >= 0);
          expectTrue(`${key} valid`, valid, { key, value });
        }
      },
    },
    {
      id: 'DB007',
      suite: 'database',
      name: '权限与角色种子',
      description: '超级管理员角色含 settings.manage',
      run: async () => {
        const role = await prisma.role.findFirst({
          where: { code: 'SUPER_ADMIN' },
          include: { permissions: { include: { permission: true } } },
        });
        expectTrue('SUPER_ADMIN role exists', !!role, { code: 'SUPER_ADMIN' });
        const codes = role?.permissions.map((rp) => rp.permission.code) ?? [];
        expectTrue('has settings.manage', codes.includes('settings.manage'), { permissions: codes });
      },
    },
    {
      id: 'DB008',
      suite: 'database',
      name: '今日注单聚合可查',
      description: 'bet 表聚合查询（只读）',
      run: async () => {
        const start = new Date();
        start.setHours(0, 0, 0, 0);
        const agg = await prisma.bet.aggregate({
          where: { placedAt: { gte: start } },
          _sum: { stake: true },
          _count: true,
        });
        expectTrue('aggregate ok', agg._count >= 0, {
          todayBetCount: agg._count,
          todayStakeSum: agg._sum.stake?.toString() ?? '0',
        });
        expectEqual('stake sum type', agg._sum.stake instanceof Decimal || agg._sum.stake == null, true, {
          stake: agg._sum.stake?.toString() ?? '0',
        });
      },
    },
  ];
}
