import type { McpTemplate } from '@prisma/client';
import type { ITemplateRepository } from '../repositories/template.repository.js';
import { CreateTemplateSchema, UpdateTemplateSchema } from '../validation/template.schema.js';
import { NotFoundError, ConflictError } from './mcp-server.service.js';

export class TemplateService {
  constructor(private readonly repo: ITemplateRepository) {}

  async list(namePattern?: string): Promise<McpTemplate[]> {
    if (namePattern) {
      return this.repo.search(namePattern);
    }
    return this.repo.findAll();
  }

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

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

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

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

    return this.repo.create(data);
  }

  async update(id: string, input: unknown): Promise<McpTemplate> {
    const data = UpdateTemplateSchema.parse(input);
    await this.getById(id);
    return this.repo.update(id, data);
  }

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

  // ── Backup/restore helpers ──

  async upsertByName(data: Record<string, unknown>): Promise<McpTemplate> {
    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<ITemplateRepository['update']>[1]);
    }
    return this.repo.create(data as Parameters<ITemplateRepository['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);
  }
}
