"use client";

import { CheckIcon, CircleAlertIcon, LinkIcon, RotateCcwIcon } from "lucide-react";
import { useEffect, useRef, useState } from "react";

import { Button } from "@/components/ui/button";
import { Field, FieldLabel } from "@/components/ui/field";
import { Spinner } from "@/components/ui/spinner";
import { Textarea } from "@/components/ui/textarea";
import { checkSlugAvailability } from "@/features/blogs/actions";
import { EXCERPT_MAX, EXCERPT_RECOMMENDED, TITLE_MAX } from "@/features/blogs/schemas";
import { SLUG_PATTERN, slugify } from "@/lib/slug";
import { cn } from "@/lib/utils";

import { useBlogEditor } from "./editor-context";
import { CharCounter, ErrorText } from "./fields";
import { RichTextEditor } from "./rich-text-editor";

export function ContentSection() {
  const { values, setField, errors } = useBlogEditor();
  const titleRef = useRef<HTMLTextAreaElement>(null);

  // New articles start with the cursor in the title.
  useEffect(() => {
    if (!values.title) titleRef.current?.focus();
    // eslint-disable-next-line react-hooks/exhaustive-deps -- only on mount
  }, []);

  return (
    <div className="space-y-6">
      <div>
        <label htmlFor="blog-title" className="sr-only">
          Title
        </label>
        <Textarea
          id="blog-title"
          ref={titleRef}
          value={values.title}
          maxLength={TITLE_MAX}
          rows={1}
          placeholder="Article title"
          aria-invalid={Boolean(errors.title) || undefined}
          onChange={(event) => setField("title", event.target.value.replace(/\n/g, " "))}
          onKeyDown={(event) => {
            if (event.key === "Enter") {
              event.preventDefault();
              document.querySelector<HTMLElement>("#blog-excerpt")?.focus();
            }
          }}
          className="min-h-0 resize-none border-none bg-transparent px-0 py-1 text-3xl leading-tight font-semibold tracking-tight shadow-none placeholder:text-muted-foreground/50 focus-visible:ring-0 md:text-[2.125rem]"
        />
        <ErrorText message={errors.title} />
        <SlugField />
      </div>

      <Field>
        <div className="flex items-baseline justify-between">
          <FieldLabel htmlFor="blog-excerpt">Excerpt</FieldLabel>
          <CharCounter value={values.excerpt} recommended={EXCERPT_RECOMMENDED} max={EXCERPT_MAX} />
        </div>
        <Textarea
          id="blog-excerpt"
          value={values.excerpt}
          maxLength={EXCERPT_MAX}
          rows={2}
          placeholder="A short summary shown on blog cards and used when no meta description is set."
          onChange={(event) => setField("excerpt", event.target.value)}
          className="resize-none bg-card"
        />
        <ErrorText message={errors.excerpt} />
      </Field>

      <div>
        <RichTextEditor
          value={values.content}
          onChange={(html) => setField("content", html)}
          invalid={Boolean(errors.content)}
          toolbarOffset={57 + 49}
        />
        <ErrorText message={errors.content} />
      </div>
    </div>
  );
}

function SlugField() {
  const { values, setField, errors, meta, setSlugTouched, siteUrl } = useBlogEditor();
  const [checked, setChecked] = useState<{ slug: string; available: boolean; usedBy: string | null } | null>(
    null,
  );

  const slug = values.slug;
  const validFormat = slug === "" || SLUG_PATTERN.test(slug);
  const liveSlug = meta?.status === "PUBLISHED" ? meta.liveSlug : null;
  const host = siteUrl ? new URL(siteUrl).host : "wifi-calls-web.vercel.app";

  const availability =
    !slug || !validFormat
      ? null
      : checked?.slug !== slug
        ? ({ state: "checking" } as const)
        : checked.available
          ? ({ state: "available" } as const)
          : ({ state: "taken", usedBy: checked.usedBy } as const);

  useEffect(() => {
    if (!slug || !validFormat) return;
    let cancelled = false;
    const timer = setTimeout(async () => {
      const result = await checkSlugAvailability(slug, meta?.id ?? null);
      if (cancelled || !result.ok) return;
      setChecked({ slug, available: result.data.available, usedBy: result.data.usedBy });
    }, 400);
    return () => {
      cancelled = true;
      clearTimeout(timer);
    };
  }, [slug, validFormat, meta?.id]);

  return (
    <div className="mt-2">
      <div
        className={cn(
          "flex min-w-0 items-center gap-1.5 text-sm text-muted-foreground",
          (errors.slug || !validFormat || availability?.state === "taken") && "text-destructive",
        )}
      >
        <LinkIcon className="size-3.5 shrink-0" />
        <span className="shrink-0">{host}/blog/</span>
        <label htmlFor="blog-slug" className="sr-only">
          URL slug
        </label>
        <input
          id="blog-slug"
          value={slug}
          spellCheck={false}
          placeholder="url-slug"
          aria-invalid={Boolean(errors.slug) || !validFormat || undefined}
          onChange={(event) => {
            setSlugTouched(true);
            setField("slug", event.target.value.toLowerCase().replace(/\s+/g, "-").slice(0, 120));
          }}
          onBlur={() => {
            const cleaned = slugify(slug);
            if (cleaned !== slug) setField("slug", cleaned);
          }}
          style={{ width: `${Math.max(8, slug.length + 1)}ch` }}
          className="-mx-1 min-w-0 rounded-md bg-transparent px-1 py-0.5 font-mono text-[0.8125rem] text-foreground outline-none hover:bg-muted focus:bg-muted focus-visible:ring-2 focus-visible:ring-ring/40"
        />
        <span className="shrink-0">/</span>
        {availability?.state === "checking" && <Spinner className="size-3.5" />}
        {availability?.state === "available" && slug !== meta?.slug && (
          <CheckIcon className="size-3.5 text-success" aria-label="Available" />
        )}
        {slugify(values.title) && slug !== slugify(values.title) && (
          <Button
            type="button"
            variant="ghost"
            size="xs"
            className="text-muted-foreground"
            onClick={() => {
              setSlugTouched(false);
              setField("slug", slugify(values.title));
            }}
          >
            <RotateCcwIcon />
            From title
          </Button>
        )}
      </div>
      {!validFormat && (
        <p className="mt-1 text-xs text-destructive">Use lowercase letters, numbers and single hyphens.</p>
      )}
      {availability?.state === "taken" && (
        <p className="mt-1 text-xs text-destructive">
          Already used by “{availability.usedBy}”. {meta?.status === "DRAFT" || !meta ? "A number will be added when saving a draft." : ""}
        </p>
      )}
      <ErrorText message={errors.slug} />
      {liveSlug && slug !== liveSlug && validFormat && slug && (
        <p className="mt-1.5 flex items-start gap-1.5 text-xs text-warning">
          <CircleAlertIcon className="mt-px size-3.5 shrink-0" />
          This article is live at /blog/{liveSlug}/. When you update, the old URL will permanently redirect to the new one.
        </p>
      )}
    </div>
  );
}
