import {eq, inArray, or} from 'drizzle-orm'

import {db, schema} from '../db/client'
import {isUniqueViolation} from '../lib/sql'

// shared by db/seed.ts and routes/dev.ts so their reset/seed behavior
// can't drift; never reached in production

// deterministic handles let flows target seeded users by name; tolerate a
// handle already taken by another row (only matters in a dirtied dev db)
export const setHandle = async (userId: string, handle: string) => {
  try {
    await db
      .update(schema.users)
      .set({handle, updatedAt: new Date()})
      .where(eq(schema.users.id, userId))
  } catch (err) {
    if (!isUniqueViolation(err)) throw err
  }
}

// wipe everything the users authored or participate in. deleting crumbs,
// trails, and conversations cascades to their dependents (reminders, tags,
// trail crumbs/posts/states, messages); cross-user edges and state on other
// users' trails need explicit deletes
export const resetUserData = async (userIds: string[]) => {
  await db
    .delete(schema.crumbs)
    .where(inArray(schema.crumbs.authorId, userIds))
  await db
    .delete(schema.trails)
    .where(inArray(schema.trails.authorId, userIds))
  await db
    .delete(schema.friendships)
    .where(
      or(
        inArray(schema.friendships.requesterId, userIds),
        inArray(schema.friendships.addresseeId, userIds),
      ),
    )
  await db
    .delete(schema.trailCollaborators)
    .where(inArray(schema.trailCollaborators.userId, userIds))
  await db
    .delete(schema.trailUserStates)
    .where(inArray(schema.trailUserStates.userId, userIds))
  await db
    .delete(schema.conversations)
    .where(
      or(
        inArray(schema.conversations.userAId, userIds),
        inArray(schema.conversations.userBId, userIds),
      ),
    )
}

export const seedTrail = async (
  authorId: string,
  name: string,
  crumbIds: string[],
): Promise<string> => {
  const [trail] = await db
    .insert(schema.trails)
    .values({authorId, name})
    .returning({id: schema.trails.id})
  if (!trail) throw new Error('failed to seed trail')
  if (crumbIds.length)
    await db.insert(schema.trailCrumbs).values(
      crumbIds.map((crumbId, position) => ({
        trailId: trail.id,
        crumbId,
        addedBy: authorId,
        position,
      })),
    )
  return trail.id
}
