import {
  createPost,
  deletePost,
  listPostsWithTranslations,
  updatePost,
  upsertPostTranslation,
} 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>
const SUPPORTED_LOCALES = ["de", "en", "es", "fr"] as const

type SupportedLocale = (typeof SUPPORTED_LOCALES)[number]

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 | undefined {
  const value = readInputString(formData, field)
  return value.length > 0 ? value : undefined
}

function normalizeLocale(input: string | null): SupportedLocale {
  if (input && SUPPORTED_LOCALES.includes(input as SupportedLocale)) {
    return input as SupportedLocale
  }

  return "en"
}

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 ? `/news?${value}` : "/news")
}

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

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

  try {
    await createPost({
      title: readInputString(formData, "title"),
      slug: readInputString(formData, "slug"),
      excerpt: readNullableString(formData, "excerpt"),
      body: readInputString(formData, "body"),
      status: readInputString(formData, "status") === "published" ? "published" : "draft",
    })
  } catch {
    redirectWithState({ error: "Failed to create post." })
  }

  revalidatePath("/news")
  revalidatePath("/")
  redirectWithState({ notice: "Post created." })
}

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

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

  try {
    await updatePost(readInputString(formData, "id"), {
      title: readInputString(formData, "title"),
      slug: readInputString(formData, "slug"),
      excerpt: readNullableString(formData, "excerpt"),
      body: readInputString(formData, "body"),
      status: readInputString(formData, "status") === "published" ? "published" : "draft",
    })
  } catch {
    redirectWithState({ error: "Failed to update post." })
  }

  revalidatePath("/news")
  revalidatePath("/")
  redirectWithState({ notice: "Post updated." })
}

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

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

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

  revalidatePath("/news")
  revalidatePath("/")
  redirectWithState({ notice: "Post deleted." })
}

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

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

  const locale = normalizeLocale(readInputString(formData, "locale"))

  try {
    await upsertPostTranslation({
      postId: readInputString(formData, "postId"),
      locale,
      title: readInputString(formData, "title"),
      excerpt: readNullableString(formData, "excerpt") ?? null,
      body: readInputString(formData, "body"),
    })
  } catch {
    redirectWithState({ error: "Failed to save translation." })
  }

  revalidatePath("/news")
  revalidatePath("/")
  redirectWithState({ notice: "Post translation saved." })
}

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

  const [resolvedSearchParams, posts] = await Promise.all([
    searchParams,
    listPostsWithTranslations(),
  ])

  const notice = readFirstValue(resolvedSearchParams.notice)
  const error = readFirstValue(resolvedSearchParams.error)
  const selectedLocale = normalizeLocale(readFirstValue(resolvedSearchParams.locale))

  return (
    <AdminShell
      role={role}
      activePath="/news"
      badge="Admin App"
      title="News"
      description="Manage blog/news posts for public updates and announcements archive."
    >
      {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 Post</h2>
        <form action={createNewsAction} className="mt-4 space-y-3">
          <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"
                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>
          </div>
          <label className="space-y-1">
            <span className="text-xs text-neutral-600">Excerpt</span>
            <input
              name="excerpt"
              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">Body</span>
            <textarea
              name="body"
              rows={5}
              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">Status</span>
            <select
              name="status"
              defaultValue="draft"
              className="w-full rounded border border-neutral-300 px-3 py-2 text-sm"
            >
              <option value="draft">draft</option>
              <option value="published">published</option>
            </select>
          </label>
          <Button type="submit">Create post</Button>
        </form>
      </section>

      <section className="space-y-3">
        <div className="flex flex-wrap gap-2">
          {SUPPORTED_LOCALES.map((locale) => (
            <a
              key={locale}
              href={`/news?locale=${locale}`}
              className={`inline-flex rounded border px-3 py-1.5 text-xs ${
                selectedLocale === locale
                  ? "border-neutral-800 bg-neutral-900 text-white"
                  : "border-neutral-300 text-neutral-700"
              }`}
            >
              {locale.toUpperCase()}
            </a>
          ))}
        </div>

        {posts.map((post) => {
          const translation = post.translations.find((entry) => entry.locale === selectedLocale)

          return (
            <div key={post.id} className="rounded-xl border border-neutral-200 p-6">
              <form action={updateNewsAction}>
                <input type="hidden" name="id" value={post.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={post.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">Slug</span>
                    <input
                      name="slug"
                      defaultValue={post.slug}
                      className="w-full rounded border border-neutral-300 px-3 py-2 text-sm"
                    />
                  </label>
                </div>
                <label className="mt-3 block space-y-1">
                  <span className="text-xs text-neutral-600">Excerpt</span>
                  <input
                    name="excerpt"
                    defaultValue={post.excerpt ?? ""}
                    className="w-full rounded border border-neutral-300 px-3 py-2 text-sm"
                  />
                </label>
                <label className="mt-3 block space-y-1">
                  <span className="text-xs text-neutral-600">Body</span>
                  <textarea
                    name="body"
                    rows={4}
                    defaultValue={post.body}
                    className="w-full rounded border border-neutral-300 px-3 py-2 text-sm"
                  />
                </label>
                <div className="mt-3 flex flex-wrap items-center justify-between gap-3">
                  <select
                    name="status"
                    defaultValue={post.status}
                    className="rounded border border-neutral-300 px-3 py-2 text-sm"
                  >
                    <option value="draft">draft</option>
                    <option value="published">published</option>
                  </select>
                  <div className="flex items-center gap-2">
                    <Button type="submit" size="sm">
                      Save
                    </Button>
                    <button
                      type="submit"
                      formAction={deleteNewsAction}
                      className="rounded-md border border-red-300 px-3 py-2 text-sm text-red-700"
                    >
                      Delete
                    </button>
                  </div>
                </div>
              </form>

              <form
                action={upsertNewsTranslationAction}
                className="mt-4 rounded-lg border border-neutral-200 p-4"
              >
                <input type="hidden" name="postId" value={post.id} />
                <input type="hidden" name="locale" value={selectedLocale} />

                <h3 className="text-sm font-medium">
                  Translation ({selectedLocale.toUpperCase()})
                </h3>
                <p className="mt-1 text-xs text-neutral-600">
                  Missing fields fall back to base post content on public pages.
                </p>
                {post.translations.length > 0 ? (
                  <p className="mt-2 text-xs text-neutral-600">
                    Saved locales:{" "}
                    {post.translations.map((entry) => entry.locale.toUpperCase()).join(", ")}
                  </p>
                ) : null}

                <div className="mt-3 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={translation?.title ?? post.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">Excerpt</span>
                    <input
                      name="excerpt"
                      defaultValue={translation?.excerpt ?? post.excerpt ?? ""}
                      className="w-full rounded border border-neutral-300 px-3 py-2 text-sm"
                    />
                  </label>
                </div>

                <label className="mt-3 block space-y-1">
                  <span className="text-xs text-neutral-600">Body</span>
                  <textarea
                    name="body"
                    rows={4}
                    defaultValue={translation?.body ?? post.body}
                    className="w-full rounded border border-neutral-300 px-3 py-2 text-sm"
                  />
                </label>

                <div className="mt-3">
                  <Button type="submit" size="sm">
                    Save translation
                  </Button>
                </div>
              </form>
            </div>
          )
        })}
      </section>
    </AdminShell>
  )
}
