import { Injectable, Logger, NotFoundException, HttpException, HttpStatus } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { KitsConfig } from '../../entities/kits-config.entity';
import { InstancesService } from '../instances/instances.service';
import { CreateKitsConfigDto } from './dto/create-kits-config.dto';
import { UpdateKitsConfigDto } from './dto/update-kits-config.dto';

@Injectable()
export class KitsService {
  private readonly logger = new Logger(KitsService.name);

  constructor(
    @InjectRepository(KitsConfig)
    private readonly kitsRepo: Repository<KitsConfig>,
    private readonly instancesService: InstancesService,
  ) {}

  /** List configs for a license (summaries — no JSONB) */
  async getConfigs(licenseId: string) {
    const configs = await this.kitsRepo.find({
      where: { license_id: licenseId },
      select: ['id', 'config_name', 'description', 'is_active', 'created_at', 'updated_at'],
      order: { created_at: 'DESC' },
    });
    return { configs };
  }

  /** Get full config with JSONB data */
  async getConfig(licenseId: string, configId: string) {
    const config = await this.kitsRepo.findOne({
      where: { id: configId, license_id: licenseId },
    });
    if (!config) throw new NotFoundException('Kits config not found');
    return { config };
  }

  /** Create a new config */
  async createConfig(licenseId: string, dto: CreateKitsConfigDto) {
    const config = this.kitsRepo.create({
      license_id: licenseId,
      config_name: dto.config_name,
      description: dto.description || null,
      config_data: dto.config_data || {},
    });
    const saved = await this.kitsRepo.save(config);
    return { config: saved };
  }

  /** Update an existing config */
  async updateConfig(licenseId: string, configId: string, dto: UpdateKitsConfigDto) {
    const config = await this.kitsRepo.findOne({
      where: { id: configId, license_id: licenseId },
    });
    if (!config) throw new NotFoundException('Kits config not found');

    if (dto.config_name !== undefined) config.config_name = dto.config_name;
    if (dto.description !== undefined) config.description = dto.description;
    if (dto.config_data !== undefined) config.config_data = dto.config_data;
    if (dto.is_active !== undefined) config.is_active = dto.is_active;
    config.updated_at = new Date();

    const saved = await this.kitsRepo.save(config);
    return { config: saved };
  }

  /** Delete a config */
  async deleteConfig(licenseId: string, configId: string) {
    const result = await this.kitsRepo.delete({ id: configId, license_id: licenseId });
    if (result.affected === 0) throw new NotFoundException('Kits config not found');
    return { deleted: true };
  }

  /** Deploy config to game server via NATS */
  async applyToServer(licenseId: string, configId: string) {
    const config = await this.kitsRepo.findOne({
      where: { id: configId, license_id: licenseId },
    });
    if (!config) throw new NotFoundException('Kits config not found');

    const jsonString = JSON.stringify(config.config_data, null, 2);

    try {
      // Write Kits.json via Rust agent
      await this.instancesService.writeFileForLicense(
        licenseId,
        'oxide/config/Kits.json',
        jsonString,
      );

      // Reload Kits plugin via RCON
      await this.instancesService.rconForLicense(licenseId, 'oxide.reload Kits');

      // Mark this config as active, deactivate others
      await this.kitsRepo.update({ license_id: licenseId }, { is_active: false });
      await this.kitsRepo.update(
        { id: configId, license_id: licenseId },
        { is_active: true, updated_at: new Date() },
      );

      return {
        success: true,
        message: `Config "${config.config_name}" deployed to server`,
        config_name: config.config_name,
      };
    } catch (error) {
      this.logger.error(`Failed to deploy kits config: ${(error as Error).message}`);
      throw new HttpException(
        'Failed to deploy kits config — agent may be offline',
        HttpStatus.SERVICE_UNAVAILABLE,
      );
    }
  }

  /** Import Kits.json from game server via NATS */
  async importFromServer(licenseId: string, configName: string, description?: string) {
    try {
      // Read Kits.json from server via Rust agent
      const result = await this.instancesService.readFileForLicense(
        licenseId,
        'oxide/config/Kits.json',
      );

      if (!result) {
        throw new HttpException(
          'No response from agent — it may be offline',
          HttpStatus.SERVICE_UNAVAILABLE,
        );
      }

      // Parse the response content as JSON
      const responseData = (result as any).content;
      let configData: Record<string, any>;

      if (typeof responseData === 'string') {
        configData = JSON.parse(responseData);
      } else if (typeof responseData === 'object') {
        configData = responseData;
      } else {
        throw new HttpException(
          'Unexpected response format from agent',
          HttpStatus.BAD_GATEWAY,
        );
      }

      // Create new kits config row
      const config = this.kitsRepo.create({
        license_id: licenseId,
        config_name: configName,
        description: description || 'Imported from server',
        config_data: configData,
      });
      const saved = await this.kitsRepo.save(config);

      return { config: saved };
    } catch (error) {
      if (error instanceof HttpException) throw error;
      this.logger.error(`Failed to import kits config from server: ${(error as Error).message}`);
      throw new HttpException(
        'Failed to import kits config — agent may be offline',
        HttpStatus.SERVICE_UNAVAILABLE,
      );
    }
  }
}
