import type { RbacDefinition } from '@prisma/client';
import type { IRbacDefinitionRepository } from '../repositories/rbac-definition.repository.js';
import { CreateRbacDefinitionSchema, UpdateRbacDefinitionSchema } from '../validation/rbac-definition.schema.js';
import { NotFoundError, ConflictError } from './mcp-server.service.js';

export class RbacDefinitionService {
  constructor(private readonly repo: IRbacDefinitionRepository) {}

  async list(): Promise<RbacDefinition[]> {
    return this.repo.findAll();
  }

  async getById(id: string): Promise<RbacDefinition> {
    const def = await this.repo.findById(id);
    if (def === null) {
      throw new NotFoundError(`RbacDefinition not found: ${id}`);
    }
    return def;
  }

  async getByName(name: string): Promise<RbacDefinition> {
    const def = await this.repo.findByName(name);
    if (def === null) {
      throw new NotFoundError(`RbacDefinition not found: ${name}`);
    }
    return def;
  }

  async create(input: unknown): Promise<RbacDefinition> {
    const data = CreateRbacDefinitionSchema.parse(input);

    const existing = await this.repo.findByName(data.name);
    if (existing !== null) {
      throw new ConflictError(`RbacDefinition already exists: ${data.name}`);
    }

    return this.repo.create(data);
  }

  async update(id: string, input: unknown): Promise<RbacDefinition> {
    const data = UpdateRbacDefinitionSchema.parse(input);

    // Verify exists
    await this.getById(id);

    return this.repo.update(id, data);
  }

  async delete(id: string): Promise<void> {
    // Verify exists
    await this.getById(id);
    await this.repo.delete(id);
  }

  // ── Backup/restore helpers ──

  async upsertByName(data: Record<string, unknown>): Promise<RbacDefinition> {
    const name = data['name'] as string;
    const existing = await this.repo.findByName(name);
    if (existing !== null) {
      const { name: _, ...updateFields } = data;
      return this.repo.update(existing.id, updateFields as Parameters<IRbacDefinitionRepository['update']>[1]);
    }
    return this.repo.create(data as Parameters<IRbacDefinitionRepository['create']>[0]);
  }

  async deleteByName(name: string): Promise<void> {
    const existing = await this.repo.findByName(name);
    if (existing === null) return;
    await this.repo.delete(existing.id);
  }
}
