import type {TrailPost} from '@crumbs/core/schemas'
import {and, eq} from 'drizzle-orm'

import {db, schema} from '../db/client'
import {keysetCursorWhere, keysetOrder, toPage} from '../lib/cursor'
import {publicImageUrl} from '../lib/source-image'
import {notBlockedByViewer} from './blocks'

type TrailPostRow = typeof schema.trailPosts.$inferSelect

type TrailPostJoinedRow = {
  post: TrailPostRow
  authorHandle: string
  authorAvatarRef: string | null
}

export const toTrailPost = (r: TrailPostJoinedRow): TrailPost => ({
  id: r.post.id,
  text: r.post.text,
  facets: r.post.facets,
  author: {
    id: r.post.authorId,
    handle: r.authorHandle,
    avatarUrl: publicImageUrl(r.authorAvatarRef),
  },
  createdAt: r.post.createdAt.toISOString(),
})

// keyset-paginated posts on a trail, newest first. viewerId filters out
// posts by members the viewer has blocked (or been blocked by)
export const listTrailPosts = async (
  trailId: string,
  {
    viewerId,
    limit,
    cursor,
  }: {viewerId: string; limit: number; cursor?: string},
) => {
  const rows = await db
    .select({
      post: schema.trailPosts,
      authorHandle: schema.users.handle,
      authorAvatarRef: schema.users.avatarRef,
    })
    .from(schema.trailPosts)
    .innerJoin(
      schema.users,
      eq(schema.users.id, schema.trailPosts.authorId),
    )
    .where(
      and(
        eq(schema.trailPosts.trailId, trailId),
        notBlockedByViewer(schema.trailPosts.authorId, viewerId),
        keysetCursorWhere(
          schema.trailPosts.createdAt,
          schema.trailPosts.id,
          cursor,
        ),
      ),
    )
    .orderBy(
      ...keysetOrder(
        schema.trailPosts.createdAt,
        schema.trailPosts.id,
      ),
    )
    .limit(limit + 1)

  const {page, nextCursor} = toPage(rows, limit, (r) => ({
    createdAt: r.post.createdAt,
    id: r.post.id,
  }))
  return {posts: page.map(toTrailPost), nextCursor}
}
