import { BadRequestException, Injectable } from '@nestjs/common';

import type { IdleStatusResponse } from '@hexahost/contracts';
import { parseMinecraftListOutput } from '@hexahost/metering';

import { NodeBridgeService } from '../../nodes/node-bridge.service';
import { PrismaService } from '../../prisma/prisma.service';
import { findOwnedServer } from '../shared/server-ownership.util';

@Injectable()
export class IdleService {
  constructor(
    private readonly prisma: PrismaService,
    private readonly nodeBridge: NodeBridgeService,
  ) {}

  async getIdleStatus(userId: string, serverId: string): Promise<IdleStatusResponse> {
    const server = await findOwnedServer(this.prisma, userId, serverId);

    let playerCount: number | null = null;

    if (server.status === 'RUNNING' && server.nodeId) {
      const response = await this.nodeBridge.sendAgentRequest(
        server.nodeId,
        'server.command',
        {
          serverId: server.id,
          generation: server.version,
          command: 'list',
        },
        10_000,
      );

      if (response.success) {
        const output =
          typeof response.result === 'object' &&
          response.result !== null &&
          'output' in response.result &&
          typeof (response.result as { output: unknown }).output === 'string'
            ? (response.result as { output: string }).output
            : typeof response.result === 'string'
              ? response.result
              : '';

        playerCount = parseMinecraftListOutput(output);
      }
    }

    const secondsRemaining =
      server.idleStopAt && server.idleStopAt.getTime() > Date.now()
        ? Math.ceil((server.idleStopAt.getTime() - Date.now()) / 1000)
        : null;

    return {
      enabled: server.idleShutdownEnabled,
      playerCount,
      idleStopAt: server.idleStopAt?.toISOString() ?? null,
      secondsRemaining,
      lastPlayerSeenAt: server.lastPlayerSeenAt?.toISOString() ?? null,
    };
  }

  async extendIdleCountdown(userId: string, serverId: string): Promise<IdleStatusResponse> {
    const server = await findOwnedServer(this.prisma, userId, serverId);

    if (!server.idleStopAt) {
      throw new BadRequestException('No idle shutdown countdown is active');
    }

    const extended = new Date(server.idleStopAt.getTime() + 5 * 60_000);

    await this.prisma.gameServer.update({
      where: { id: serverId },
      data: { idleStopAt: extended },
    });

    return this.getIdleStatus(userId, serverId);
  }
}
