import { Controller, Get, Post, Put, Delete, Body, Param, Query, NotFoundException, HttpException, HttpStatus } from '@nestjs/common';
import { ServerRepository } from '../../../infrastructure/repositories/server.repository';
import { Server } from '../../../domain/entities/server.entity';
import { TenantContextService } from '@it0/common';
import * as crypto from 'crypto';

@Controller('api/v1/inventory/servers')
export class ServerController {
  constructor(private readonly serverRepository: ServerRepository) {}

  private serializeServer(server: Server) {
    return {
      ...server,
      hostname: server.name,
      sshPort: server.port,
    };
  }

  @Get()
  async listServers(@Query('environment') env?: string) {
    const servers = env
      ? await this.serverRepository.findByEnvironment(env)
      : await this.serverRepository.findAll();
    return servers.map((s) => this.serializeServer(s));
  }

  @Post()
  async createServer(@Body() body: any) {
    // Quota enforcement
    const tenant = TenantContextService.getTenant();
    if (tenant && tenant.maxServers !== -1) {
      const existing = await this.serverRepository.findAll();
      if (existing.length >= tenant.maxServers) {
        throw new HttpException(
          { message: `Server quota exceeded (${existing.length}/${tenant.maxServers}). Upgrade your plan to add more servers.`, code: 'QUOTA_EXCEEDED' },
          HttpStatus.TOO_MANY_REQUESTS,
        );
      }
    }
    const server = new Server();
    server.id = crypto.randomUUID();
    server.tenantId = body.tenantId;
    server.name = body.hostname ?? body.name;
    server.host = body.host;
    server.port = body.sshPort ?? body.port ?? 22;
    server.environment = body.environment;
    server.role = body.role;
    server.clusterId = body.clusterId;
    server.sshUser = body.sshUser;
    server.credentialId = body.credentialId;
    server.networkType = body.networkType ?? 'private';
    server.jumpServerId = body.jumpServerId;
    server.sshOptions = body.sshOptions ?? {};
    server.tags = body.tags ?? {};
    server.status = 'active';
    server.description = body.description;
    server.createdAt = new Date();
    server.updatedAt = new Date();
    return this.serializeServer(await this.serverRepository.save(server));
  }

  @Get(':id')
  async getServer(@Param('id') id: string) {
    const server = await this.serverRepository.findById(id);
    if (!server) {
      throw new NotFoundException(`Server ${id} not found`);
    }
    return this.serializeServer(server);
  }

  @Put(':id')
  async updateServer(@Param('id') id: string, @Body() body: any) {
    const server = await this.serverRepository.findById(id);
    if (!server) {
      throw new NotFoundException(`Server ${id} not found`);
    }
    const { hostname, sshPort, ...rest } = body;
    if (hostname !== undefined) rest.name = hostname;
    if (sshPort !== undefined) rest.port = sshPort;
    Object.assign(server, rest);
    server.updatedAt = new Date();
    return this.serializeServer(await this.serverRepository.save(server));
  }

  @Delete(':id')
  async deleteServer(@Param('id') id: string) {
    const server = await this.serverRepository.findById(id);
    if (!server) {
      throw new NotFoundException(`Server ${id} not found`);
    }
    await this.serverRepository.remove(server);
    return { message: 'Server deleted', id };
  }
}
