"use server"

import { revalidatePath } from "next/cache"

import { dayIn } from "@/lib/calendar"
import {
  endCover,
  openCover,
  type EndCoverResult,
  type OpenCoverResult,
} from "@/lib/services/covers"
import {
  setDutyActive,
  setJobDescription,
  type WriteResult,
} from "@/lib/services/duties"
import { requireAtLeast } from "@/lib/services/session"

/**
 * The four writes this page owns, as thin adapters.
 *
 * Each establishes who is asking and hands the work to a service, which asks
 * again whether that person may touch this position. The screen showing a
 * control is not a permission, which is why none of these trusts the id it is
 * given.
 *
 * `requireAtLeast("admin")` on all four, matching the page. That is the door
 * and not the rule: `withinScope` in covers.ts answers for a manager too, so
 * the day ELEVA-139 opens this page to managers these lines change and the
 * services do not.
 *
 * `revalidatePath` on the position rather than on the layout: only this page
 * changed, and the sidebar has nothing to redraw.
 */
export async function toggleDuty(
  positionId: string,
  dutyId: string,
  active: boolean,
): Promise<WriteResult> {
  const user = await requireAtLeast("admin")
  const result = await setDutyActive(user, dutyId, active)
  if (result.ok) revalidatePath(`/positions/${positionId}`)
  return result
}

export async function saveJobDescription(
  positionId: string,
  text: string,
): Promise<WriteResult> {
  const user = await requireAtLeast("admin")
  const result = await setJobDescription(user, positionId, text)
  if (result.ok) revalidatePath(`/positions/${positionId}`)
  return result
}

export async function startCover(
  positionId: string,
  standIn: string,
  fromDate: string,
  untilDate: string,
  reason: string,
): Promise<OpenCoverResult> {
  const user = await requireAtLeast("admin")
  const result = await openCover(user, {
    positionId,
    coveringPersonId: standIn,
    fromDate,
    untilDate,
    reason,
  })
  if (result.ok) revalidatePath(`/positions/${positionId}`)
  return result
}

/**
 * End a cover, as of today.
 *
 * **Today is read here and never taken from the browser.** `endCover` takes the
 * day as a parameter so it can be tested without moving a clock, and a
 * parameter reachable from a request body is a parameter somebody sets to next
 * month: the window would be extended rather than cut, and the stand-in would
 * keep receiving work after they had been stood down. The clock is read at the
 * one place a clock belongs, which is the edge.
 *
 * The position id travels alongside the cover id only so the right page can be
 * revalidated. `endCover` reads the position off the row itself and scopes
 * against that, so a mismatched pair here changes nothing about who is allowed.
 */
export async function stopCover(
  positionId: string,
  coverId: string,
): Promise<EndCoverResult> {
  const user = await requireAtLeast("admin")
  const result = await endCover(user, coverId, dayIn(new Date()))
  if (result.ok) revalidatePath(`/positions/${positionId}`)
  return result
}
