import {
  createAnnouncement,
  deleteAnnouncement,
  listAnnouncements,
  updateAnnouncement,
} from "@cms/db"
import { Button } from "@cms/ui/button"
import { revalidatePath } from "next/cache"
import { redirect } from "next/navigation"

import { AdminShell } from "@/components/admin-shell"
import { requirePermissionForRoute } from "@/lib/route-guards"

export const dynamic = "force-dynamic"

type SearchParamsInput = Record<string, string | string[] | undefined>

function readFirstValue(value: string | string[] | undefined): string | null {
  if (Array.isArray(value)) {
    return value[0] ?? null
  }

  return value ?? null
}

function readInputString(formData: FormData, field: string): string {
  const value = formData.get(field)
  return typeof value === "string" ? value.trim() : ""
}

function readNullableString(formData: FormData, field: string): string | null {
  const value = readInputString(formData, field)
  return value.length > 0 ? value : null
}

function readNullableDate(formData: FormData, field: string): Date | null {
  const value = readInputString(formData, field)

  if (!value) {
    return null
  }

  const parsed = new Date(value)

  if (Number.isNaN(parsed.getTime())) {
    return null
  }

  return parsed
}

function readInt(formData: FormData, field: string, fallback = 100): number {
  const value = readInputString(formData, field)

  if (!value) {
    return fallback
  }

  const parsed = Number.parseInt(value, 10)

  if (!Number.isFinite(parsed)) {
    return fallback
  }

  return parsed
}

function redirectWithState(params: { notice?: string; error?: string }) {
  const query = new URLSearchParams()

  if (params.notice) {
    query.set("notice", params.notice)
  }

  if (params.error) {
    query.set("error", params.error)
  }

  const value = query.toString()
  redirect(value ? `/announcements?${value}` : "/announcements")
}

async function createAnnouncementAction(formData: FormData) {
  "use server"

  await requirePermissionForRoute({
    nextPath: "/announcements",
    permission: "banner:write",
    scope: "global",
  })

  try {
    await createAnnouncement({
      title: readInputString(formData, "title"),
      message: readInputString(formData, "message"),
      placement: readInputString(formData, "placement"),
      priority: readInt(formData, "priority", 100),
      ctaLabel: readNullableString(formData, "ctaLabel"),
      ctaHref: readNullableString(formData, "ctaHref"),
      startsAt: readNullableDate(formData, "startsAt"),
      endsAt: readNullableDate(formData, "endsAt"),
      isVisible: readInputString(formData, "isVisible") === "true",
    })
  } catch {
    redirectWithState({ error: "Failed to create announcement." })
  }

  revalidatePath("/announcements")
  revalidatePath("/")
  redirectWithState({ notice: "Announcement created." })
}

async function updateAnnouncementAction(formData: FormData) {
  "use server"

  await requirePermissionForRoute({
    nextPath: "/announcements",
    permission: "banner:write",
    scope: "global",
  })

  try {
    await updateAnnouncement({
      id: readInputString(formData, "id"),
      title: readInputString(formData, "title"),
      message: readInputString(formData, "message"),
      placement: readInputString(formData, "placement"),
      priority: readInt(formData, "priority", 100),
      ctaLabel: readNullableString(formData, "ctaLabel"),
      ctaHref: readNullableString(formData, "ctaHref"),
      startsAt: readNullableDate(formData, "startsAt"),
      endsAt: readNullableDate(formData, "endsAt"),
      isVisible: readInputString(formData, "isVisible") === "true",
    })
  } catch {
    redirectWithState({ error: "Failed to update announcement." })
  }

  revalidatePath("/announcements")
  revalidatePath("/")
  redirectWithState({ notice: "Announcement updated." })
}

async function deleteAnnouncementAction(formData: FormData) {
  "use server"

  await requirePermissionForRoute({
    nextPath: "/announcements",
    permission: "banner:write",
    scope: "global",
  })

  try {
    await deleteAnnouncement(readInputString(formData, "id"))
  } catch {
    redirectWithState({ error: "Failed to delete announcement." })
  }

  revalidatePath("/announcements")
  revalidatePath("/")
  redirectWithState({ notice: "Announcement deleted." })
}

function dateInputValue(value: Date | null): string {
  if (!value) {
    return ""
  }

  return value.toISOString().slice(0, 10)
}

export default async function AnnouncementsPage({
  searchParams,
}: {
  searchParams: Promise<SearchParamsInput>
}) {
  const role = await requirePermissionForRoute({
    nextPath: "/announcements",
    permission: "banner:read",
    scope: "global",
  })

  const [resolvedSearchParams, announcements] = await Promise.all([
    searchParams,
    listAnnouncements(200),
  ])

  const notice = readFirstValue(resolvedSearchParams.notice)
  const error = readFirstValue(resolvedSearchParams.error)

  return (
    <AdminShell
      role={role}
      activePath="/announcements"
      badge="Admin App"
      title="Announcements"
      description="Manage public site announcements with schedule and placement controls."
    >
      {notice ? (
        <section className="rounded-xl border border-emerald-300 bg-emerald-50 px-4 py-3 text-sm text-emerald-800">
          {notice}
        </section>
      ) : null}

      {error ? (
        <section className="rounded-xl border border-red-300 bg-red-50 px-4 py-3 text-sm text-red-800">
          {error}
        </section>
      ) : null}

      <section className="rounded-xl border border-neutral-200 p-6">
        <h2 className="text-xl font-medium">Create Announcement</h2>
        <form action={createAnnouncementAction} className="mt-4 space-y-3">
          <label className="space-y-1">
            <span className="text-xs text-neutral-600">Title</span>
            <input
              name="title"
              required
              className="w-full rounded border border-neutral-300 px-3 py-2 text-sm"
            />
          </label>
          <label className="space-y-1">
            <span className="text-xs text-neutral-600">Message</span>
            <textarea
              name="message"
              rows={3}
              required
              className="w-full rounded border border-neutral-300 px-3 py-2 text-sm"
            />
          </label>
          <div className="grid gap-3 md:grid-cols-3">
            <label className="space-y-1">
              <span className="text-xs text-neutral-600">Placement</span>
              <select
                name="placement"
                defaultValue="global_top"
                className="w-full rounded border border-neutral-300 px-3 py-2 text-sm"
              >
                <option value="global_top">global_top</option>
                <option value="homepage">homepage</option>
              </select>
            </label>
            <label className="space-y-1">
              <span className="text-xs text-neutral-600">Priority</span>
              <input
                name="priority"
                type="number"
                min={0}
                defaultValue="100"
                className="w-full rounded border border-neutral-300 px-3 py-2 text-sm"
              />
            </label>
            <label className="inline-flex items-center gap-2 pt-6 text-sm text-neutral-700">
              <input
                name="isVisible"
                type="checkbox"
                value="true"
                defaultChecked
                className="size-4"
              />
              Visible
            </label>
          </div>
          <div className="grid gap-3 md:grid-cols-2">
            <label className="space-y-1">
              <span className="text-xs text-neutral-600">CTA label</span>
              <input
                name="ctaLabel"
                className="w-full rounded border border-neutral-300 px-3 py-2 text-sm"
              />
            </label>
            <label className="space-y-1">
              <span className="text-xs text-neutral-600">CTA href</span>
              <input
                name="ctaHref"
                className="w-full rounded border border-neutral-300 px-3 py-2 text-sm"
              />
            </label>
          </div>
          <div className="grid gap-3 md:grid-cols-2">
            <label className="space-y-1">
              <span className="text-xs text-neutral-600">Starts at</span>
              <input
                name="startsAt"
                type="date"
                className="w-full rounded border border-neutral-300 px-3 py-2 text-sm"
              />
            </label>
            <label className="space-y-1">
              <span className="text-xs text-neutral-600">Ends at</span>
              <input
                name="endsAt"
                type="date"
                className="w-full rounded border border-neutral-300 px-3 py-2 text-sm"
              />
            </label>
          </div>
          <Button type="submit">Create announcement</Button>
        </form>
      </section>

      <section className="space-y-3">
        {announcements.length === 0 ? (
          <article className="rounded-xl border border-neutral-200 p-6 text-sm text-neutral-600">
            No announcements yet.
          </article>
        ) : (
          announcements.map((announcement) => (
            <form
              key={announcement.id}
              action={updateAnnouncementAction}
              className="rounded-xl border border-neutral-200 p-6"
            >
              <input type="hidden" name="id" value={announcement.id} />
              <div className="grid gap-3 md:grid-cols-2">
                <label className="space-y-1">
                  <span className="text-xs text-neutral-600">Title</span>
                  <input
                    name="title"
                    defaultValue={announcement.title}
                    className="w-full rounded border border-neutral-300 px-3 py-2 text-sm"
                  />
                </label>
                <label className="space-y-1">
                  <span className="text-xs text-neutral-600">Placement</span>
                  <select
                    name="placement"
                    defaultValue={announcement.placement}
                    className="w-full rounded border border-neutral-300 px-3 py-2 text-sm"
                  >
                    <option value="global_top">global_top</option>
                    <option value="homepage">homepage</option>
                  </select>
                </label>
              </div>
              <label className="mt-3 block space-y-1">
                <span className="text-xs text-neutral-600">Message</span>
                <textarea
                  name="message"
                  rows={2}
                  defaultValue={announcement.message}
                  className="w-full rounded border border-neutral-300 px-3 py-2 text-sm"
                />
              </label>
              <div className="mt-3 grid gap-3 md:grid-cols-3">
                <label className="space-y-1">
                  <span className="text-xs text-neutral-600">Priority</span>
                  <input
                    name="priority"
                    type="number"
                    min={0}
                    defaultValue={announcement.priority}
                    className="w-full rounded border border-neutral-300 px-3 py-2 text-sm"
                  />
                </label>
                <label className="space-y-1">
                  <span className="text-xs text-neutral-600">Starts</span>
                  <input
                    name="startsAt"
                    type="date"
                    defaultValue={dateInputValue(announcement.startsAt)}
                    className="w-full rounded border border-neutral-300 px-3 py-2 text-sm"
                  />
                </label>
                <label className="space-y-1">
                  <span className="text-xs text-neutral-600">Ends</span>
                  <input
                    name="endsAt"
                    type="date"
                    defaultValue={dateInputValue(announcement.endsAt)}
                    className="w-full rounded border border-neutral-300 px-3 py-2 text-sm"
                  />
                </label>
              </div>
              <div className="mt-3 grid gap-3 md:grid-cols-2">
                <label className="space-y-1">
                  <span className="text-xs text-neutral-600">CTA label</span>
                  <input
                    name="ctaLabel"
                    defaultValue={announcement.ctaLabel ?? ""}
                    className="w-full rounded border border-neutral-300 px-3 py-2 text-sm"
                  />
                </label>
                <label className="space-y-1">
                  <span className="text-xs text-neutral-600">CTA href</span>
                  <input
                    name="ctaHref"
                    defaultValue={announcement.ctaHref ?? ""}
                    className="w-full rounded border border-neutral-300 px-3 py-2 text-sm"
                  />
                </label>
              </div>
              <div className="mt-3 flex flex-wrap items-center justify-between gap-3">
                <label className="inline-flex items-center gap-2 text-sm text-neutral-700">
                  <input
                    name="isVisible"
                    type="checkbox"
                    value="true"
                    defaultChecked={announcement.isVisible}
                    className="size-4"
                  />
                  Visible
                </label>
                <div className="flex items-center gap-2">
                  <Button type="submit" size="sm">
                    Save
                  </Button>
                  <button
                    type="submit"
                    formAction={deleteAnnouncementAction}
                    className="rounded-md border border-red-300 px-3 py-2 text-sm text-red-700"
                  >
                    Delete
                  </button>
                </div>
              </div>
            </form>
          ))
        )}
      </section>
    </AdminShell>
  )
}
