"use client";

import { useEffect, useState, useTransition } from "react";
import { useActionState } from "react";
import { useRouter } from "next/navigation";
import {
  updateTodoStatusAction,
  updateTodoAction,
  deleteTodoAction,
  addTodoNoteAction,
  addTodoSubtaskAction,
  toggleTodoSubtaskAction,
  deleteTodoSubtaskAction,
  addTodoAttachmentsAction,
  deleteTodoAttachmentAction,
} from "@/lib/actions/todos";
import { STATUS_LABELS, PRIORITY_LABELS, PRIORITY_COLORS, RECURRENCE_LABELS, labelColor } from "@/lib/todoConstants";
import { TagInput } from "@/components/admin/TagInput";
import { TodoPeoplePicker } from "@/components/admin/TodoPeoplePicker";
import { TodoRecurrenceFields } from "@/components/admin/TodoRecurrenceFields";
import type { StaffOption, OrderOption, TodoRow } from "@/components/admin/TodoBoard";
import type { TodoStatus, TodoPriority } from "@/models/Todo";
import { formatDateDE, formatDateTimeDE } from "@/lib/orderConstants";

export function TodoItem({
  todo,
  staffById,
  staffList,
  orderOptions,
  viewerId,
  canCreateForOthers,
  isOwn,
  canEditOthers,
  canDeleteOthers,
}: {
  todo: TodoRow;
  staffById: Map<string, StaffOption>;
  staffList: StaffOption[];
  orderOptions: OrderOption[];
  viewerId: string;
  canCreateForOthers: boolean;
  isOwn: boolean;
  canEditOthers: boolean;
  canDeleteOthers: boolean;
}) {
  const [pending, startTransition] = useTransition();
  const router = useRouter();
  const [noteText, setNoteText] = useState("");

  const canEdit = isOwn || canEditOthers;
  const canDelete = isOwn || canDeleteOthers;
  const assignee = staffById.get(todo.assignedToId);
  const linkedOrder = todo.orderId ? orderOptions.find((o) => o.id === todo.orderId) : null;
  const todayStr = new Date().toISOString().slice(0, 10);
  const isOverdue = todo.status !== "done" && Boolean(todo.dueDate) && (todo.dueDate as string).slice(0, 10) < todayStr;
  const subDone = todo.subtasks.filter((s) => s.done).length;

  function changeStatus(status: TodoStatus) {
    startTransition(async () => {
      await updateTodoStatusAction(todo.id, status);
      router.refresh();
    });
  }

  function submitNote() {
    if (!noteText.trim()) return;
    startTransition(async () => {
      await addTodoNoteAction(todo.id, noteText);
      setNoteText("");
      router.refresh();
    });
  }

  function remove() {
    if (!confirm(`ToDo „${todo.title}" wirklich löschen?`)) return;
    startTransition(async () => {
      await deleteTodoAction(todo.id);
      router.refresh();
    });
  }

  return (
    <div
      className={`bg-[var(--rk-surface)] border rounded-xl ${isOverdue ? "border-red-500/30" : "border-white/10"}`}
      style={{ borderLeft: `3px solid ${PRIORITY_COLORS[todo.priority]}` }}
    >
      <div className="flex flex-wrap items-center gap-3 p-4">
        <select
          value={todo.status}
          disabled={pending || !canEdit}
          onChange={(e) => changeStatus(e.target.value as TodoStatus)}
          className="bg-[var(--rk-bg)] border border-white/15 rounded-lg px-2 py-1 text-xs focus:outline-none focus:border-white/50 disabled:opacity-50 shrink-0"
        >
          {(Object.keys(STATUS_LABELS) as TodoStatus[]).map((s) => (
            <option key={s} value={s}>
              {STATUS_LABELS[s]}
            </option>
          ))}
        </select>
        <div className="flex-1 min-w-0">
          <p
            className={`text-sm font-medium ${
              todo.status === "done" ? "line-through text-[var(--rk-ink-muted)]" : "text-[var(--rk-ink)]"
            }`}
          >
            {todo.title}
          </p>
          {(todo.labels.length > 0 || todo.project) && (
            <div className="mt-1 flex flex-wrap items-center gap-1">
              {todo.project && (
                <span className="rounded-full border border-white/20 bg-white/5 px-2 py-0.5 text-[0.6rem] uppercase tracking-[0.06em] text-[var(--rk-ink-muted)]">
                  ▤ {todo.project}
                </span>
              )}
              {todo.labels.map((l) => (
                <span
                  key={l}
                  className="rounded-full px-2 py-0.5 text-[0.6rem] font-medium"
                  style={{ backgroundColor: `${labelColor(l)}22`, color: labelColor(l) }}
                >
                  {l}
                </span>
              ))}
            </div>
          )}
          <p className="text-xs text-[var(--rk-ink-muted)] mt-0.5 flex flex-wrap items-center gap-x-1.5">
            {assignee && (
              <span className="flex items-center gap-1">
                {assignee.avatarPath && (
                  // eslint-disable-next-line @next/next/no-img-element
                  <img
                    src={`/api/avatars/${todo.assignedToId}/${assignee.avatarPath}`}
                    alt=""
                    className="w-4 h-4 rounded-full object-cover border border-white/15"
                  />
                )}
                {assignee.name}
              </span>
            )}
            {todo.additionalAssigneeIds.length > 0 && (
              <span>
                +{" "}
                {todo.additionalAssigneeIds
                  .map((id) => staffById.get(id)?.name)
                  .filter(Boolean)
                  .join(", ")}
              </span>
            )}
            {todo.watcherIds.length > 0 && <span>· 👁 {todo.watcherIds.length}</span>}
            {todo.dueDate && (
              <span className={isOverdue ? "text-red-400" : ""}>
                · Fällig {formatDateDE(new Date(todo.dueDate))}
              </span>
            )}
            {linkedOrder && (
              <a href={`/de/admin/orders/${todo.orderId}`} className="underline hover:text-[var(--rk-ink)]">
                · {linkedOrder.label}
              </a>
            )}
            {todo.recurrence !== "none" && <span>· 🔁 {RECURRENCE_LABELS[todo.recurrence]}</span>}
            {todo.subtasks.length > 0 && (
              <span className={subDone === todo.subtasks.length ? "text-emerald-400" : ""}>
                · ☑ {subDone}/{todo.subtasks.length}
              </span>
            )}
          </p>
        </div>
        <span
          className="text-[0.6rem] uppercase tracking-[0.08em] shrink-0 border rounded-full px-2 py-0.5"
          style={{ borderColor: `${PRIORITY_COLORS[todo.priority]}66`, color: PRIORITY_COLORS[todo.priority] }}
        >
          {PRIORITY_LABELS[todo.priority]}
        </span>
      </div>

      <details className="border-t border-white/5">
        <summary className="text-xs cursor-pointer text-[var(--rk-ink-muted)] hover:text-[var(--rk-ink)] px-4 py-2 transition-colors">
          Details
          {todo.subtasks.length > 0 ? ` · ${subDone}/${todo.subtasks.length} Unteraufgaben` : ""}
          {todo.notes.length > 0 ? ` · ${todo.notes.length} Notiz${todo.notes.length === 1 ? "" : "en"}` : ""}
        </summary>
        <div className="px-4 pb-4 flex flex-col gap-3">
          {canEdit ? (
            <EditTodoForm
              todo={todo}
              staffList={staffList}
              orderOptions={orderOptions}
              viewerId={viewerId}
              canCreateForOthers={canCreateForOthers}
            />
          ) : (
            todo.description && <p className="text-sm text-[var(--rk-ink-muted)] whitespace-pre-line">{todo.description}</p>
          )}

          <SubtaskSection todoId={todo.id} subtasks={todo.subtasks} canEdit={canEdit} />

          <AttachmentSection
            todoId={todo.id}
            attachments={todo.attachments}
            canEdit={canEdit}
          />

          {todo.notes.length > 0 && (
            <div className="flex flex-col gap-2 border-t border-white/5 pt-3">
              {todo.notes.map((n) => (
                <div key={n.id} className="text-xs">
                  <span className="text-[var(--rk-ink)]">{staffById.get(n.authorId)?.name ?? "?"}</span>{" "}
                  <span className="text-[var(--rk-ink-muted)]">{formatDateTimeDE(new Date(n.createdAt))}</span>
                  <p className="text-[var(--rk-ink-muted)] mt-0.5 whitespace-pre-line">{n.text}</p>
                </div>
              ))}
            </div>
          )}

          {todo.activity.length > 0 && (
            <details className="border-t border-white/5 pt-3 text-xs">
              <summary className="cursor-pointer text-[var(--rk-ink-muted)] hover:text-[var(--rk-ink)]">
                Verlauf ({todo.activity.length})
              </summary>
              <ul className="mt-2 flex flex-col gap-1">
                {[...todo.activity].reverse().map((a, i) => (
                  <li key={i} className="text-[var(--rk-ink-muted)]">
                    <span className="text-[var(--rk-ink)]">{staffById.get(a.actorId)?.name ?? "?"}</span> · {a.text} ·{" "}
                    {formatDateTimeDE(new Date(a.createdAt))}
                  </li>
                ))}
              </ul>
            </details>
          )}

          <div className="flex items-center gap-2 border-t border-white/5 pt-3">
            <input
              value={noteText}
              disabled={pending}
              onChange={(e) => setNoteText(e.target.value)}
              placeholder="Notiz… (@Name erwähnt jemanden)"
              className="flex-1 bg-[var(--rk-bg)] border border-white/15 rounded-lg px-2.5 py-1.5 text-xs focus:outline-none focus:border-white/50 disabled:opacity-50"
            />
            <button
              type="button"
              disabled={pending || !noteText.trim()}
              onClick={submitNote}
              className="text-xs border border-white/30 rounded-lg px-3 py-1.5 hover:border-white disabled:opacity-50 shrink-0"
            >
              Hinzufügen
            </button>
          </div>

          {canDelete && (
            <button
              type="button"
              disabled={pending}
              onClick={remove}
              className="self-start text-xs text-red-400/80 hover:text-red-400 transition-colors disabled:opacity-50"
            >
              ToDo löschen
            </button>
          )}
        </div>
      </details>
    </div>
  );
}

function EditTodoForm({
  todo,
  staffList,
  orderOptions,
  viewerId,
  canCreateForOthers,
}: {
  todo: TodoRow;
  staffList: StaffOption[];
  orderOptions: OrderOption[];
  viewerId: string;
  canCreateForOthers: boolean;
}) {
  const [state, formAction, pending] = useActionState(updateTodoAction.bind(null, todo.id), {});
  const router = useRouter();

  useEffect(() => {
    if (state.success) router.refresh();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [state.success]);

  return (
    <form action={formAction} className="flex flex-col gap-2.5">
      <label className="flex flex-col gap-1 text-xs">
        <span className="text-[var(--rk-ink-muted)]">Titel</span>
        <input
          name="title"
          defaultValue={todo.title}
          required
          maxLength={200}
          className="bg-[var(--rk-bg)] border border-white/15 rounded-lg px-2.5 py-1.5 text-xs text-[var(--rk-ink)] focus:outline-none focus:border-white/50"
        />
      </label>
      <label className="flex flex-col gap-1 text-xs">
        <span className="text-[var(--rk-ink-muted)]">Beschreibung</span>
        <textarea
          name="description"
          defaultValue={todo.description}
          rows={2}
          maxLength={4000}
          className="bg-[var(--rk-bg)] border border-white/15 rounded-lg px-2.5 py-1.5 text-xs text-[var(--rk-ink)] focus:outline-none focus:border-white/50 resize-y"
        />
      </label>
      <div className="grid grid-cols-1 sm:grid-cols-3 gap-2.5">
        <label className="flex flex-col gap-1 text-xs">
          <span className="text-[var(--rk-ink-muted)]">Zuständig</span>
          <select
            name="assignedToId"
            defaultValue={todo.assignedToId}
            disabled={!canCreateForOthers && todo.assignedToId !== viewerId}
            className="bg-[var(--rk-bg)] border border-white/15 rounded-lg px-2.5 py-1.5 text-xs text-[var(--rk-ink)] focus:outline-none focus:border-white/50 disabled:opacity-60"
          >
            {staffList.map((s) => (
              <option key={s.id} value={s.id}>
                {s.id === viewerId ? `${s.name} (ich)` : s.name}
              </option>
            ))}
          </select>
        </label>
        <label className="flex flex-col gap-1 text-xs">
          <span className="text-[var(--rk-ink-muted)]">Priorität</span>
          <select
            name="priority"
            defaultValue={todo.priority}
            className="bg-[var(--rk-bg)] border border-white/15 rounded-lg px-2.5 py-1.5 text-xs text-[var(--rk-ink)] focus:outline-none focus:border-white/50"
          >
            {(Object.keys(PRIORITY_LABELS) as TodoPriority[]).map((p) => (
              <option key={p} value={p}>
                {PRIORITY_LABELS[p]}
              </option>
            ))}
          </select>
        </label>
        <label className="flex flex-col gap-1 text-xs">
          <span className="text-[var(--rk-ink-muted)]">Fällig am</span>
          <input
            type="date"
            name="dueDate"
            defaultValue={todo.dueDate ? todo.dueDate.slice(0, 10) : ""}
            className="bg-[var(--rk-bg)] border border-white/15 rounded-lg px-2.5 py-1.5 text-xs text-[var(--rk-ink)] focus:outline-none focus:border-white/50"
          />
        </label>
      </div>
      <div className="grid grid-cols-1 sm:grid-cols-2 gap-2.5">
        <label className="flex flex-col gap-1 text-xs">
          <span className="text-[var(--rk-ink-muted)]">Labels</span>
          <TagInput name="labels" defaultValue={todo.labels.join(", ")} placeholder="Label + Enter" />
        </label>
        <label className="flex flex-col gap-1 text-xs">
          <span className="text-[var(--rk-ink-muted)]">Projekt / Liste</span>
          <input
            name="project"
            defaultValue={todo.project}
            maxLength={80}
            className="bg-[var(--rk-bg)] border border-white/15 rounded-lg px-2.5 py-1.5 text-xs text-[var(--rk-ink)] focus:outline-none focus:border-white/50"
          />
        </label>
      </div>
      {canCreateForOthers && (
        <details className="rounded-lg border border-white/10 p-2.5 text-xs">
          <summary className="cursor-pointer text-[var(--rk-ink-muted)]">Weitere Personen</summary>
          <input type="hidden" name="peopleEdited" value="1" />
          <div className="mt-2 flex flex-col gap-2">
            <div>
              <p className="mb-1 text-[var(--rk-ink-muted)]">Weitere Zuständige</p>
              <TodoPeoplePicker name="additionalAssigneeIds" staffList={staffList} defaultIds={todo.additionalAssigneeIds} />
            </div>
            <div>
              <p className="mb-1 text-[var(--rk-ink-muted)]">Beobachter</p>
              <TodoPeoplePicker name="watcherIds" staffList={staffList} defaultIds={todo.watcherIds} />
            </div>
          </div>
        </details>
      )}
      <TodoRecurrenceFields
        compact
        defaultRecurrence={todo.recurrence}
        defaultInterval={todo.recurrenceInterval}
        defaultWeekdays={todo.recurrenceWeekdays}
        defaultEndDate={todo.recurrenceEndDate ? todo.recurrenceEndDate.slice(0, 10) : ""}
      />
      {orderOptions.length > 0 && (
        <label className="flex flex-col gap-1 text-xs">
          <span className="text-[var(--rk-ink-muted)]">Auftragsbezug</span>
          <select
            name="orderId"
            defaultValue={todo.orderId ?? ""}
            className="bg-[var(--rk-bg)] border border-white/15 rounded-lg px-2.5 py-1.5 text-xs text-[var(--rk-ink)] focus:outline-none focus:border-white/50"
          >
            <option value="">Kein Auftrag</option>
            {orderOptions.map((o) => (
              <option key={o.id} value={o.id}>
                {o.label}
              </option>
            ))}
          </select>
        </label>
      )}
      <button
        type="submit"
        disabled={pending}
        className="self-start text-xs border border-white/30 rounded-lg px-3 py-1.5 hover:border-white disabled:opacity-50"
      >
        {pending ? "…" : "Speichern"}
      </button>
      {state.error && <p className="text-xs text-red-400">{state.error}</p>}
    </form>
  );
}

function SubtaskSection({
  todoId,
  subtasks,
  canEdit,
}: {
  todoId: string;
  subtasks: { id: string; text: string; done: boolean }[];
  canEdit: boolean;
}) {
  const [pending, startTransition] = useTransition();
  const router = useRouter();
  const [text, setText] = useState("");

  function add() {
    if (!text.trim()) return;
    startTransition(async () => {
      await addTodoSubtaskAction(todoId, text);
      setText("");
      router.refresh();
    });
  }
  function toggle(id: string, done: boolean) {
    startTransition(async () => {
      await toggleTodoSubtaskAction(todoId, id, done);
      router.refresh();
    });
  }
  function remove(id: string) {
    startTransition(async () => {
      await deleteTodoSubtaskAction(todoId, id);
      router.refresh();
    });
  }

  if (subtasks.length === 0 && !canEdit) return null;

  return (
    <div className="flex flex-col gap-1.5 border-t border-white/5 pt-3">
      <p className="text-xs uppercase tracking-[0.1em] text-[var(--rk-ink-muted)]">Unteraufgaben</p>
      {subtasks.map((s) => (
        <div key={s.id} className="flex items-center gap-2 text-sm">
          <input
            type="checkbox"
            checked={s.done}
            disabled={pending || !canEdit}
            onChange={(e) => toggle(s.id, e.target.checked)}
            className="h-3.5 w-3.5 shrink-0"
          />
          <span className={`flex-1 ${s.done ? "text-[var(--rk-ink-muted)] line-through" : ""}`}>{s.text}</span>
          {canEdit && (
            <button
              type="button"
              disabled={pending}
              onClick={() => remove(s.id)}
              className="text-[var(--rk-ink-muted)] transition-colors hover:text-red-400 disabled:opacity-50"
              aria-label="Unteraufgabe entfernen"
            >
              ×
            </button>
          )}
        </div>
      ))}
      {canEdit && (
        <div className="mt-1 flex items-center gap-2">
          <input
            value={text}
            disabled={pending}
            onChange={(e) => setText(e.target.value)}
            onKeyDown={(e) => {
              if (e.key === "Enter") {
                e.preventDefault();
                add();
              }
            }}
            placeholder="Unteraufgabe hinzufügen…"
            className="flex-1 bg-[var(--rk-bg)] border border-white/15 rounded-lg px-2.5 py-1.5 text-xs focus:outline-none focus:border-white/50 disabled:opacity-50"
          />
          <button
            type="button"
            disabled={pending || !text.trim()}
            onClick={add}
            className="shrink-0 rounded-lg border border-white/30 px-3 py-1.5 text-xs hover:border-white disabled:opacity-50"
          >
            +
          </button>
        </div>
      )}
    </div>
  );
}

function AttachmentSection({
  todoId,
  attachments,
  canEdit,
}: {
  todoId: string;
  attachments: { filename: string; storedName: string; size: number; mimeType: string }[];
  canEdit: boolean;
}) {
  const router = useRouter();
  const [pending, startTransition] = useTransition();
  const [state, formAction, uploading] = useActionState(addTodoAttachmentsAction.bind(null, todoId), {} as { error?: string; success?: boolean });

  useEffect(() => {
    if (state.success) router.refresh();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [state.success]);

  if (attachments.length === 0 && !canEdit) return null;
  const kb = (n: number) => (n < 1024 * 1024 ? `${Math.round(n / 1024)} KB` : `${(n / 1024 / 1024).toFixed(1)} MB`);

  return (
    <div className="flex flex-col gap-1.5 border-t border-white/5 pt-3">
      <p className="text-xs uppercase tracking-[0.1em] text-[var(--rk-ink-muted)]">Anhänge</p>
      {attachments.map((a) => (
        <div key={a.storedName} className="flex items-center gap-2 text-xs">
          <a
            href={`/api/files/todos/${todoId}/${a.storedName}`}
            target="_blank"
            rel="noopener noreferrer"
            className="flex-1 truncate underline hover:text-[var(--rk-ink)]"
          >
            {a.filename}
          </a>
          <span className="shrink-0 text-[var(--rk-ink-muted)]">{kb(a.size)}</span>
          {canEdit && (
            <button
              type="button"
              disabled={pending}
              onClick={() =>
                startTransition(async () => {
                  await deleteTodoAttachmentAction(todoId, a.storedName);
                  router.refresh();
                })
              }
              className="text-[var(--rk-ink-muted)] transition-colors hover:text-red-400 disabled:opacity-50"
              aria-label="Anhang entfernen"
            >
              ×
            </button>
          )}
        </div>
      ))}
      {canEdit && (
        <form action={formAction} className="mt-1 flex items-center gap-2">
          <input
            name="files"
            type="file"
            multiple
            accept="image/jpeg,image/png,image/webp,image/heic,application/pdf"
            className="text-xs"
          />
          <button
            type="submit"
            disabled={uploading}
            className="shrink-0 rounded-lg border border-white/30 px-3 py-1 text-xs hover:border-white disabled:opacity-50"
          >
            {uploading ? "…" : "Hochladen"}
          </button>
        </form>
      )}
      {state.error && <p className="text-xs text-red-400">{state.error}</p>}
    </div>
  );
}
