import { getPayload, PaginatedDocs } from 'payload'
import { unstable_cache } from 'next/cache'
import config from '@/payload.config'
import { Worship } from '@/payload-types'

const CACHE_TTL = 300 // 5 minutes

type FetchWorshipArgs = {
  fromDate?: Date
  tillDate?: Date
  locations?: string[]
}

// Resolved args use ISO strings so they serialize into a stable cache key.
type ResolvedWorshipArgs = {
  fromDate: string
  tillDate?: string
  locations?: string[]
}

// Round down to the cache window so millisecond-precision dates produce a
// stable key for the duration of the TTL.
function roundDownToTtl(date: Date): Date {
  const ms = CACHE_TTL * 1000
  return new Date(Math.floor(date.getTime() / ms) * ms)
}

const getWorship = unstable_cache(
  async (args: ResolvedWorshipArgs): Promise<PaginatedDocs<Worship>> => {
    const { fromDate, tillDate, locations } = args

    const query: any = {
      and: [
        {
          date: {
            greater_than_equal: fromDate,
          },
        },
      ],
    }

    if (tillDate) {
      query.and.push({
        date: {
          less_than: tillDate,
        },
      })
    }

    if (locations) {
      query.and.push({
        location: {
          in: locations,
        },
      })
    }

    const payload = await getPayload({ config })
    return payload.find({
      collection: 'worship',
      sort: 'date',
      where: query,
      select: {
        type: true,
        date: true,
        cancelled: true,
        location: true,
        title: true,
      },
      limit: 100,
    }) as Promise<PaginatedDocs<Worship>>
  },
  ['fetchWorship'],
  { tags: ['worship'], revalidate: CACHE_TTL },
)

export const fetchWorship = async (
  args?: FetchWorshipArgs,
): Promise<PaginatedDocs<Worship>> => {
  const { fromDate, tillDate, locations } = args || {}

  let date = fromDate
  if (!date) {
    date = new Date()
    date.setHours(0, 0, 0, 0)
  }

  return getWorship({
    fromDate: roundDownToTtl(date).toISOString(),
    tillDate: tillDate ? roundDownToTtl(tillDate).toISOString() : undefined,
    locations,
  })
}

/**
 * Fetch a single worship entry by ID
 */
export async function fetchWorshipById(
  id: string,
): Promise<Worship | undefined> {
  try {
    const payload = await getPayload({ config })
    return await payload.findByID({ collection: 'worship', id })
  } catch {
    return undefined
  }
}
