import { useRef, useState } from "react";
import { useForm } from "react-hook-form";
import { useTranslation } from "react-i18next";
import { FiSend, FiPaperclip, FiX, FiPlay, FiFile, FiTag, FiSearch } from "react-icons/fi";
import { useQueryClient } from "@tanstack/react-query";
import Textarea from "@/components/ui/Textarea";
import Button from "@/components/ui/Button";
import Spinner from "@/components/ui/Spinner";
import FormErrorBanner from "@/components/ui/FormErrorBanner";
import { applyServerErrors } from "@/utils/formErrors";
import { apiSocialPostsCreate, apiSocialPostsTagsAttachCreate } from "@/api/generated/private/posts/posts";
import { useApiSocialHubsTagsList } from "@/api/generated/private/hubs/hubs";
import { privateApi } from "@/api/privateClient";

interface Props {
  parentId?: number;
  hubId?: number | null;
  hubName?: string;
  onPosted?: () => void;
}

interface ComposerForm {
  content: string;
}

export default function PostComposer({ parentId, hubId, hubName, onPosted }: Props) {
  const { t } = useTranslation("social");
  const queryClient = useQueryClient();
  const [rootError, setRootError] = useState<string | undefined>();
  const [files, setFiles] = useState<File[]>([]);
  const [previews, setPreviews] = useState<string[]>([]);
  const [selectedTags, setSelectedTags] = useState<Set<number>>(new Set());
  const [tagModalOpen, setTagModalOpen] = useState(false);
  const [tagSearch, setTagSearch] = useState("");
  const fileInputRef = useRef<HTMLInputElement>(null);

  const { data: tagsData } = useApiSocialHubsTagsList(
    hubId ? { hub: hubId } as never : undefined,
    { query: { enabled: !!hubId } },
  );
  const hubTags = tagsData?.results ?? [];

  const form = useForm<ComposerForm>({
    defaultValues: { content: "" },
  });
  const { register, handleSubmit, formState, reset, watch, clearErrors } = form;
  const { errors, isSubmitting } = formState;

  const content = watch("content");

  function handleFileChange(e: React.ChangeEvent<HTMLInputElement>) {
    const picked = Array.from(e.target.files ?? []);
    const newPreviews = picked.map((f) => URL.createObjectURL(f));
    setFiles((prev) => [...prev, ...picked]);
    setPreviews((prev) => [...prev, ...newPreviews]);
    e.target.value = "";
  }

  function removeFile(index: number) {
    URL.revokeObjectURL(previews[index]);
    setFiles((prev) => prev.filter((_, i) => i !== index));
    setPreviews((prev) => prev.filter((_, i) => i !== index));
  }

  function toggleTag(id: number) {
    setSelectedTags((prev) => {
      const next = new Set(prev);
      if (next.has(id)) next.delete(id);
      else next.add(id);
      return next;
    });
  }

  async function onSubmit(values: ComposerForm) {
    setRootError(undefined);
    clearErrors();
    try {
      const created = await apiSocialPostsCreate({
        content: values.content,
        hub: hubId ?? null,
        reply_to: parentId ?? null,
      } as Parameters<typeof apiSocialPostsCreate>[0]);

      for (const file of files) {
        const fd = new FormData();
        fd.append("file", file);
        await privateApi.post(`/api/social/posts/${created.id}/media/`, fd);
      }

      for (const tagId of selectedTags) {
        await apiSocialPostsTagsAttachCreate(created.id, { tag_id: tagId });
      }

      previews.forEach((url) => URL.revokeObjectURL(url));
      setFiles([]);
      setPreviews([]);
      setSelectedTags(new Set());
      reset({ content: "" });
      await queryClient.invalidateQueries({ queryKey: ["social", "posts"] });
      onPosted?.();
    } catch (err) {
      setRootError(applyServerErrors(form, err));
    }
  }

  function onInvalid() {
    setRootError(undefined);
  }

  const hasContent = !!content?.trim() || files.length > 0;
  const filteredTags = hubTags.filter((t) =>
    t.name.toLowerCase().includes(tagSearch.toLowerCase()),
  );
  const selectedTagObjects = hubTags.filter((t) => selectedTags.has(t.id));

  return (
    <>
      <form
        onSubmit={handleSubmit(onSubmit, onInvalid)}
        className="border-b border-brand-lines/10 px-4 py-3"
        noValidate
      >
        {hubName && (
          <h2 className="mb-2 text-base font-semibold text-brand-text">
            Příspěvek v h/{hubName}
          </h2>
        )}

        <FormErrorBanner message={rootError} className="mb-2" />

        <Textarea
          placeholder={
            parentId
              ? t("post.compose.replyPlaceholder")
              : t("post.compose.placeholder")
          }
          rows={3}
          disabled={isSubmitting}
          error={errors.content?.message}
          {...register("content", {
            validate: (v) => files.length > 0 || v.trim().length > 0 || true,
          })}
        />

        {/* File previews */}
        {previews.length > 0 && (
          <div className="mt-2 flex flex-wrap gap-2">
            {previews.map((src, i) => {
              const file = files[i];
              const isVideo = file?.type.startsWith("video/");
              const isImage = file?.type.startsWith("image/");
              return (
                <div key={src} className="relative">
                  {isVideo ? (
                    <div className="relative h-20 w-20">
                      <video
                        src={src}
                        className="h-20 w-20 rounded-xl object-cover border border-brand-lines/20 bg-black"
                        muted
                        playsInline
                        preload="metadata"
                        onLoadedMetadata={(e) => { (e.target as HTMLVideoElement).currentTime = 0.001; }}
                      />
                      <div className="absolute inset-0 flex items-center justify-center rounded-xl bg-black/30 pointer-events-none">
                        <FiPlay size={22} className="text-white drop-shadow" fill="white" />
                      </div>
                    </div>
                  ) : isImage ? (
                    <img
                      src={src}
                      alt=""
                      className="h-20 w-20 rounded-xl object-cover border border-brand-lines/20"
                    />
                  ) : (
                    <div className="flex h-20 w-32 flex-col items-center justify-center gap-1 rounded-xl border border-brand-lines/20 bg-brand-bgLight/40 px-2">
                      <FiFile size={22} className="text-brand-text/50 shrink-0" />
                      <span className="w-full truncate text-center text-[10px] text-brand-text/60 leading-tight">
                        {file?.name}
                      </span>
                    </div>
                  )}
                  <button
                    type="button"
                    onClick={() => removeFile(i)}
                    className="absolute -right-1.5 -top-1.5 flex h-5 w-5 items-center justify-center rounded-full bg-brand-bg border border-brand-lines/30 text-brand-text/70 hover:text-brand-text shadow"
                    aria-label={t("post.compose.removeImage")}
                  >
                    <FiX size={11} />
                  </button>
                </div>
              );
            })}
          </div>
        )}

        {/* Selected tags display */}
        {selectedTagObjects.length > 0 && (
          <div className="mt-2 flex flex-wrap gap-1.5">
            {selectedTagObjects.map((tag) => (
              <span
                key={tag.id}
                className="flex items-center gap-1 rounded-full border px-2.5 py-0.5 text-xs font-medium"
                style={{ borderColor: tag.color ?? undefined, color: tag.color ?? undefined, backgroundColor: (tag.color ?? "#6366f1") + "22" }}
              >
                <span className="h-1.5 w-1.5 rounded-full" style={{ backgroundColor: tag.color ?? undefined }} />
                {tag.name}
                <button
                  type="button"
                  onClick={() => toggleTag(tag.id)}
                  className="ml-0.5 opacity-60 hover:opacity-100"
                >
                  <FiX size={10} />
                </button>
              </span>
            ))}
          </div>
        )}

        <div className="mt-2 flex items-center justify-between gap-2">
          <div className="flex items-center gap-1">
            <button
              type="button"
              disabled={isSubmitting}
              onClick={() => fileInputRef.current?.click()}
              className="inline-flex items-center justify-center h-9 w-9 rounded-xl border border-brand-lines/25 bg-brand-bgLight/40 text-brand-text/60 hover:bg-brand-lines/10 hover:text-brand-accent transition-colors disabled:opacity-40"
              aria-label={t("post.compose.attachImage")}
              title={t("post.compose.attachImage")}
            >
              <FiPaperclip size={16} />
            </button>
            <input
              ref={fileInputRef}
              type="file"
              accept="*/*"
              multiple
              className="hidden"
              onChange={handleFileChange}
            />

            {/* Tag picker button — only when inside a hub with tags */}
            {hubTags.length > 0 && (
              <button
                type="button"
                disabled={isSubmitting}
                onClick={() => { setTagSearch(""); setTagModalOpen(true); }}
                className="inline-flex items-center gap-1.5 h-9 rounded-xl border border-brand-lines/25 bg-brand-bgLight/40 px-3 text-xs font-medium text-brand-text/60 hover:bg-brand-lines/10 hover:text-brand-accent transition-colors disabled:opacity-40"
              >
                <FiTag size={14} />
                Přidat tagy
                {selectedTags.size > 0 && (
                  <span className="flex h-4 w-4 items-center justify-center rounded-full bg-brand-accent text-[10px] font-bold text-white">
                    {selectedTags.size}
                  </span>
                )}
              </button>
            )}
          </div>

          <Button
            type="submit"
            disabled={isSubmitting || !hasContent}
            leftIcon={isSubmitting ? <Spinner size={14} /> : <FiSend size={14} />}
          >
            {isSubmitting
              ? t("post.compose.submitting")
              : t("post.compose.submit")}
          </Button>
        </div>
      </form>

      {/* Tag picker modal */}
      {tagModalOpen && (
        <div
          className="fixed inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-sm p-4"
          onClick={() => setTagModalOpen(false)}
        >
          <div
            className="w-full max-w-sm rounded-2xl border border-brand-lines/20 bg-brand-bg shadow-2xl"
            onClick={(e) => e.stopPropagation()}
          >
            {/* Header */}
            <div className="flex items-center justify-between border-b border-brand-lines/10 px-5 py-4">
              <h2 className="text-base font-semibold text-brand-text">Přidat tagy</h2>
              <button
                type="button"
                onClick={() => setTagModalOpen(false)}
                className="rounded-full p-1.5 text-brand-text/50 hover:bg-brand-lines/10 hover:text-brand-text transition-colors"
              >
                <FiX size={18} />
              </button>
            </div>

            {/* Search */}
            <div className="px-5 pt-4 pb-2">
              <div className="flex items-center gap-2 rounded-xl border border-brand-lines/25 bg-brand-bgLight/40 px-3 py-2">
                <FiSearch size={15} className="shrink-0 text-brand-text/40" />
                <input
                  autoFocus
                  value={tagSearch}
                  onChange={(e) => setTagSearch(e.target.value)}
                  placeholder="Hledat..."
                  className="flex-1 bg-transparent text-sm text-brand-text placeholder:text-brand-text/40 focus:outline-none"
                />
                {tagSearch && (
                  <button type="button" onClick={() => setTagSearch("")} className="text-brand-text/40 hover:text-brand-text/70">
                    <FiX size={13} />
                  </button>
                )}
              </div>
            </div>

            {/* Tag list */}
            <div className="max-h-72 overflow-y-auto px-5 py-2">
              {filteredTags.length === 0 && (
                <p className="py-6 text-center text-sm text-brand-text/40">Žádné tagy.</p>
              )}
              {filteredTags.map((tag) => {
                const active = selectedTags.has(tag.id);
                return (
                  <label
                    key={tag.id}
                    className="flex cursor-pointer items-center gap-3 rounded-xl px-2 py-2.5 hover:bg-brand-lines/5 transition-colors"
                  >
                    <input
                      type="checkbox"
                      checked={active}
                      onChange={() => toggleTag(tag.id)}
                      className="hidden"
                    />
                    {/* Custom checkbox */}
                    <span
                      className={[
                        "flex h-5 w-5 shrink-0 items-center justify-center rounded-full border-2 transition-colors",
                        active ? "border-transparent" : "border-brand-lines/30",
                      ].join(" ")}
                      style={{ backgroundColor: active ? (tag.color ?? "#6366f1") : undefined }}
                    >
                      {active && (
                        <svg width="10" height="8" viewBox="0 0 10 8" fill="none">
                          <path d="M1 4l3 3 5-6" stroke="white" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" />
                        </svg>
                      )}
                    </span>
                    {/* Tag pill preview */}
                    <span
                      className="rounded-full border px-3 py-0.5 text-xs font-semibold"
                      style={{
                        borderColor: tag.color ?? undefined,
                        color: tag.color ?? undefined,
                        backgroundColor: (tag.color ?? "#6366f1") + "22",
                      }}
                    >
                      {tag.name}
                    </span>
                    {tag.description && (
                      <span className="ml-auto truncate text-xs text-brand-text/40">{tag.description}</span>
                    )}
                  </label>
                );
              })}
            </div>

            {/* Footer */}
            <div className="flex justify-end gap-2 border-t border-brand-lines/10 px-5 py-4">
              <Button variant="ghost" size="sm" onClick={() => setTagModalOpen(false)}>
                Zrušit
              </Button>
              <Button variant="primary" size="sm" onClick={() => setTagModalOpen(false)}>
                Přidat
              </Button>
            </div>
          </div>
        </div>
      )}
    </>
  );
}
