import { type PrismaClient, type McpTemplate, Prisma } from '@prisma/client';
import type { CreateTemplateInput, UpdateTemplateInput } from '../validation/template.schema.js';

export interface ITemplateRepository {
  findAll(): Promise<McpTemplate[]>;
  findById(id: string): Promise<McpTemplate | null>;
  findByName(name: string): Promise<McpTemplate | null>;
  search(pattern: string): Promise<McpTemplate[]>;
  create(data: CreateTemplateInput): Promise<McpTemplate>;
  update(id: string, data: UpdateTemplateInput): Promise<McpTemplate>;
  delete(id: string): Promise<void>;
}

export class TemplateRepository implements ITemplateRepository {
  constructor(private readonly prisma: PrismaClient) {}

  async findAll(): Promise<McpTemplate[]> {
    return this.prisma.mcpTemplate.findMany({ orderBy: { name: 'asc' } });
  }

  async findById(id: string): Promise<McpTemplate | null> {
    return this.prisma.mcpTemplate.findUnique({ where: { id } });
  }

  async findByName(name: string): Promise<McpTemplate | null> {
    return this.prisma.mcpTemplate.findUnique({ where: { name } });
  }

  async search(pattern: string): Promise<McpTemplate[]> {
    // Convert glob * to SQL %
    const sqlPattern = pattern.replace(/\*/g, '%');
    return this.prisma.mcpTemplate.findMany({
      where: { name: { contains: sqlPattern.replace(/%/g, ''), mode: 'insensitive' } },
      orderBy: { name: 'asc' },
    });
  }

  async create(data: CreateTemplateInput): Promise<McpTemplate> {
    return this.prisma.mcpTemplate.create({
      data: {
        name: data.name,
        version: data.version,
        description: data.description,
        packageName: data.packageName ?? null,
        runtime: data.runtime ?? null,
        dockerImage: data.dockerImage ?? null,
        transport: data.transport,
        repositoryUrl: data.repositoryUrl ?? null,
        externalUrl: data.externalUrl ?? null,
        command: (data.command ?? Prisma.JsonNull) as Prisma.InputJsonValue,
        containerPort: data.containerPort ?? null,
        replicas: data.replicas,
        env: (data.env ?? []) as unknown as Prisma.InputJsonValue,
        healthCheck: (data.healthCheck ?? Prisma.JsonNull) as Prisma.InputJsonValue,
      },
    });
  }

  async update(id: string, data: UpdateTemplateInput): Promise<McpTemplate> {
    const updateData: Record<string, unknown> = {};
    if (data.version !== undefined) updateData.version = data.version;
    if (data.description !== undefined) updateData.description = data.description;
    if (data.packageName !== undefined) updateData.packageName = data.packageName;
    if (data.runtime !== undefined) updateData.runtime = data.runtime;
    if (data.dockerImage !== undefined) updateData.dockerImage = data.dockerImage;
    if (data.transport !== undefined) updateData.transport = data.transport;
    if (data.repositoryUrl !== undefined) updateData.repositoryUrl = data.repositoryUrl;
    if (data.externalUrl !== undefined) updateData.externalUrl = data.externalUrl;
    if (data.command !== undefined) updateData.command = (data.command ?? Prisma.JsonNull) as Prisma.InputJsonValue;
    if (data.containerPort !== undefined) updateData.containerPort = data.containerPort;
    if (data.replicas !== undefined) updateData.replicas = data.replicas;
    if (data.env !== undefined) updateData.env = (data.env ?? []) as Prisma.InputJsonValue;
    if (data.healthCheck !== undefined) updateData.healthCheck = (data.healthCheck ?? Prisma.JsonNull) as Prisma.InputJsonValue;

    return this.prisma.mcpTemplate.update({
      where: { id },
      data: updateData,
    });
  }

  async delete(id: string): Promise<void> {
    await this.prisma.mcpTemplate.delete({ where: { id } });
  }
}
