"use client";

import Link from "next/link";
import { useRouter } from "next/navigation";
import { useEffect, useRef, useState, type FormEvent } from "react";
import { api, ApiError, type WorkspaceStatus } from "../lib/api";
import { UserAvatar } from "./UserAvatar";
import { IconBellOff, IconCalendar, IconCheck, IconChevron, IconX } from "./icons";

const SUGGESTIONS = [
  { emoji: "🟢", text: "Available", duration: "never" },
  { emoji: "📅", text: "In a meeting", duration: "1h" },
  { emoji: "🚗", text: "Commuting", duration: "1h" },
  { emoji: "🤒", text: "Out sick", duration: "today" },
  { emoji: "🏝️", text: "Vacationing", duration: "week" },
  { emoji: "🏠", text: "Working remotely", duration: "today" },
] as const;

type Dialog = "status" | "schedule" | "automatic" | null;

interface RecentStatus {
  emoji: string;
  text: string;
  duration: string;
  customExpiry?: string;
  pauseNotifications?: boolean;
}

const MAX_RECENT_STATUSES = 5;

function recentStatusKey(workspaceId: string, userId?: string | number | null) {
  return `connecthub:recent-statuses:${workspaceId}:${userId ?? "me"}`;
}

function durationLabel(duration: string) {
  if (duration === "30m") return "30 minutes";
  if (duration === "1h") return "1 hour";
  if (duration === "4h") return "4 hours";
  if (duration === "today") return "Today";
  if (duration === "week") return "This week";
  if (duration === "never") return "Don't clear";
  return "Custom";
}

function localInput(date: Date) {
  const offset = date.getTimezoneOffset() * 60_000;
  return new Date(date.getTime() - offset).toISOString().slice(0, 16);
}

function endOfToday() {
  const date = new Date();
  date.setHours(23, 59, 59, 999);
  return date;
}

function endOfWeek() {
  const date = endOfToday();
  const daysToFriday = (5 - date.getDay() + 7) % 7;
  date.setDate(date.getDate() + daysToFriday);
  return date;
}

function expiryFrom(duration: string, custom: string): string | null {
  if (duration === "never") return null;
  if (duration === "custom") return custom ? new Date(custom).toISOString() : null;
  if (duration === "today") return endOfToday().toISOString();
  if (duration === "week") return endOfWeek().toISOString();
  const hours = duration === "30m" ? 0.5 : duration === "4h" ? 4 : 1;
  return new Date(Date.now() + hours * 3_600_000).toISOString();
}

function readableWhen(value: string) {
  return new Date(value).toLocaleString([], { weekday: "short", month: "short", day: "numeric", hour: "numeric", minute: "2-digit" });
}

function errorText(error: unknown) {
  if (error instanceof ApiError && error.body && typeof error.body === "object") {
    const message = (error.body as { message?: unknown }).message;
    if (typeof message === "string") return message;
    if (Array.isArray(message)) return message.join(", ");
  }
  return error instanceof Error ? error.message : String(error);
}

export function StatusControls({
  workspaceId,
  userId,
  name,
  avatarUrl,
}: {
  workspaceId: string;
  userId?: string | number | null;
  name?: string | null;
  avatarUrl?: string | null;
}) {
  const router = useRouter();
  const rootRef = useRef<HTMLDivElement>(null);
  const [open, setOpen] = useState(false);
  const [dialog, setDialog] = useState<Dialog>(null);
  const [status, setStatusState] = useState<WorkspaceStatus | null>(null);
  const [busy, setBusy] = useState(false);
  const [signingOut, setSigningOut] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [emoji, setEmoji] = useState("💬");
  const [text, setText] = useState("");
  const [duration, setDuration] = useState("today");
  const [customExpiry, setCustomExpiry] = useState("");
  const [pauseNotifications, setPauseNotifications] = useState(false);
  const [recentStatuses, setRecentStatuses] = useState<RecentStatus[]>([]);
  const [editingScheduleId, setEditingScheduleId] = useState<number | null>(null);
  const [startsAt, setStartsAt] = useState(() => localInput(new Date(Date.now() + 5 * 60_000)));
  const [endsAt, setEndsAt] = useState(() => localInput(new Date(Date.now() + 65 * 60_000)));
  const [automatic, setAutomatic] = useState({
    connect: true,
    focus: true,
    outsideWorkingHours: true,
    workHoursStart: "09:00",
    workHoursEnd: "17:00",
    workingDays: [1, 2, 3, 4, 5] as number[],
  });

  async function refresh() {
    try {
      const next = await api.myStatus(workspaceId);
      setStatusState(next);
      setAutomatic({
        connect: next.automatic.connect,
        focus: next.automatic.focus,
        outsideWorkingHours: next.automatic.outsideWorkingHours,
        workHoursStart: next.automatic.workHoursStart,
        workHoursEnd: next.automatic.workHoursEnd,
        workingDays: next.automatic.workingDays,
      });
    } catch {
      // Status controls remain unobtrusive while the workspace is loading.
    }
  }

  useEffect(() => {
    void refresh();
    const onChanged = (event: Event) => {
      const id = (event as CustomEvent<{ workspaceId?: string | number }>).detail?.workspaceId;
      if (id == null || String(id) === workspaceId) void refresh();
    };
    window.addEventListener("connecthub:member-status-changed", onChanged);
    const timer = window.setInterval(() => void refresh(), 60_000);
    return () => {
      window.clearInterval(timer);
      window.removeEventListener("connecthub:member-status-changed", onChanged);
    };
  }, [workspaceId]);

  useEffect(() => {
    try {
      const saved = window.localStorage.getItem(recentStatusKey(workspaceId, userId));
      const parsed = saved ? JSON.parse(saved) : [];
      setRecentStatuses(Array.isArray(parsed) ? parsed.slice(0, MAX_RECENT_STATUSES) : []);
    } catch {
      setRecentStatuses([]);
    }
  }, [workspaceId, userId]);

  useEffect(() => {
    if (!open) return;
    const close = (event: PointerEvent) => {
      if (!rootRef.current?.contains(event.target as Node)) setOpen(false);
    };
    window.addEventListener("pointerdown", close);
    return () => window.removeEventListener("pointerdown", close);
  }, [open]);

  const effective = status?.effective;
  const statusSummary = effective?.text ? `${effective.emoji ?? "💬"} ${effective.text}` : "Update your status";
  const focusOn = status?.automatic.focusModeEnabled ?? false;

  function announce(next: WorkspaceStatus) {
    setStatusState(next);
    setError(null);
    window.dispatchEvent(new CustomEvent("connecthub:status-changed", { detail: { workspaceId, status: next } }));
    window.dispatchEvent(new CustomEvent("connecthub:member-status-changed", { detail: { workspaceId, userId } }));
  }

  function openStatusEditor() {
    setText(status?.manual.text ?? "");
    setEmoji(status?.manual.emoji ?? "💬");
    setDuration(status?.manual.expiresAt ? "custom" : "today");
    setCustomExpiry(status?.manual.expiresAt ? localInput(new Date(status.manual.expiresAt)) : "");
    setPauseNotifications(status?.manual.pauseNotifications ?? false);
    setError(null);
    setOpen(false);
    setDialog("status");
  }

  function openSchedule(schedule?: WorkspaceStatus["schedules"][number]) {
    setEditingScheduleId(schedule?.id ?? null);
    setText(schedule?.text ?? "");
    setEmoji(schedule?.emoji ?? "💬");
    setStartsAt(localInput(schedule ? new Date(schedule.startsAt) : new Date(Date.now() + 5 * 60_000)));
    setEndsAt(localInput(schedule ? new Date(schedule.endsAt) : new Date(Date.now() + 65 * 60_000)));
    setPauseNotifications(schedule?.pauseNotifications ?? false);
    setError(null);
    setOpen(false);
    setDialog("schedule");
  }

  async function mutate(run: () => Promise<WorkspaceStatus>, close = true) {
    setBusy(true);
    setError(null);
    try {
      announce(await run());
      if (close) setDialog(null);
      return true;
    } catch (err) {
      setError(errorText(err));
      return false;
    } finally {
      setBusy(false);
    }
  }

  function rememberRecent(recent: RecentStatus) {
    const normalized = { ...recent, text: recent.text.trim(), emoji: recent.emoji || "💬" };
    const next = [
      normalized,
      ...recentStatuses.filter((item) => item.text.toLowerCase() !== normalized.text.toLowerCase() || item.emoji !== normalized.emoji),
    ].slice(0, MAX_RECENT_STATUSES);
    setRecentStatuses(next);
    window.localStorage.setItem(recentStatusKey(workspaceId, userId), JSON.stringify(next));
  }

  function removeRecent(index: number) {
    const next = recentStatuses.filter((_, itemIndex) => itemIndex !== index);
    setRecentStatuses(next);
    window.localStorage.setItem(recentStatusKey(workspaceId, userId), JSON.stringify(next));
  }

  function chooseRecent(recent: RecentStatus) {
    setEmoji(recent.emoji);
    setText(recent.text);
    setDuration(recent.duration === "custom" && (!recent.customExpiry || new Date(recent.customExpiry) <= new Date()) ? "today" : recent.duration);
    setCustomExpiry(recent.customExpiry ?? "");
    setPauseNotifications(recent.pauseNotifications ?? false);
  }

  async function saveStatus(event: FormEvent) {
    event.preventDefault();
    const expiresAt = expiryFrom(duration, customExpiry);
    if (duration === "custom" && !customExpiry) {
      setError("Choose when this status should clear.");
      return;
    }
    const saved = await mutate(() => api.setStatus(workspaceId, { text, emoji, expiresAt, pauseNotifications }));
    if (saved) rememberRecent({ emoji, text, duration, customExpiry, pauseNotifications });
  }

  async function saveSchedule(event: FormEvent) {
    event.preventDefault();
    const input = {
      text,
      emoji,
      startsAt: new Date(startsAt).toISOString(),
      endsAt: new Date(endsAt).toISOString(),
      pauseNotifications,
    };
    await mutate(() =>
      editingScheduleId == null
        ? api.createScheduledStatus(workspaceId, input)
        : api.updateScheduledStatus(workspaceId, editingScheduleId, input),
    );
  }

  async function saveAutomatic(event: FormEvent) {
    event.preventDefault();
    await mutate(() => api.updateAutomaticStatus(workspaceId, automatic));
  }

  async function signOut() {
    if (signingOut) return;
    setSigningOut(true);
    setOpen(false);
    try {
      await api.logout();
    } finally {
      router.replace("/login");
      router.refresh();
    }
  }

  return (
    <div className="status-controls" ref={rootRef}>
      <button
        className="gnav-user"
        type="button"
        onClick={() => setOpen((value) => !value)}
        aria-label="Your profile and status"
        aria-expanded={open}
      >
        <UserAvatar userId={userId} name={name} avatarUrl={avatarUrl} className="gnav-user-avatar" />
        <span className={status?.availabilityMode === "away" ? "gnav-presence away" : "gnav-presence"} />
        {effective?.emoji && <span className="gnav-status-emoji">{effective.emoji}</span>}
        {effective?.dndActive && <span className="gnav-dnd"><IconBellOff size={9} /></span>}
      </button>

      {open && (
        <section className="status-menu" aria-label="Profile and status menu">
          <div className="status-menu-profile">
            <UserAvatar userId={userId} name={name} avatarUrl={avatarUrl} className="status-menu-avatar" />
            <div><strong>{name ?? "You"}</strong><span>{statusSummary}</span></div>
          </div>

          <button className="status-menu-main" type="button" onClick={openStatusEditor}>
            <span>{effective?.emoji ?? "💬"}</span>
            <span>{effective?.text ? "Edit your status" : "Update your status"}</span>
            <IconChevron size={14} />
          </button>
          {status?.availabilityMode !== "available" && (effective?.text || effective?.source === "outside_hours") && (
            <button
              className="status-menu-row"
              type="button"
              onClick={() => void mutate(() => api.setAvailability(workspaceId, "available"), false)}
            >
              <span className="status-presence-dot" />
              Set yourself as available
            </button>
          )}
          {status?.availabilityMode === "available" && (
            <button
              className="status-menu-row"
              type="button"
              onClick={() => void mutate(() => api.setAvailability(workspaceId, "auto"), false)}
            >
              Use automatic status
            </button>
          )}
          {status?.manual.text && (
            <button className="status-menu-row danger" type="button" onClick={() => void mutate(() => api.setStatus(workspaceId, { text: "" }), false)}>
              Clear status
            </button>
          )}

          <div className="status-menu-separator" />
          <button
            className="status-menu-row"
            type="button"
            onClick={() => void mutate(() => api.setAvailability(workspaceId, status?.availabilityMode === "away" ? "auto" : "away"), false)}
          >
            <span className={status?.availabilityMode === "away" ? "status-presence-dot away" : "status-presence-dot"} />
            {status?.availabilityMode === "away" ? "Set yourself as active" : "Set yourself as away"}
          </button>
          <button
            className="status-menu-row"
            type="button"
            onClick={() => void mutate(() => api.setStatusContext(workspaceId, { focusModeEnabled: !focusOn }), false)}
          >
            <span className="status-focus-icon">◎</span>
            {focusOn ? "Turn off focus mode" : "Turn on focus mode"}
            {focusOn && <IconCheck size={14} />}
          </button>

          <div className="status-menu-separator" />
          <div className="status-menu-section-head"><span>Scheduled</span><b>{status?.schedules.length ?? 0}/5</b></div>
          {status?.schedules.slice(0, 3).map((schedule) => (
            <div className="status-schedule-row" key={schedule.id}>
              <button type="button" onClick={() => openSchedule(schedule)}>
                <span>{schedule.emoji}</span>
                <span><strong>{schedule.text}</strong><small>{readableWhen(schedule.startsAt)}</small></span>
              </button>
              <button
                type="button"
                aria-label={`Delete ${schedule.text}`}
                onClick={() => void mutate(() => api.deleteScheduledStatus(workspaceId, schedule.id), false)}
              >×</button>
            </div>
          ))}
          {(status?.schedules.length ?? 0) < 5 && (
            <button className="status-menu-row" type="button" onClick={() => openSchedule()}>
              <IconCalendar size={16} /> Schedule a status
            </button>
          )}
          <button className="status-menu-row" type="button" onClick={() => { setOpen(false); setDialog("automatic"); }}>
            <span className="status-sliders">☷</span> Automatic status preferences
          </button>

          <div className="status-menu-separator" />
          <Link className="status-menu-row" href={`/settings?workspaceId=${workspaceId}`}>Profile &amp; settings</Link>
          <div className="status-menu-separator" />
          <button className="status-menu-row status-menu-signout" type="button" onClick={() => void signOut()} disabled={signingOut}>
            {signingOut ? "Signing out…" : "Sign out of connectHUB"}
          </button>
          {error && <p className="status-menu-error">{error}</p>}
        </section>
      )}

      {dialog && (
        <div className="status-modal-backdrop" role="presentation" onMouseDown={(event) => event.target === event.currentTarget && setDialog(null)}>
          <section className="status-modal" role="dialog" aria-modal="true" aria-labelledby="status-modal-title">
            <header>
              <div>
                <h2 id="status-modal-title">{dialog === "status" ? "Set a status" : dialog === "schedule" ? "Schedule a status" : "Automatic statuses"}</h2>
                {dialog === "automatic" && <p>Choose when connectHUB updates your status for you.</p>}
              </div>
              <button type="button" onClick={() => setDialog(null)} aria-label="Close"><IconX size={19} /></button>
            </header>

            {dialog === "status" && (
              <form onSubmit={saveStatus}>
                <div className="status-editor-input">
                  <input value={emoji} onChange={(event) => setEmoji(event.target.value)} aria-label="Status emoji" maxLength={8} />
                  <input value={text} onChange={(event) => setText(event.target.value)} placeholder="What’s your status?" maxLength={100} autoFocus />
                </div>
                {recentStatuses.length > 0 && (
                  <section className="status-choice-section" aria-label="Recent statuses">
                    <h3>Recent</h3>
                    <div className="status-recent-list">
                      {recentStatuses.map((recent, index) => (
                        <div className="status-recent-row" key={`${recent.emoji}-${recent.text}-${index}`}>
                          <button className="status-recent-select" type="button" onClick={() => chooseRecent(recent)}>
                            <span className="status-choice-emoji">{recent.emoji}</span>
                            <strong>{recent.text}</strong>
                            <span>— {durationLabel(recent.duration)}</span>
                          </button>
                          <button className="status-recent-remove" type="button" aria-label={`Remove ${recent.text} from recent statuses`} onClick={() => removeRecent(index)}>
                            <IconX size={16} />
                          </button>
                        </div>
                      ))}
                    </div>
                  </section>
                )}
                <section className="status-choice-section" aria-label="Suggested statuses">
                  <h3>For this workspace</h3>
                <div className="status-suggestions">
                  {SUGGESTIONS.map((suggestion) => (
                    <button type="button" key={suggestion.text} onClick={() => { setEmoji(suggestion.emoji); setText(suggestion.text); setDuration(suggestion.duration); }}>
                      <span>{suggestion.emoji}</span>{suggestion.text}
                    </button>
                  ))}
                </div>
                </section>
                <label className="status-field-label">Remove status after
                  <select value={duration} onChange={(event) => setDuration(event.target.value)}>
                    <option value="30m">30 minutes</option><option value="1h">1 hour</option><option value="4h">4 hours</option>
                    <option value="today">Today</option><option value="week">This week</option><option value="never">Don’t clear</option>
                    <option value="custom">Custom date and time</option>
                  </select>
                </label>
                {duration === "custom" && <input className="status-datetime" type="datetime-local" value={customExpiry} onChange={(event) => setCustomExpiry(event.target.value)} />}
                <label className="status-check"><input type="checkbox" checked={pauseNotifications} onChange={(event) => setPauseNotifications(event.target.checked)} /> Pause notifications until this status clears</label>
                {error && <p className="status-modal-error">{error}</p>}
                <footer><button type="button" onClick={() => setDialog(null)}>Cancel</button><button className="primary" type="submit" disabled={busy || !text.trim()}>{busy ? "Saving…" : "Save"}</button></footer>
              </form>
            )}

            {dialog === "schedule" && (
              <form onSubmit={saveSchedule}>
                <div className="status-editor-input">
                  <input value={emoji} onChange={(event) => setEmoji(event.target.value)} aria-label="Status emoji" maxLength={8} />
                  <input value={text} onChange={(event) => setText(event.target.value)} placeholder="What’s your status?" maxLength={100} autoFocus />
                </div>
                <div className="status-date-grid">
                  <label>Starts<input type="datetime-local" value={startsAt} onChange={(event) => setStartsAt(event.target.value)} /></label>
                  <label>Ends<input type="datetime-local" value={endsAt} onChange={(event) => setEndsAt(event.target.value)} /></label>
                </div>
                <label className="status-check"><input type="checkbox" checked={pauseNotifications} onChange={(event) => setPauseNotifications(event.target.checked)} /> Pause notifications while this status is active</label>
                {error && <p className="status-modal-error">{error}</p>}
                <footer><button type="button" onClick={() => setDialog(null)}>Cancel</button><button className="primary" type="submit" disabled={busy || !text.trim()}>{busy ? "Saving…" : editingScheduleId == null ? "Schedule" : "Save changes"}</button></footer>
              </form>
            )}

            {dialog === "automatic" && (
              <form onSubmit={saveAutomatic}>
                <div className="automatic-status-options">
                  <label><span><strong>In Connect</strong><small>Show 🎧 while you’re in an active call.</small></span><input type="checkbox" checked={automatic.connect} onChange={(event) => setAutomatic((value) => ({ ...value, connect: event.target.checked }))} /></label>
                  <label><span><strong>Focus mode</strong><small>Show 🎯 and pause notifications while focus mode is on.</small></span><input type="checkbox" checked={automatic.focus} onChange={(event) => setAutomatic((value) => ({ ...value, focus: event.target.checked }))} /></label>
                  <label><span><strong>Outside working hours</strong><small>Show 🌙 before or after your configured hours.</small></span><input type="checkbox" checked={automatic.outsideWorkingHours} onChange={(event) => setAutomatic((value) => ({ ...value, outsideWorkingHours: event.target.checked }))} /></label>
                </div>
                <div className="status-date-grid working-hours">
                  <label>Starts<input type="time" value={automatic.workHoursStart} onChange={(event) => setAutomatic((value) => ({ ...value, workHoursStart: event.target.value }))} /></label>
                  <label>Ends<input type="time" value={automatic.workHoursEnd} onChange={(event) => setAutomatic((value) => ({ ...value, workHoursEnd: event.target.value }))} /></label>
                </div>
                <div className="working-days" aria-label="Working days">
                  {["S", "M", "T", "W", "T", "F", "S"].map((label, day) => (
                    <button
                      type="button"
                      className={automatic.workingDays.includes(day) ? "active" : ""}
                      key={`${label}-${day}`}
                      onClick={() => setAutomatic((value) => ({ ...value, workingDays: value.workingDays.includes(day) ? value.workingDays.filter((item) => item !== day) : [...value.workingDays, day] }))}
                    >{label}</button>
                  ))}
                </div>
                {error && <p className="status-modal-error">{error}</p>}
                <footer><button type="button" onClick={() => setDialog(null)}>Cancel</button><button className="primary" type="submit" disabled={busy || automatic.workingDays.length === 0}>{busy ? "Saving…" : "Save"}</button></footer>
              </form>
            )}
          </section>
        </div>
      )}
    </div>
  );
}
