/**
 * Pure helpers for reading filter values out of URL search params.
 * Kept separate from the client FilterBar component so server components
 * can import them without crossing the RSC boundary.
 */

export type DatePreset = 'all' | 'this-month' | 'last-month' | 'custom'
/**
 * Status filter values. After the invoice migration `'applied'` is the
 * preferred label, but `'transferred'` is kept as a back-compat alias
 * (existing bookmarks / URLs). The two are treated identically by
 * applyStatus in /entries/page.tsx and applyBulkFilter in
 * entries/actions.ts.
 */
export type StatusFilter =
  | 'all'
  | 'pending'
  | 'transferred'
  | 'applied'
  | 'blocked'

function trimOrNull(v: string | string[] | undefined): string | null {
  if (typeof v !== 'string') return null
  const s = v.trim()
  return s === '' ? null : s
}

export type FilterDefaults = {
  date?: DatePreset
  status?: StatusFilter
}

export function readFiltersFromSearchParams(
  sp: Record<string, string | string[] | undefined>,
  defaults: FilterDefaults = {},
): {
  startBound: string | null
  endBound: string | null
  status: StatusFilter
  batch: string | null
  q: string | null
  project: string | null
  user: string | null
  source_email: string | null
  client: string | null
  operator: string | null
  imported_by: string | null
} {
  const date = (sp.date as DatePreset) ?? defaults.date ?? 'this-month'
  const customStart = typeof sp.start === 'string' ? sp.start : ''
  const customEnd = typeof sp.end === 'string' ? sp.end : ''
  const status = (sp.status as StatusFilter) ?? defaults.status ?? 'all'
  const batch = typeof sp.batch === 'string' && sp.batch !== 'all' ? sp.batch : null
  const q = typeof sp.q === 'string' && sp.q.trim() !== '' ? sp.q.trim() : null
  const project = trimOrNull(sp.project)
  const user = trimOrNull(sp.user)
  const source_email = trimOrNull(sp.source_email)
  const client = trimOrNull(sp.client)
  const operator = trimOrNull(sp.operator)
  const imported_by = trimOrNull(sp.imported_by)

  let startBound: string | null = null
  let endBound: string | null = null

  const now = new Date()
  const thisYear = now.getFullYear()
  const thisMonth = now.getMonth() + 1

  const monthStart = (y: number, m: number) =>
    `${y.toString().padStart(4, '0')}-${m.toString().padStart(2, '0')}-01 00:00:00`

  if (date === 'this-month') {
    startBound = monthStart(thisYear, thisMonth)
    const ny = thisMonth === 12 ? thisYear + 1 : thisYear
    const nm = thisMonth === 12 ? 1 : thisMonth + 1
    endBound = monthStart(ny, nm)
  } else if (date === 'last-month') {
    const lm = thisMonth === 1 ? 12 : thisMonth - 1
    const ly = thisMonth === 1 ? thisYear - 1 : thisYear
    startBound = monthStart(ly, lm)
    endBound = monthStart(thisYear, thisMonth)
  } else if (date === 'custom') {
    if (customStart) startBound = `${customStart} 00:00:00`
    if (customEnd) {
      const d = new Date(customEnd + 'T00:00:00Z')
      d.setUTCDate(d.getUTCDate() + 1)
      const y = d.getUTCFullYear()
      const m = d.getUTCMonth() + 1
      const da = d.getUTCDate()
      endBound = `${y}-${m.toString().padStart(2, '0')}-${da.toString().padStart(2, '0')} 00:00:00`
    }
  }
  // date === 'all' → no bounds

  return {
    startBound,
    endBound,
    status,
    batch,
    q,
    project,
    user,
    source_email,
    client,
    operator,
    imported_by,
  }
}
