import type { PrismaClient, Prisma, Skill } from '@prisma/client';

/**
 * Skill repository — mirrors PromptRepository. Same nullable-FK
 * compound-key workaround (`projectId ?? ''`) applies, see prompt.repository.ts.
 */

export interface SkillCreateInput {
  name: string;
  content: string;
  description?: string;
  files?: Prisma.InputJsonValue;
  metadata?: Prisma.InputJsonValue;
  projectId?: string;
  agentId?: string;
  priority?: number;
  semver?: string;
}

export interface SkillUpdateInput {
  content?: string;
  description?: string;
  files?: Prisma.InputJsonValue;
  metadata?: Prisma.InputJsonValue;
  priority?: number;
  summary?: string;
  chapters?: string[];
  semver?: string;
  currentRevisionId?: string | null;
}

export interface ISkillRepository {
  findAll(projectId?: string): Promise<Skill[]>;
  findGlobal(): Promise<Skill[]>;
  findByAgent(agentId: string): Promise<Skill[]>;
  findById(id: string): Promise<Skill | null>;
  findByNameAndProject(name: string, projectId: string | null): Promise<Skill | null>;
  findByNameAndAgent(name: string, agentId: string | null): Promise<Skill | null>;
  create(data: SkillCreateInput): Promise<Skill>;
  update(id: string, data: SkillUpdateInput): Promise<Skill>;
  delete(id: string): Promise<void>;
}

export class SkillRepository implements ISkillRepository {
  constructor(private readonly prisma: PrismaClient) {}

  async findAll(projectId?: string): Promise<Skill[]> {
    const include = { project: { select: { name: true } } };
    if (projectId !== undefined) {
      // Project-scoped + globals.
      return this.prisma.skill.findMany({
        where: { OR: [{ projectId }, { projectId: null, agentId: null }] },
        include,
        orderBy: { name: 'asc' },
      });
    }
    return this.prisma.skill.findMany({ include, orderBy: { name: 'asc' } });
  }

  async findGlobal(): Promise<Skill[]> {
    return this.prisma.skill.findMany({
      where: { projectId: null, agentId: null },
      include: { project: { select: { name: true } } },
      orderBy: { name: 'asc' },
    });
  }

  async findByAgent(agentId: string): Promise<Skill[]> {
    return this.prisma.skill.findMany({
      where: { agentId },
      include: { agent: { select: { name: true } } },
      orderBy: { name: 'asc' },
    });
  }

  async findById(id: string): Promise<Skill | null> {
    return this.prisma.skill.findUnique({
      where: { id },
      include: {
        project: { select: { name: true } },
        agent: { select: { name: true } },
      },
    });
  }

  async findByNameAndProject(name: string, projectId: string | null): Promise<Skill | null> {
    return this.prisma.skill.findUnique({
      where: { name_projectId: { name, projectId: projectId ?? '' } },
    });
  }

  async findByNameAndAgent(name: string, agentId: string | null): Promise<Skill | null> {
    return this.prisma.skill.findUnique({
      where: { name_agentId: { name, agentId: agentId ?? '' } },
    });
  }

  async create(data: SkillCreateInput): Promise<Skill> {
    return this.prisma.skill.create({ data });
  }

  async update(id: string, data: SkillUpdateInput): Promise<Skill> {
    return this.prisma.skill.update({ where: { id }, data });
  }

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