import {
  createNavigationItem,
  createNavigationMenu,
  deleteNavigationItem,
  listNavigationMenus,
  listPages,
  updateNavigationItem,
} 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 readInt(formData: FormData, field: string, fallback = 0): 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 ? `/navigation?${value}` : "/navigation")
}

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

  await requirePermissionForRoute({
    nextPath: "/navigation",
    permission: "navigation:write",
    scope: "team",
  })

  try {
    await createNavigationMenu({
      name: readInputString(formData, "name"),
      slug: readInputString(formData, "slug"),
      location: readInputString(formData, "location"),
      isVisible: readInputString(formData, "isVisible") === "true",
    })
  } catch {
    redirectWithState({ error: "Failed to create navigation menu." })
  }

  revalidatePath("/navigation")
  redirectWithState({ notice: "Navigation menu created." })
}

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

  await requirePermissionForRoute({
    nextPath: "/navigation",
    permission: "navigation:write",
    scope: "team",
  })

  try {
    await createNavigationItem({
      menuId: readInputString(formData, "menuId"),
      label: readInputString(formData, "label"),
      href: readNullableString(formData, "href"),
      pageId: readNullableString(formData, "pageId"),
      parentId: readNullableString(formData, "parentId"),
      sortOrder: readInt(formData, "sortOrder", 0),
      isVisible: readInputString(formData, "isVisible") === "true",
    })
  } catch {
    redirectWithState({ error: "Failed to create navigation item." })
  }

  revalidatePath("/navigation")
  redirectWithState({ notice: "Navigation item created." })
}

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

  await requirePermissionForRoute({
    nextPath: "/navigation",
    permission: "navigation:write",
    scope: "team",
  })

  try {
    await updateNavigationItem({
      id: readInputString(formData, "id"),
      label: readInputString(formData, "label"),
      href: readNullableString(formData, "href"),
      pageId: readNullableString(formData, "pageId"),
      parentId: readNullableString(formData, "parentId"),
      sortOrder: readInt(formData, "sortOrder", 0),
      isVisible: readInputString(formData, "isVisible") === "true",
    })
  } catch {
    redirectWithState({ error: "Failed to update navigation item." })
  }

  revalidatePath("/navigation")
  redirectWithState({ notice: "Navigation item updated." })
}

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

  await requirePermissionForRoute({
    nextPath: "/navigation",
    permission: "navigation:write",
    scope: "team",
  })

  try {
    await deleteNavigationItem(readInputString(formData, "id"))
  } catch {
    redirectWithState({ error: "Failed to delete navigation item." })
  }

  revalidatePath("/navigation")
  redirectWithState({ notice: "Navigation item deleted." })
}

export default async function NavigationManagementPage({
  searchParams,
}: {
  searchParams: Promise<SearchParamsInput>
}) {
  const role = await requirePermissionForRoute({
    nextPath: "/navigation",
    permission: "navigation:read",
    scope: "team",
  })

  const [resolvedSearchParams, menus, pages] = await Promise.all([
    searchParams,
    listNavigationMenus(),
    listPages(200),
  ])

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

  return (
    <AdminShell
      role={role}
      activePath="/navigation"
      badge="Admin App"
      title="Navigation"
      description="Manage menus and navigation entries linked to pages or custom routes."
    >
      {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="grid gap-4 lg:grid-cols-2">
        <article className="rounded-xl border border-neutral-200 p-6">
          <h2 className="text-xl font-medium">Create Menu</h2>
          <form action={createMenuAction} className="mt-4 space-y-3">
            <label className="space-y-1">
              <span className="text-xs text-neutral-600">Name</span>
              <input
                name="name"
                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">Slug</span>
              <input
                name="slug"
                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">Location</span>
              <input
                name="location"
                defaultValue="primary"
                className="w-full rounded border border-neutral-300 px-3 py-2 text-sm"
              />
            </label>
            <label className="inline-flex items-center gap-2 text-sm text-neutral-700">
              <input
                name="isVisible"
                type="checkbox"
                value="true"
                defaultChecked
                className="size-4"
              />
              Visible
            </label>
            <Button type="submit">Create menu</Button>
          </form>
        </article>

        <article className="rounded-xl border border-neutral-200 p-6">
          <h2 className="text-xl font-medium">Create Navigation Item</h2>
          <form action={createItemAction} className="mt-4 space-y-3">
            <label className="space-y-1">
              <span className="text-xs text-neutral-600">Menu</span>
              <select
                name="menuId"
                className="w-full rounded border border-neutral-300 px-3 py-2 text-sm"
              >
                {menus.map((menu) => (
                  <option key={menu.id} value={menu.id}>
                    {menu.name} ({menu.location})
                  </option>
                ))}
              </select>
            </label>
            <label className="space-y-1">
              <span className="text-xs text-neutral-600">Label</span>
              <input
                name="label"
                required
                className="w-full rounded border border-neutral-300 px-3 py-2 text-sm"
              />
            </label>
            <div className="grid gap-3 md:grid-cols-2">
              <label className="space-y-1">
                <span className="text-xs text-neutral-600">Custom href</span>
                <input
                  name="href"
                  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">Linked page</span>
                <select
                  name="pageId"
                  className="w-full rounded border border-neutral-300 px-3 py-2 text-sm"
                >
                  <option value="">(none)</option>
                  {pages.map((page) => (
                    <option key={page.id} value={page.id}>
                      {page.title} (/{page.slug})
                    </option>
                  ))}
                </select>
              </label>
            </div>
            <div className="grid gap-3 md:grid-cols-2">
              <label className="space-y-1">
                <span className="text-xs text-neutral-600">Parent item id</span>
                <input
                  name="parentId"
                  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">Sort order</span>
                <input
                  name="sortOrder"
                  defaultValue="0"
                  type="number"
                  min={0}
                  className="w-full rounded border border-neutral-300 px-3 py-2 text-sm"
                />
              </label>
            </div>
            <label className="inline-flex items-center gap-2 text-sm text-neutral-700">
              <input
                name="isVisible"
                type="checkbox"
                value="true"
                defaultChecked
                className="size-4"
              />
              Visible
            </label>
            <Button type="submit">Create item</Button>
          </form>
        </article>
      </section>

      <section className="space-y-4">
        {menus.length === 0 ? (
          <article className="rounded-xl border border-neutral-200 p-6 text-sm text-neutral-600">
            No navigation menus yet.
          </article>
        ) : (
          menus.map((menu) => (
            <article key={menu.id} className="rounded-xl border border-neutral-200 p-6">
              <div className="flex flex-wrap items-center justify-between gap-2">
                <h3 className="text-lg font-medium">
                  {menu.name} <span className="text-sm text-neutral-500">({menu.location})</span>
                </h3>
                <span className="text-xs text-neutral-500">
                  {menu.isVisible ? "visible" : "hidden"}
                </span>
              </div>

              <div className="mt-4 space-y-3">
                {menu.items.length === 0 ? (
                  <p className="text-sm text-neutral-600">No items in this menu.</p>
                ) : (
                  menu.items.map((item) => (
                    <form
                      key={item.id}
                      action={updateItemAction}
                      className="rounded-lg border border-neutral-200 p-3"
                    >
                      <input type="hidden" name="id" value={item.id} />
                      <div className="grid gap-3 md:grid-cols-5">
                        <label className="space-y-1 md:col-span-2">
                          <span className="text-xs text-neutral-600">Label</span>
                          <input
                            name="label"
                            defaultValue={item.label}
                            className="w-full rounded border border-neutral-300 px-3 py-2 text-sm"
                          />
                        </label>
                        <label className="space-y-1 md:col-span-2">
                          <span className="text-xs text-neutral-600">Href</span>
                          <input
                            name="href"
                            defaultValue={item.href ?? ""}
                            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">Sort</span>
                          <input
                            name="sortOrder"
                            type="number"
                            min={0}
                            defaultValue={item.sortOrder}
                            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">Linked page</span>
                          <select
                            name="pageId"
                            defaultValue={item.pageId ?? ""}
                            className="w-full rounded border border-neutral-300 px-3 py-2 text-sm"
                          >
                            <option value="">(none)</option>
                            {pages.map((page) => (
                              <option key={page.id} value={page.id}>
                                {page.title} (/{page.slug})
                              </option>
                            ))}
                          </select>
                        </label>
                        <label className="space-y-1">
                          <span className="text-xs text-neutral-600">Parent id</span>
                          <input
                            name="parentId"
                            defaultValue={item.parentId ?? ""}
                            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
                            type="checkbox"
                            name="isVisible"
                            value="true"
                            defaultChecked={item.isVisible}
                            className="size-4"
                          />
                          Visible
                        </label>
                        <div className="flex items-center gap-2">
                          <Button type="submit" size="sm">
                            Save item
                          </Button>
                          <button
                            type="submit"
                            formAction={deleteItemAction}
                            className="rounded-md border border-red-300 px-3 py-2 text-sm text-red-700"
                          >
                            Delete
                          </button>
                        </div>
                      </div>
                    </form>
                  ))
                )}
              </div>
            </article>
          ))
        )}
      </section>
    </AdminShell>
  )
}
