import { BadRequestException, Injectable } from '@nestjs/common';
import type { GameServer } from '@hexahost/database';

type GameServerStatus = GameServer['status'];

const ALLOWED_TRANSITIONS: Record<GameServerStatus, GameServerStatus[]> = {
  DRAFT: ['PROVISIONING', 'DELETING'],
  PROVISIONING: ['INSTALLING', 'ERROR', 'DELETING'],
  INSTALLING: ['STOPPED', 'ERROR', 'DELETING'],
  STOPPED: ['STARTING', 'PROVISIONING', 'DELETING'],
  STARTING: ['RUNNING', 'STOPPED', 'ERROR', 'DELETING'],
  RUNNING: ['STOPPING', 'ERROR', 'DELETING'],
  STOPPING: ['STOPPED', 'ERROR', 'DELETING'],
  ERROR: ['STOPPED', 'STARTING', 'PROVISIONING', 'DELETING'],
  DELETING: ['DELETED'],
  DELETED: [],
};

const IN_PROGRESS_STATUSES: GameServerStatus[] = [
  'PROVISIONING',
  'INSTALLING',
  'STARTING',
  'STOPPING',
  'DELETING',
];

@Injectable()
export class ServerStateService {
  assertTransition(
    fromStatus: GameServerStatus,
    toStatus: GameServerStatus,
  ): void {
    const allowed = ALLOWED_TRANSITIONS[fromStatus];

    if (!allowed.includes(toStatus)) {
      throw new BadRequestException(
        `Invalid state transition from ${fromStatus} to ${toStatus}`,
      );
    }
  }

  assertNotInProgress(status: GameServerStatus): void {
    if (IN_PROGRESS_STATUSES.includes(status)) {
      throw new BadRequestException('Server operation already in progress');
    }
  }

  resolveStartTarget(status: GameServerStatus): GameServerStatus {
    switch (status) {
      case 'DRAFT':
      case 'ERROR':
        return 'PROVISIONING';
      case 'STOPPED':
        return 'STARTING';
      default:
        throw new BadRequestException(
          `Cannot start server while in status ${status}`,
        );
    }
  }

  resolveStopTarget(status: GameServerStatus): GameServerStatus {
    if (status !== 'RUNNING') {
      throw new BadRequestException(
        `Cannot stop server while in status ${status}`,
      );
    }

    return 'STOPPING';
  }
}
