import type { Secret } from '@prisma/client';
import type { ISecretRepository } from '../repositories/interfaces.js';
import { CreateSecretSchema, UpdateSecretSchema } from '../validation/secret.schema.js';
import { NotFoundError, ConflictError } from './mcp-server.service.js';

export class SecretService {
  constructor(private readonly repo: ISecretRepository) {}

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

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

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

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

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

    return this.repo.create(data);
  }

  async update(id: string, input: unknown): Promise<Secret> {
    const data = UpdateSecretSchema.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<Secret> {
    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<ISecretRepository['update']>[1]);
    }
    return this.repo.create(data as Parameters<ISecretRepository['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);
  }
}
