"use client";

import Link from "next/link";
import { useRouter } from "next/navigation";
import * as React from "react";
import { ArrowLeft, Loader2 } from "lucide-react";
import { toast } from "sonner";

import {
  createDiscussionThreadClient,
  updateDiscussionThreadClient,
} from "@/app/customer/[tenant]/discussion-board/_lib/discussion-board-api";
import type {
  DiscussionFormOptions,
  DiscussionTagOption,
  DiscussionThreadDetail,
} from "@/app/customer/[tenant]/discussion-board/_lib/types";
import { RichTextEditor } from "@/components/settings/common-template/components/rich-text-editor";
import { SETTINGS_INPUT_CLASS } from "@/components/settings/constants";
import { ErrorBanner } from "@/components/shared/error-banner";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Textarea } from "@/components/ui/textarea";
import { customerUrl } from "@/lib/tenant";
import { cn } from "@/lib/utils";

const ALL_AUTHENTICATED = "all_authenticated";

type DiscussionThreadFormProps = {
  tenant: string;
  mode: "create" | "update";
  formOptions: DiscussionFormOptions;
  initialThread?: DiscussionThreadDetail;
  initialTagIds?: number[];
};

function parseVisibilityKeys(visibility: string): string[] {
  const normalized = visibility.trim();
  if (!normalized) return [ALL_AUTHENTICATED];
  if (normalized.includes(",")) {
    return normalized
      .split(",")
      .map((item) => item.trim())
      .filter(Boolean);
  }
  return [normalized];
}

function resolveVisibilityPayload(selected: string[]): string | string[] {
  if (selected.includes(ALL_AUTHENTICATED)) {
    return ALL_AUTHENTICATED;
  }
  if (selected.length === 1) {
    return selected[0];
  }
  return selected;
}

export function DiscussionThreadForm({
  tenant,
  mode,
  formOptions,
  initialThread,
  initialTagIds = [],
}: DiscussionThreadFormProps) {
  const router = useRouter();
  const boardHref = customerUrl(tenant, "/discussion-board");

  const [title, setTitle] = React.useState(initialThread?.title ?? "");
  const [body, setBody] = React.useState(initialThread?.body ?? "");
  const [editReason, setEditReason] = React.useState("");
  const [selectedTagIds, setSelectedTagIds] = React.useState<number[]>(initialTagIds);
  const [newTags, setNewTags] = React.useState("");
  const [visibilityKeys, setVisibilityKeys] = React.useState<string[]>(() =>
    initialThread ? parseVisibilityKeys(initialThread.visibility) : [ALL_AUTHENTICATED],
  );
  const [isSaving, setIsSaving] = React.useState(false);
  const [errorMessage, setErrorMessage] = React.useState<string | null>(null);

  const groupChoices = formOptions.visibilityChoices.filter(
    (choice) => choice.value !== ALL_AUTHENTICATED,
  );
  const allAuthenticatedSelected = visibilityKeys.includes(ALL_AUTHENTICATED);

  const toggleVisibility = (value: string) => {
    if (value === ALL_AUTHENTICATED) {
      setVisibilityKeys([ALL_AUTHENTICATED]);
      return;
    }

    setVisibilityKeys((prev) => {
      const withoutAll = prev.filter((item) => item !== ALL_AUTHENTICATED);
      if (withoutAll.includes(value)) {
        const next = withoutAll.filter((item) => item !== value);
        return next.length > 0 ? next : [ALL_AUTHENTICATED];
      }
      return [...withoutAll, value];
    });
  };

  const toggleTag = (tagId: number) => {
    setSelectedTagIds((prev) =>
      prev.includes(tagId) ? prev.filter((id) => id !== tagId) : [...prev, tagId],
    );
  };

  const submit = async (publish: boolean) => {
    if (!title.trim()) {
      setErrorMessage("Title is required.");
      return;
    }

    setIsSaving(true);
    setErrorMessage(null);

    const payload: Record<string, unknown> = {
      title: title.trim(),
      body,
      visibility: resolveVisibilityPayload(visibilityKeys),
      tag_ids: selectedTagIds,
      new_tags: newTags.trim(),
      publish,
      draft: !publish,
    };

    if (mode === "update" && initialThread) {
      payload.id = initialThread.token;
      if (editReason.trim()) {
        payload.edit_reason = editReason.trim();
      }
    }

    try {
      const result =
        mode === "create"
          ? await createDiscussionThreadClient(tenant, payload)
          : await updateDiscussionThreadClient(tenant, payload);

      toast.success(publish ? "Thread published" : "Draft saved");
      router.push(customerUrl(tenant, `/discussion-board/view/${encodeURIComponent(result.token)}`));
      router.refresh();
    } catch (error) {
      const message = error instanceof Error ? error.message : "Failed to save thread";
      setErrorMessage(message);
      toast.error(message);
    } finally {
      setIsSaving(false);
    }
  };

  return (
    <div className="flex flex-col gap-3 md:gap-4">
      <div className="flex flex-col gap-2 border-b pb-3 sm:flex-row sm:items-center sm:justify-between">
        <div className="flex items-center gap-2">
          <h1 className="font-semibold text-base tracking-tight">
            {mode === "create" ? "New topic" : "Edit topic"}
          </h1>
        </div>
        <Button variant="outline" size="sm" className="gap-1.5" asChild>
          <Link href={boardHref}>
            <ArrowLeft className="size-4" />
            Back to board
          </Link>
        </Button>
      </div>

      <ErrorBanner message={errorMessage} />

      <div className="space-y-4 rounded-lg border p-4">
        <div className="space-y-1.5">
          <Label htmlFor="thread-title">Title</Label>
          <Input
            id="thread-title"
            className={SETTINGS_INPUT_CLASS}
            value={title}
            onChange={(event) => setTitle(event.target.value)}
            placeholder="Topic title"
          />
        </div>

        <div className="space-y-1.5">
          <Label>Body</Label>
          <RichTextEditor value={body} onChange={setBody} minHeight={220} />
        </div>

        <div className="space-y-2">
          <Label>Visibility</Label>
          <div className="flex flex-wrap gap-2">
            {formOptions.visibilityChoices.map((choice) => {
              const selected =
                choice.value === ALL_AUTHENTICATED
                  ? allAuthenticatedSelected
                  : !allAuthenticatedSelected && visibilityKeys.includes(choice.value);
              return (
                <Button
                  key={choice.value}
                  type="button"
                  size="sm"
                  variant={selected ? "default" : "outline"}
                  className="h-8 text-xs"
                  onClick={() => toggleVisibility(choice.value)}
                >
                  {choice.label}
                </Button>
              );
            })}
          </div>
          {groupChoices.length > 0 ? (
            <p className="text-muted-foreground text-xs">
              Select everyone, or one or more specific groups — not both.
            </p>
          ) : null}
        </div>

        <div className="space-y-2">
          <Label>Tags</Label>
          <div className="flex flex-wrap gap-2">
            {formOptions.tags.map((tag: DiscussionTagOption) => {
              const selected = selectedTagIds.includes(tag.tag_id);
              return (
                <Button
                  key={tag.tag_id}
                  type="button"
                  size="sm"
                  variant={selected ? "default" : "outline"}
                  className="h-8 text-xs"
                  onClick={() => toggleTag(tag.tag_id)}
                >
                  {tag.label}
                </Button>
              );
            })}
          </div>
          <Textarea
            className={cn(SETTINGS_INPUT_CLASS, "min-h-20")}
            value={newTags}
            onChange={(event) => setNewTags(event.target.value)}
            placeholder="Add new tags (comma or newline separated)"
          />
        </div>

        {mode === "update" ? (
          <div className="space-y-1.5">
            <Label htmlFor="edit-reason">Edit reason (optional)</Label>
            <Input
              id="edit-reason"
              className={SETTINGS_INPUT_CLASS}
              value={editReason}
              onChange={(event) => setEditReason(event.target.value)}
              placeholder="Why are you editing this topic?"
            />
          </div>
        ) : null}

        <div className="flex flex-wrap gap-2 pt-2">
          <Button type="button" disabled={isSaving} onClick={() => void submit(true)}>
            {isSaving ? <Loader2 className="size-4 animate-spin" /> : null}
            Publish
          </Button>
          <Button
            type="button"
            variant="outline"
            disabled={isSaving}
            onClick={() => void submit(false)}
          >
            Save draft
          </Button>
        </div>
      </div>
    </div>
  );
}
