"use client";

import { useEffect, useMemo, useState } from "react";
import type { TaskStatus } from "@slackwsh/contracts";
import { avatarColor, initials } from "../lib/avatar";
import { toLocalDateInput } from "../lib/datetime";
import type { ConversationRow } from "../lib/conversations";
import { IconX } from "./icons";

export interface TaskModalMember {
  user: { id: string | number; name: string; email: string };
}

export interface TaskModalValues {
  title: string;
  description: string;
  assigneeUserId: string | null;
  dueAt: string | null; // ISO datetime or null
  channelId: string | null;
  status: TaskStatus;
}

/**
 * Create/edit Task dialog. Invoked from both /tasks (create/edit a
 * standalone task) and the channel message hover action ("create task from
 * message", pre-filled from message text) — the one modal in this codebase
 * that's genuinely shared across two pages with two different submit
 * targets, unlike e.g. channel-invite-modal which is only ever opened from
 * one place. Markup mirrors that modal's backdrop/dialog structure.
 */
export function TaskModal({
  title,
  mode,
  initial,
  members,
  channels,
  /** When set, the channel this task is tied to is fixed (e.g. "create task
   * from message" — the source message's channel) — shown as a read-only
   * label instead of the picker, and channelId edits are not offered. Passed
   * pre-formatted by the caller, since a room reads "#name" but a DM reads as
   * the peer's name. */
  lockedChannelName,
  createdByName,
  busy,
  error,
  onClose,
  onSubmit,
  onDelete,
}: {
  title: string;
  mode: "create" | "edit";
  initial: Partial<TaskModalValues>;
  members: TaskModalMember[];
  channels: ConversationRow[];
  lockedChannelName?: string | null;
  /** Read-only — who created the task. Shown on edit, not create. */
  createdByName?: string | null;
  busy?: boolean;
  error?: string | null;
  onClose: () => void;
  onSubmit: (values: TaskModalValues) => void;
  /** Edit mode only — omitted when the caller has nothing to delete yet. */
  onDelete?: () => void;
}) {
  const [values, setValues] = useState<TaskModalValues>({
    title: initial.title ?? "",
    description: initial.description ?? "",
    assigneeUserId: initial.assigneeUserId ?? null,
    dueAt: initial.dueAt ?? null,
    channelId: initial.channelId ?? null,
    status: initial.status ?? "todo",
  });

  // The <input type="date"> value must be the *local* calendar date, and
  // dueAt is stored as an ISO instant at local midnight — so slicing the ISO
  // string would render the day before for any timezone ahead of UTC (and a
  // saved date would drift a day every time the modal was reopened).
  const dueDateValue = values.dueAt ? toLocalDateInput(new Date(values.dueAt)) : "";

  useEffect(() => {
    function onKeyDown(e: KeyboardEvent) {
      if (e.key === "Escape") onClose();
    }
    window.addEventListener("keydown", onKeyDown);
    return () => window.removeEventListener("keydown", onKeyDown);
  }, [onClose]);

  const sortedMembers = useMemo(() => [...members].sort((a, b) => a.user.name.localeCompare(b.user.name)), [members]);

  function submit() {
    if (!values.title.trim() || busy) return;
    onSubmit({ ...values, title: values.title.trim() });
  }

  return (
    <div className="channel-invite-backdrop" role="presentation" onClick={onClose}>
      <div
        className="task-modal"
        role="dialog"
        aria-modal="true"
        aria-labelledby="task-modal-title"
        onClick={(e) => e.stopPropagation()}
      >
        <div className="channel-invite-head">
          <div>
            <h2 id="task-modal-title">{title}</h2>
            <p>{mode === "create" ? "Assign it to someone, or leave it unassigned for now." : "Update the details below."}</p>
          </div>
          <button className="thread-close" type="button" onClick={onClose} aria-label="Close">
            <IconX />
          </button>
        </div>

        <div className="task-modal-body">
          <label className="task-modal-field">
            <span>Title</span>
            <input
              type="text"
              value={values.title}
              maxLength={200}
              autoFocus
              onChange={(e) => setValues((v) => ({ ...v, title: e.target.value }))}
              placeholder="What needs to happen?"
            />
          </label>

          {createdByName && (
            <p className="task-modal-created-by">Created by {createdByName}</p>
          )}

          <label className="task-modal-field">
            <span>Description</span>
            <textarea
              value={values.description}
              maxLength={10_000}
              rows={3}
              onChange={(e) => setValues((v) => ({ ...v, description: e.target.value }))}
              placeholder="Add more detail (optional)"
            />
          </label>

          <div className="task-modal-row">
            <label className="task-modal-field">
              <span>Due date</span>
              <input
                type="date"
                value={dueDateValue}
                onChange={(e) => {
                  const raw = e.target.value;
                  setValues((v) => ({ ...v, dueAt: raw ? new Date(`${raw}T00:00:00`).toISOString() : null }));
                }}
              />
            </label>

            <label className="task-modal-field">
              <span>Channel</span>
              {lockedChannelName != null ? (
                <input type="text" value={lockedChannelName} disabled />
              ) : (
                <select
                  value={values.channelId ?? ""}
                  onChange={(e) => setValues((v) => ({ ...v, channelId: e.target.value || null }))}
                >
                  <option value="">No channel</option>
                  {channels.map((row) => (
                    <option key={row.channel.id} value={row.channel.id}>
                      #{row.channel.name ?? "untitled"}
                    </option>
                  ))}
                </select>
              )}
            </label>
          </div>

          {mode === "edit" && (
            <label className="task-modal-field">
              <span>Status</span>
              <select
                value={values.status}
                onChange={(e) => setValues((v) => ({ ...v, status: e.target.value as TaskStatus }))}
              >
                <option value="todo">To do</option>
                <option value="in_progress">In progress</option>
                <option value="done">Done</option>
              </select>
            </label>
          )}

          <div className="task-modal-field">
            <span>Assignee</span>
            <div className="task-modal-assignees">
              <button
                type="button"
                className={values.assigneeUserId === null ? "channel-invite-row selected" : "channel-invite-row"}
                onClick={() => setValues((v) => ({ ...v, assigneeUserId: null }))}
              >
                <span className="list-row-avatar" style={{ background: "var(--surface-chip)", color: "var(--ink-mid)" }}>
                  —
                </span>
                <span className="channel-invite-meta">
                  <strong>Unassigned</strong>
                </span>
                <span className="channel-invite-check" aria-hidden="true">
                  {values.assigneeUserId === null ? "✓" : ""}
                </span>
              </button>
              {sortedMembers.map((row) => {
                const id = String(row.user.id);
                const selected = values.assigneeUserId === id;
                const color = avatarColor(id);
                return (
                  <button
                    key={id}
                    type="button"
                    className={selected ? "channel-invite-row selected" : "channel-invite-row"}
                    onClick={() => setValues((v) => ({ ...v, assigneeUserId: id }))}
                  >
                    <span className="list-row-avatar" style={{ background: color.bg, color: color.fg }}>
                      {initials(row.user.name)}
                    </span>
                    <span className="channel-invite-meta">
                      <strong>{row.user.name}</strong>
                      <span>{row.user.email}</span>
                    </span>
                    <span className="channel-invite-check" aria-hidden="true">
                      {selected ? "✓" : ""}
                    </span>
                  </button>
                );
              })}
            </div>
          </div>

          {error && <p className="error-text">{error}</p>}
        </div>

        <div className="channel-invite-foot">
          {mode === "edit" && onDelete && (
            <button className="screen-btn danger task-modal-delete" type="button" disabled={busy} onClick={onDelete}>
              Delete
            </button>
          )}
          <button className="screen-btn" type="button" onClick={onClose}>
            Cancel
          </button>
          <button className="screen-btn primary" type="button" disabled={busy || !values.title.trim()} onClick={submit}>
            {busy ? "Saving…" : mode === "create" ? "Create task" : "Save changes"}
          </button>
        </div>
      </div>
    </div>
  );
}
