"use client";

import Link from "next/link";
import { useActionState, useId, useState } from "react";
import { FormErrorBanner } from "@/components/admin/Flash";
import { FormTabs } from "@/components/admin/FormTabs";
import { RichTextEditor } from "@/components/admin/RichTextEditor";
import { SubmitButton } from "@/components/admin/SubmitButton";
import { ErrorText, HelpText, Input, Label, Select } from "@/components/ui";
import type { Page } from "@/db/schema";
import { type FormState, firstFieldError, initialFormState } from "@/lib/forms";
import { slugify } from "@/lib/slug";

type Props = {
  page?: Page;
  action: (prev: FormState, formData: FormData) => Promise<FormState>;
};

const SETTINGS_FIELDS = ["title", "slug"];

/** Same tabbed layout as PostForm: full-height canvas + settings panel. */
export function PageForm({ page, action }: Props) {
  const [state, formAction] = useActionState(action, initialFormState);
  const ids = useId();

  // See PostForm: explicit tab clicks win until the next action result,
  // which routes to the tab containing validation errors.
  const [tabChoice, setTabChoice] = useState<{
    tab: "content" | "settings";
    forState: FormState;
  }>({ tab: "content", forState: initialFormState });
  const [title, setTitle] = useState(page?.title ?? "");
  const [slug, setSlug] = useState(page?.slug ?? "");
  const [slugTouched, setSlugTouched] = useState(page !== undefined);
  const [status, setStatus] = useState<string>(page?.status ?? "draft");

  const err = (field: string) => firstFieldError(state, field);
  const errorKeys = Object.keys(state.fieldErrors ?? {});
  const settingsHasError = errorKeys.some((key) => SETTINGS_FIELDS.includes(key));
  const contentHasError = errorKeys.includes("body");

  const tab =
    tabChoice.forState === state
      ? tabChoice.tab
      : settingsHasError
        ? "settings"
        : contentHasError
          ? "content"
          : tabChoice.tab;
  const setTab = (next: "content" | "settings") =>
    setTabChoice({ tab: next, forState: state });

  return (
    <form action={formAction}>
      <div className="sticky top-0 z-20 -mb-px flex flex-wrap items-center justify-between gap-x-4 gap-y-2 border-b border-edge bg-background pt-1">
        <FormTabs
          idBase={ids}
          label="Page editor sections"
          activeId={tab}
          onSelect={(id) => setTab(id as typeof tab)}
          tabs={[
            { id: "content", label: "Content", hasError: contentHasError },
            { id: "settings", label: "Page settings", hasError: settingsHasError },
          ]}
        />
        <div className="flex items-center gap-3 pb-1.5">
          <Select
            aria-label="Status"
            name="status"
            value={status}
            onChange={(e) => setStatus(e.target.value)}
            className="w-32"
          >
            <option value="draft">Draft</option>
            <option value="published">Published</option>
          </Select>
          <SubmitButton>Save page</SubmitButton>
          <Link href="/admin/pages" className="text-sm text-ink-muted hover:text-ink-strong">
            Cancel
          </Link>
        </div>
      </div>

      <div className="pt-5">
        <FormErrorBanner>{state.formError}</FormErrorBanner>
      </div>

      <div
        role="tabpanel"
        id={`${ids}-panel-content`}
        aria-labelledby={`${ids}-tab-content`}
        hidden={tab !== "content"}
      >
        <RichTextEditor
          name="body"
          label="Body"
          initialHTML={page?.body ?? ""}
          error={err("body")}
          minHeightClassName="min-h-[max(24rem,calc(100dvh-24rem))]"
        />
      </div>

      <div
        role="tabpanel"
        id={`${ids}-panel-settings`}
        aria-labelledby={`${ids}-tab-settings`}
        hidden={tab !== "settings"}
        className="max-w-3xl space-y-6"
      >
        <div>
          <Label htmlFor={`${ids}-title`}>Title</Label>
          <Input
            id={`${ids}-title`}
            name="title"
            value={title}
            onChange={(e) => {
              setTitle(e.target.value);
              if (!slugTouched) setSlug(slugify(e.target.value));
            }}
            required
            aria-invalid={err("title") ? true : undefined}
            aria-describedby={err("title") ? `${ids}-title-error` : undefined}
          />
          <ErrorText id={`${ids}-title-error`}>{err("title")}</ErrorText>
        </div>

        <div>
          <Label htmlFor={`${ids}-slug`}>Slug</Label>
          <Input
            id={`${ids}-slug`}
            name="slug"
            value={slug}
            onChange={(e) => {
              setSlug(e.target.value);
              setSlugTouched(e.target.value !== "");
            }}
            aria-invalid={err("slug") ? true : undefined}
            aria-describedby={`${ids}-slug-help${err("slug") ? ` ${ids}-slug-error` : ""}`}
          />
          <HelpText id={`${ids}-slug-help`}>
            Public URL: /pages/{slug || "…"} — leave blank to generate from the title.
          </HelpText>
          <ErrorText id={`${ids}-slug-error`}>{err("slug")}</ErrorText>
        </div>

        <HelpText>Published pages can be linked from the top navigation.</HelpText>
      </div>
    </form>
  );
}
