import 'server-only'
import type { Prisma } from '@prisma/client'

/**
 * Who can see what. Every session-backed query filters through this module —
 * one place to read, one place to audit — rather than spreading `ownerId`
 * checks across ~120 call sites where exactly one will eventually be forgotten.
 *
 * Three tiers, and the difference between the last two matters:
 *
 *  - **visible**: what the account may READ and EDIT. For the shareable models
 *    that is "mine, or shared with the household" — a shared grocery list
 *    nobody but its owner can tick off is not shared in any useful sense.
 *  - **owned**: what the account may DELETE, rename, or change the visibility
 *    of. Editing a shared list is collaboration; deleting one is not.
 *  - Models with no visibility column (captures, calendar events, Apple lists,
 *    the activity feed, topics) are owner-only in every direction. Raw audio
 *    and transcripts are the most personal thing in the app, so a capture is
 *    never visible to another account by any route.
 */

/** Owner-only: deletes, renames, visibility changes. */
export function owned(userId: string): { ownerId: string } {
  return { ownerId: userId }
}

/** Mine, or shared with the household. */
function mineOrShared(userId: string) {
  return { OR: [{ ownerId: userId }, { visibility: 'HOUSEHOLD' as const }] }
}

export const visible = {
  reminder: (userId: string): Prisma.ReminderWhereInput => mineOrShared(userId),
  thought: (userId: string): Prisma.ThoughtWhereInput => mineOrShared(userId),
  checklist: (userId: string): Prisma.ChecklistWhereInput => mineOrShared(userId),

  // Leaf models have no owner of their own — they inherit their parent's.
  checklistItem: (userId: string): Prisma.ChecklistItemWhereInput => ({
    list: mineOrShared(userId),
  }),

  // Owner-only, no sharing possible.
  capture: (userId: string): Prisma.CaptureWhereInput => owned(userId),
  calendarEvent: (userId: string): Prisma.CalendarEventWhereInput => owned(userId),
  reminderList: (userId: string): Prisma.ReminderListWhereInput => owned(userId),
  activity: (userId: string): Prisma.ActivityWhereInput => owned(userId),
  topic: (userId: string): Prisma.TopicWhereInput => owned(userId),

  // A pin is visible if it's yours, or if it was pinned to the shared board.
  // The SHARED-implies-household-visible-target invariant is enforced where
  // pins are created (see requireShareableTarget), so a shared pin can never
  // surface a private record.
  focusPin: (userId: string): Prisma.FocusPinWhereInput => ({
    OR: [{ ownerId: userId }, { scope: 'SHARED' as const }],
  }),

  // An attachment is visible exactly when the record it hangs off is. Without
  // this, /api/image/:id and /api/audio/:id are "any signed-in household
  // member can read any photo or voice memo by guessing an id".
  attachment: (userId: string): Prisma.AttachmentWhereInput => ({
    OR: [
      { capture: owned(userId) },
      { thought: mineOrShared(userId) },
      { reminder: mineOrShared(userId) },
      { checklistItem: { list: mineOrShared(userId) } },
    ],
  }),
}
