import { Autocomplete, Box, Button, Group, Select, Stack, TagsInput, Text, Textarea } from "@mantine/core";
import { notifications } from "@mantine/notifications";
import { DragEvent, FormEvent, KeyboardEvent, useRef, useState } from "react";
import * as api from "../api";
import type { User } from "../types";

// CardForm: Solicitante (Autocomplete) intencionadamente NO hace submit en Enter.
// Enter dentro del Autocomplete deja que Mantine seleccione el item resaltado del
// dropdown sin cerrar el formulario. Submit solo via boton "Crear" o Ctrl+Enter
// en descripcion. Ver issue 0088.

export interface CardFormValues {
  requester: string;
  title: string;
  description: string;
  assignee_id: string | null;
  tags: string[];
}

interface Props {
  initial?: Partial<CardFormValues>;
  submitLabel?: string;
  users?: User[];
  requesterOptions?: string[];
  tagOptions?: string[];
  cardId?: string;
  onFileUploaded?: () => void;
  onSubmit: (v: CardFormValues) => Promise<void> | void;
  onCancel: () => void;
}

function markdownRef(filename: string, url: string, isImage: boolean): string {
  const safeName = filename.replace(/]/g, "");
  return isImage ? `![${safeName}](${url})` : `[${safeName}](${url})`;
}

export function CardForm({
  initial,
  submitLabel = "Guardar",
  users = [],
  requesterOptions = [],
  tagOptions = [],
  cardId,
  onFileUploaded,
  onSubmit,
  onCancel,
}: Props) {
  const [requester, setRequester] = useState(initial?.requester ?? "");
  const [title, setTitle] = useState(initial?.title ?? "");
  const [description, setDescription] = useState(initial?.description ?? "");
  const [assigneeId, setAssigneeId] = useState<string | null>(initial?.assignee_id ?? null);
  const [tags, setTags] = useState<string[]>(initial?.tags ?? []);
  const [dragOver, setDragOver] = useState(false);
  const [uploading, setUploading] = useState(false);
  const textareaRef = useRef<HTMLTextAreaElement>(null);

  const submit = async (e?: FormEvent) => {
    e?.preventDefault();
    const t = title.trim();
    if (!t) return;
    await onSubmit({
      requester: requester.trim(),
      title: t,
      description,
      assignee_id: assigneeId,
      tags,
    });
  };

  const textareaEnter = (e: KeyboardEvent<HTMLTextAreaElement>) => {
    if (e.key === "Enter" && (e.ctrlKey || e.metaKey)) {
      e.preventDefault();
      submit();
    }
  };

  const insertAtCursor = (snippet: string) => {
    const ta = textareaRef.current;
    if (!ta) {
      setDescription((d) => (d ? d + "\n" + snippet : snippet));
      return;
    }
    const start = ta.selectionStart ?? description.length;
    const end = ta.selectionEnd ?? description.length;
    const before = description.slice(0, start);
    const after = description.slice(end);
    const sep = before && !before.endsWith("\n") ? "\n" : "";
    const next = before + sep + snippet + after;
    setDescription(next);
    queueMicrotask(() => {
      ta.focus();
      const pos = (before + sep + snippet).length;
      ta.setSelectionRange(pos, pos);
    });
  };

  const handleFiles = async (files: FileList | File[]) => {
    if (!cardId) {
      notifications.show({ color: "yellow", message: "Guarda la tarjeta antes de subir archivos." });
      return;
    }
    setUploading(true);
    try {
      for (const file of Array.from(files)) {
        try {
          const cf = await api.uploadCardFile(cardId, file, "description");
          insertAtCursor(markdownRef(cf.filename, cf.url, cf.mime.startsWith("image/")));
          onFileUploaded?.();
        } catch (e) {
          notifications.show({ color: "red", message: `${file.name}: ${(e as Error).message}` });
        }
      }
    } finally {
      setUploading(false);
    }
  };

  const onDrop = (e: DragEvent<HTMLDivElement>) => {
    e.preventDefault();
    setDragOver(false);
    if (!e.dataTransfer.files || e.dataTransfer.files.length === 0) return;
    handleFiles(e.dataTransfer.files);
  };

  const onDragOver = (e: DragEvent<HTMLDivElement>) => {
    if (!cardId) return;
    if (!e.dataTransfer.types.includes("Files")) return;
    e.preventDefault();
    setDragOver(true);
  };

  const onDragLeave = (e: DragEvent<HTMLDivElement>) => {
    e.preventDefault();
    setDragOver(false);
  };

  return (
    <form onSubmit={submit}>
      <Stack gap="sm">
        <Textarea
          label="Tarea"
          value={title}
          onChange={(e) => setTitle(e.currentTarget.value)}
          tabIndex={1}
          required
          autoComplete="off"
          data-autofocus
          autosize
          minRows={1}
          maxRows={4}
          onKeyDown={(e) => {
            if (e.key === "Enter" && !e.shiftKey) {
              e.preventDefault();
              submit();
            }
          }}
        />
        <Autocomplete
          label="Solicitante"
          value={requester}
          onChange={setRequester}
          data={requesterOptions}
          tabIndex={2}
          autoComplete="off"
          data-field="requester"
          placeholder="Empieza a escribir y elige uno existente"
          limit={10}
          onKeyDown={(e) => {
            if (e.key === "Enter") e.preventDefault();
          }}
        />
        <Box
          onDrop={onDrop}
          onDragOver={onDragOver}
          onDragLeave={onDragLeave}
          style={{
            position: "relative",
            outline: dragOver ? "2px dashed var(--mantine-color-blue-5)" : undefined,
            outlineOffset: dragOver ? 2 : undefined,
            borderRadius: 4,
          }}
        >
          <Textarea
            ref={textareaRef}
            label="Descripcion"
            value={description}
            onChange={(e) => setDescription(e.currentTarget.value)}
            tabIndex={3}
            autosize
            minRows={3}
            maxRows={8}
            onKeyDown={textareaEnter}
            description={cardId ? "Ctrl+Enter para guardar. Arrastra archivos para adjuntar." : "Ctrl+Enter para guardar"}
          />
          {(dragOver || uploading) && (
            <Box
              style={{
                position: "absolute",
                inset: 0,
                background: "rgba(34,139,230,0.08)",
                display: "flex",
                alignItems: "center",
                justifyContent: "center",
                pointerEvents: "none",
                borderRadius: 4,
              }}
            >
              <Text size="sm" fw={500} c="blue">
                {uploading ? "Subiendo..." : "Suelta para adjuntar"}
              </Text>
            </Box>
          )}
        </Box>
        <Select
          label="Asignar a"
          placeholder="Sin asignar"
          value={assigneeId}
          onChange={(v) => setAssigneeId(v)}
          data={users.map((u) => ({
            value: u.id,
            label: u.display_name || u.username,
          }))}
          clearable
          searchable
          tabIndex={4}
        />
        <TagsInput
          label="Tags"
          value={tags}
          onChange={setTags}
          data={tagOptions}
          clearable
          tabIndex={5}
          placeholder="Enter para añadir; sugiere existentes"
          splitChars={[",", " "]}
        />
        <Group justify="flex-end" gap="xs" mt="xs">
          <Button variant="subtle" color="gray" tabIndex={7} type="button" onClick={onCancel}>
            Cancelar
          </Button>
          <Button tabIndex={6} type="submit" disabled={!title.trim()}>
            {submitLabel}
          </Button>
        </Group>
      </Stack>
    </form>
  );
}
