/**
 * Drizzle Review Comment Repository Adapter
 *
 * Implements ReviewCommentRepository interface using Drizzle ORM.
 */

import { eq, asc } from 'drizzle-orm';
import { nanoid } from 'nanoid';
import type { DrizzleDatabase } from '../../index.js';
import { reviewComments, type ReviewComment } from '../../schema.js';
import type { ReviewCommentRepository, CreateReviewCommentData } from '../review-comment-repository.js';

export class DrizzleReviewCommentRepository implements ReviewCommentRepository {
  constructor(private db: DrizzleDatabase) {}

  async create(data: CreateReviewCommentData): Promise<ReviewComment> {
    const now = new Date();
    const id = nanoid();
    await this.db.insert(reviewComments).values({
      id,
      phaseId: data.phaseId,
      filePath: data.filePath,
      lineNumber: data.lineNumber,
      lineType: data.lineType,
      body: data.body,
      author: data.author ?? 'user',
      parentCommentId: data.parentCommentId ?? null,
      resolved: false,
      createdAt: now,
      updatedAt: now,
    });
    const rows = await this.db
      .select()
      .from(reviewComments)
      .where(eq(reviewComments.id, id))
      .limit(1);
    return rows[0]!;
  }

  async createReply(parentCommentId: string, body: string, author?: string): Promise<ReviewComment> {
    // Fetch parent comment to copy context fields
    const parentRows = await this.db
      .select()
      .from(reviewComments)
      .where(eq(reviewComments.id, parentCommentId))
      .limit(1);
    const parent = parentRows[0];
    if (!parent) {
      throw new Error(`Parent comment not found: ${parentCommentId}`);
    }

    const now = new Date();
    const id = nanoid();
    await this.db.insert(reviewComments).values({
      id,
      phaseId: parent.phaseId,
      filePath: parent.filePath,
      lineNumber: parent.lineNumber,
      lineType: parent.lineType,
      body,
      author: author ?? 'user',
      parentCommentId,
      resolved: false,
      createdAt: now,
      updatedAt: now,
    });
    const rows = await this.db
      .select()
      .from(reviewComments)
      .where(eq(reviewComments.id, id))
      .limit(1);
    return rows[0]!;
  }

  async findByPhaseId(phaseId: string): Promise<ReviewComment[]> {
    return this.db
      .select()
      .from(reviewComments)
      .where(eq(reviewComments.phaseId, phaseId))
      .orderBy(asc(reviewComments.createdAt));
  }

  async update(id: string, body: string): Promise<ReviewComment | null> {
    await this.db
      .update(reviewComments)
      .set({ body, updatedAt: new Date() })
      .where(eq(reviewComments.id, id));
    const rows = await this.db
      .select()
      .from(reviewComments)
      .where(eq(reviewComments.id, id))
      .limit(1);
    return rows[0] ?? null;
  }

  async resolve(id: string): Promise<ReviewComment | null> {
    await this.db
      .update(reviewComments)
      .set({ resolved: true, updatedAt: new Date() })
      .where(eq(reviewComments.id, id));
    const rows = await this.db
      .select()
      .from(reviewComments)
      .where(eq(reviewComments.id, id))
      .limit(1);
    return rows[0] ?? null;
  }

  async unresolve(id: string): Promise<ReviewComment | null> {
    await this.db
      .update(reviewComments)
      .set({ resolved: false, updatedAt: new Date() })
      .where(eq(reviewComments.id, id));
    const rows = await this.db
      .select()
      .from(reviewComments)
      .where(eq(reviewComments.id, id))
      .limit(1);
    return rows[0] ?? null;
  }

  async delete(id: string): Promise<void> {
    await this.db
      .delete(reviewComments)
      .where(eq(reviewComments.id, id));
  }
}
