import type { PrismaClient, Personality, PersonalityPrompt, Prompt } from '@prisma/client';

export interface PersonalityCreateInput {
  name: string;
  description?: string;
  agentId: string;
  priority?: number;
}

export interface PersonalityUpdateInput {
  description?: string;
  priority?: number;
}

export interface IPersonalityRepository {
  findAll(): Promise<Personality[]>;
  findByAgent(agentId: string): Promise<Personality[]>;
  findById(id: string): Promise<Personality | null>;
  findByNameAndAgent(name: string, agentId: string): Promise<Personality | null>;
  create(data: PersonalityCreateInput): Promise<Personality>;
  update(id: string, data: PersonalityUpdateInput): Promise<Personality>;
  delete(id: string): Promise<void>;
  listPrompts(personalityId: string): Promise<Array<PersonalityPrompt & { prompt: Prompt }>>;
  attachPrompt(personalityId: string, promptId: string, priority?: number): Promise<PersonalityPrompt>;
  detachPrompt(personalityId: string, promptId: string): Promise<void>;
  findBinding(personalityId: string, promptId: string): Promise<PersonalityPrompt | null>;
}

export class PersonalityRepository implements IPersonalityRepository {
  constructor(private readonly prisma: PrismaClient) {}

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

  async findByAgent(agentId: string): Promise<Personality[]> {
    return this.prisma.personality.findMany({
      where: { agentId },
      orderBy: { name: 'asc' },
    });
  }

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

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

  async create(data: PersonalityCreateInput): Promise<Personality> {
    return this.prisma.personality.create({
      data: {
        name: data.name,
        description: data.description ?? '',
        agentId: data.agentId,
        priority: data.priority ?? 5,
      },
    });
  }

  async update(id: string, data: PersonalityUpdateInput): Promise<Personality> {
    return this.prisma.personality.update({ where: { id }, data });
  }

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

  async listPrompts(personalityId: string): Promise<Array<PersonalityPrompt & { prompt: Prompt }>> {
    return this.prisma.personalityPrompt.findMany({
      where: { personalityId },
      include: { prompt: true },
      orderBy: { priority: 'desc' },
    });
  }

  async attachPrompt(personalityId: string, promptId: string, priority?: number): Promise<PersonalityPrompt> {
    return this.prisma.personalityPrompt.create({
      data: {
        personalityId,
        promptId,
        priority: priority ?? 5,
      },
    });
  }

  async detachPrompt(personalityId: string, promptId: string): Promise<void> {
    await this.prisma.personalityPrompt.delete({
      where: { personalityId_promptId: { personalityId, promptId } },
    });
  }

  async findBinding(personalityId: string, promptId: string): Promise<PersonalityPrompt | null> {
    return this.prisma.personalityPrompt.findUnique({
      where: { personalityId_promptId: { personalityId, promptId } },
    });
  }
}
