import { AppShell } from "@/components/app-shell"
import { Badge } from "@/components/ui/badge"
import { translator, type Translate } from "@/lib/i18n"
import { OCCURRENCE_WORD } from "@/lib/i18n/duty-words"
import { ownJobDescription } from "@/lib/job-description-view"
import { positionDetail, type PositionDuty } from "@/lib/services/positions"
import { requireUser } from "@/lib/services/session"

/**
 * What my job is.
 *
 * The third of the three screens the specification gives a staff member, and
 * the last one to be built: the sidebar has promised it since the beginning
 * with a link to `#`.
 *
 * Read-only, with no exception and no button. The job description belongs to
 * the position, not to whoever is sitting in it — somebody editing their own
 * would be editing their successor's, and the same paragraph is what the next
 * holder reads to learn the job. Writing it stays at `/positions/[id]`, which
 * `routes.json` calls "THE position page = job-description editor and the only
 * write surface".
 *
 * `requireUser` rather than `requireAtLeast`, because this is the one screen
 * here that everybody has. The scope guard is still real: `positionDetail`
 * runs `visibleTo`, which lets a staff member reach their own position and no
 * other, so asking for somebody else's is answered with nothing rather than
 * with a page.
 */
export default async function Page() {
  const user = await requireUser()
  const t = translator(user.language)

  /**
   * Null while somebody is between two positions, which `SignedIn` documents
   * as a real state rather than a missing value. They have no job description
   * because they have no job, and saying so is better than an empty page.
   */
  const detail = user.positionId
    ? await positionDetail(user, user.positionId)
    : null

  if (!detail) {
    return (
      <AppShell title="nav.myJobDescription" user={user}>
        <p className="max-w-prose text-foreground/80">
          {t("myJobDescription.noPosition")}
        </p>
      </AppShell>
    )
  }

  const own = ownJobDescription({
    jobDescription: detail.jobDescription,
    duties: detail.duties,
  })

  return (
    <AppShell title="nav.myJobDescription" user={user}>
      <div className="flex flex-col gap-6">
        <div>
          <h2 className="text-lg font-medium">{detail.title}</h2>
          <p className="text-foreground/70">{detail.department}</p>
        </div>

        {own.isEmpty ? (
          <p className="max-w-prose text-foreground/80">
            {t("myJobDescription.empty")}
          </p>
        ) : (
          <>
            {/*
              No heading over the prose and no placeholder when it is missing.
              The paragraph either says what the job is for or it is not there,
              and a line reading "no description" above a list of real duties
              would contradict the list underneath it.
            */}
            {own.hasText ? (
              <p className="max-w-prose leading-relaxed whitespace-pre-wrap">
                {detail.jobDescription}
              </p>
            ) : null}

            <Duties
              title={t("myJobDescription.listed")}
              duties={own.listed}
              t={t}
              schedule={false}
            />
            <Duties
              title={t("myJobDescription.generated")}
              duties={own.generated}
              t={t}
              schedule
            />
          </>
        )}
      </div>
    </AppShell>
  )
}

/**
 * One of the two lists, or nothing at all when it is empty.
 *
 * The two are drawn by the same component and told apart by one flag, because
 * they differ in exactly one way: a listed duty has no schedule to show, its
 * occurrence being the whole of what makes it listed.
 */
function Duties({
  title,
  duties,
  t,
  schedule,
}: {
  title: string
  duties: PositionDuty[]
  t: Translate
  schedule: boolean
}) {
  if (duties.length === 0) return null

  return (
    <section className="flex flex-col gap-2">
      <h3 className="font-medium">{title}</h3>
      <ul className="flex max-w-prose flex-col gap-2">
        {duties.map((duty) => (
          <li
            key={duty.id}
            className="flex items-baseline justify-between gap-4 border-b pb-2 last:border-b-0"
          >
            <span>{duty.description}</span>
            {schedule ? (
              <Badge variant="outline" className="shrink-0">
                {t(OCCURRENCE_WORD[duty.occurrence])}
              </Badge>
            ) : null}
          </li>
        ))}
      </ul>
    </section>
  )
}
