// src/server/features/notes/db/repository/layout.ts
// Layout functions for managing note positions and viewing states

import crypto from 'node:crypto';
import { db } from '@serverShared/db/client';
import { noteLayouts } from '../note_layouts.table';
import { eq, and } from 'drizzle-orm';
import { dayjs } from '@serverShared/lib/dayjs';
import { loggerService } from '@serverShared/lib/logger';

const notesLogger = loggerService.get('HTTP').child({ module: 'notes-repo-layout' });
const logger = loggerService.get('DB').child({ module: 'notes-repo-layout' });

/**
 * Get current personal layout for a user and note
 */
export async function findLayout(noteId: string, userId: string) {
  const result = await db
    .select({
      column: noteLayouts.column,
      positionY: noteLayouts.positionY,
      height: noteLayouts.height,
    })
    .from(noteLayouts)
    .where(
      and(
        eq(noteLayouts.noteId, noteId),
        eq(noteLayouts.userId, userId)
      )
    )
    .limit(1);

  if (!result || result.length === 0) {
    return null;
  }

  return result[0];
}

/**
 * Update personal layout for a user and note
 */
export async function updateNoteLayout(
  noteId: string,
  userId: string,
  column: number,
  positionY: number,
  height: number,
  reminderAt?: Date | null,
  lastViewedAt?: Date | null
) {
  const values: any = {
    id: crypto.randomUUID(),
    noteId: noteId,
    userId: userId,
    column: column,
    positionY: positionY,
    height: height,
  };

  const setValues: any = {
    column: column,
    positionY: positionY,
    height: height,
  };

  // Add reminderAt if provided - Date object for Drizzle
  if (reminderAt !== undefined) {
    values.reminderAt = reminderAt;
    setValues.reminderAt = reminderAt;
  }

  // Add lastViewedAt if provided - Date object for Drizzle
  if (lastViewedAt !== undefined) {
    values.lastViewedAt = lastViewedAt;
    setValues.lastViewedAt = lastViewedAt;
  }

  await db
    .insert(noteLayouts)
    .values(values)
    .onDuplicateKeyUpdate({
      set: setValues,
    });
}

/**
 * Mark note as viewed for a user and note
 * Updates lastViewedAt (unified field for comments, priority, content)
 * Uses onDuplicateKeyUpdate to handle both insert and update cases
 * Uses deterministic UUID based on hash(noteId + userId) to prevent duplicates
 * If layout entry doesn't exist, creates it with default values: column: 1, positionY: 0, height: 220
 * Day.js Protocol: Backend uses dayjs.utc() for all date operations
 */
export async function markNoteAsViewed(noteId: string, userId: string) {
  // Deterministic UUID: hash(noteId + userId) to ensure same ID for same (noteId, userId) pair
  const hashInput = `${noteId}:${userId}`;
  const deterministicId = crypto.createHash('sha256').update(hashInput).digest('hex').substring(0, 36);

  const now = dayjs.utc().toDate();
  const values = {
    id: deterministicId,
    noteId,
    userId,
    column: 1,  // Default column
    positionY: 0,  // Default position
    height: 220,  // Default height
    lastViewedAt: now,
  };

  await db
    .insert(noteLayouts)
    .values(values)
    .onDuplicateKeyUpdate({
      set: {
        lastViewedAt: now,
      },
    });

  notesLogger.debug('[DEBUG] markNoteAsViewed: Updated layout for note', noteId, 'user', userId, 'with timestamp', now.toISOString());
}

/**
 * Hard delete all layout entries for a note
 * Used when a note is moved from active status to inactive (done/cancelled)
 *
 * @param noteId - The ID of the note whose layouts should be deleted
 */
export async function hardDeleteNoteLayouts(noteId: string): Promise<void> {
  await db
    .delete(noteLayouts)
    .where(eq(noteLayouts.noteId, noteId));
  
  logger.info(`Note ${noteId} layouts cleared (note inactivated)`);
}
