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

import {
  serverPropertiesSchema,
  updateServerPropertiesSchema,
  type ServerPropertiesResponse,
  type UpdateServerProperties,
} from '@hexahost/contracts';

import { AuditService } from '../../auth/audit.service';
import { PrismaService } from '../../prisma/prisma.service';
import { FilesService } from '../files/files.service';
import { findOwnedServer } from '../shared/server-ownership.util';

import {
  PROPERTIES_FILE,
  parsePropertiesFile,
  serializePropertiesFile,
} from './server-properties.util';

@Injectable()
export class PropertiesService {
  constructor(
    private readonly prisma: PrismaService,
    private readonly filesService: FilesService,
    private readonly auditService: AuditService,
  ) {}

  async getProperties(
    userId: string,
    serverId: string,
  ): Promise<ServerPropertiesResponse> {
    await findOwnedServer(this.prisma, userId, serverId);

    const file = await this.filesService.readFile(
      userId,
      serverId,
      PROPERTIES_FILE,
    );

    const parsed = parsePropertiesFile(file.content);
    const properties = serverPropertiesSchema.parse(parsed);

    return {
      properties,
      raw: file.content,
    };
  }

  async updateProperties(
    userId: string,
    serverId: string,
    patch: UpdateServerProperties,
  ): Promise<ServerPropertiesResponse> {
    await findOwnedServer(this.prisma, userId, serverId);

    const validatedPatch = updateServerPropertiesSchema.parse(patch);
    const current = await this.filesService.readFile(
      userId,
      serverId,
      PROPERTIES_FILE,
    );

    const merged = {
      ...parsePropertiesFile(current.content),
      ...validatedPatch,
    };

    const properties = serverPropertiesSchema.parse(merged);
    const raw = serializePropertiesFile(properties, current.content);

    await this.filesService.writeFile(userId, serverId, {
      path: PROPERTIES_FILE,
      content: raw,
      encoding: 'utf-8',
    });

    await this.auditService.record({
      action: 'server.properties.update',
      userId,
      entityType: 'game_server',
      entityId: serverId,
      metadata: { keys: Object.keys(validatedPatch) },
    });

    return { properties, raw };
  }
}
