"use client";

import { Suspense, useEffect, useMemo, useState } from "react";
import { useRouter, useSearchParams } from "next/navigation";
import Link from "next/link";
import { api, ApiError, getCurrentUserId, forceLogin } from "../../lib/api";
import { CommandPalette } from "../../components/CommandPalette";
import { GlobalNav } from "../../components/GlobalNav";
import { WorkspaceSidebar } from "../../components/WorkspaceSidebar";
import {
  channelPath,
  dmChannelByUserId,
  normalizeChannelRows,
  textChannels as onlyTextChannels,
  type ConversationRow,
} from "../../lib/conversations";
import { useUnreadTotal } from "../../lib/unread-store";
import { useMemberStatusRefresh } from "../../lib/member-status-events";

interface MemberRow {
  member: { role: string; statusText?: string | null; statusEmoji?: string | null; dndActive?: boolean };
  user: { id: string | number; name: string; email: string };
}

function WorkspaceView() {
  const router = useRouter();
  const params = useSearchParams();
  const workspaceId = params.get("id");
  const [members, setMembers] = useState<MemberRow[]>([]);
  const [channels, setChannels] = useState<ConversationRow[]>([]);
  const [presence, setPresence] = useState<Record<string, { status: string }>>({});
  const [newChannelName, setNewChannelName] = useState("");
  const [showCreateChannel, setShowCreateChannel] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [busyUserId, setBusyUserId] = useState<string | null>(null);
  const [myUserId, setMyUserId] = useState<number | null>(null);
  const [unreadAssignedCount, setUnreadAssignedCount] = useState(0);

  const textChannels = useMemo(() => onlyTextChannels(channels), [channels]);
  const dmByUser = useMemo(() => dmChannelByUserId(channels), [channels]);
  const dmMembers = useMemo(
    () => members.filter((row) => String(row.user.id) !== String(myUserId)),
    [members, myUserId],
  );
  const me = members.find((row) => String(row.user.id) === String(myUserId))?.user;
  const chatUnread = useUnreadTotal(workspaceId);

  function loadChannels() {
    if (!workspaceId) return;
    api
      .listChannels(workspaceId)
      .then((res) => setChannels(normalizeChannelRows(res.channels)))
      .catch((err) => setError(err instanceof ApiError ? JSON.stringify(err.body) : String(err)));
  }

  useEffect(() => {
    getCurrentUserId().then(setMyUserId);
  }, []);

  useEffect(() => {
    if (!workspaceId) return;
    api
      .members(workspaceId)
      .then((res) => setMembers(res.members as MemberRow[]))
      .catch((err) => {
        if (err instanceof ApiError && err.status === 401) void forceLogin(router);
        else setError(String(err));
      });
    loadChannels();
    api
      .presenceSnapshot(workspaceId)
      .then((res) => setPresence(res.presence))
      .catch(() => undefined);
  }, [workspaceId]);

  useEffect(() => {
    if (!workspaceId) return;
    let cancelled = false;
    function refresh() {
      api
        .unreadAssignedTasks(workspaceId!)
        .then((res) => {
          if (!cancelled) setUnreadAssignedCount(res.unread);
        })
        .catch(() => undefined);
    }
    refresh();
    window.addEventListener("slackwsh:task", refresh);
    window.addEventListener("slackwsh:tasks-seen", refresh);
    return () => {
      cancelled = true;
      window.removeEventListener("slackwsh:task", refresh);
      window.removeEventListener("slackwsh:tasks-seen", refresh);
    };
  }, [workspaceId]);

  useMemberStatusRefresh(workspaceId, () => {
    if (!workspaceId) return;
    void api.members(workspaceId)
      .then((res) => setMembers(res.members as MemberRow[]))
      .catch(() => undefined);
  });

  async function createChannel(e: React.FormEvent) {
    e.preventDefault();
    if (!workspaceId || !newChannelName.trim()) return;
    setError(null);
    try {
      const created = await api.createChannel(workspaceId, { name: newChannelName.trim(), type: "public" });
      setNewChannelName("");
      setShowCreateChannel(false);
      router.push(`${channelPath(workspaceId, String(created.id))}&addMembers=1`);
    } catch (err) {
      setError(err instanceof ApiError ? JSON.stringify(err.body) : String(err));
    }
  }

  function openChannel(channelId: string | number) {
    if (!workspaceId || !channelId) return;
    router.push(channelPath(workspaceId, String(channelId)));
  }

  async function openDm(userId: string | number) {
    if (!workspaceId || !userId || String(userId) === String(myUserId)) return;
    setError(null);
    const existing = dmByUser.get(String(userId));
    if (existing) {
      openChannel(existing);
      return;
    }
    setBusyUserId(String(userId));
    try {
      const dm = await api.createDm(workspaceId, String(userId));
      if (!dm?.id) throw new Error("Could not open direct message");
      router.push(channelPath(workspaceId, String(dm.id)));
    } catch (err) {
      setError(err instanceof ApiError ? JSON.stringify(err.body) : String(err));
    } finally {
      setBusyUserId(null);
    }
  }

  if (!workspaceId) {
    return (
      <main className="page-card">
        <p>
          Missing ?id= — go back to <Link href="/workspaces">workspaces</Link>.
        </p>
      </main>
    );
  }

  return (
    <main className="app windshield">
      <GlobalNav workspaceId={workspaceId} myUserId={myUserId} meName={me?.name} chatCount={chatUnread} taskCount={unreadAssignedCount} />
      <WorkspaceSidebar
        workspaceId={workspaceId}
        workspaceLabel="Workspace"
        active="chat"
        variant="chat"
        channels={textChannels}
        conversations={channels}
        members={members}
        presence={presence}
        myUserId={myUserId}
        meName={me?.name}
        onOpenChannel={openChannel}
        onOpenDm={openDm}
        onCreateChannel={() => setShowCreateChannel((v) => !v)}
        createChannelSlot={
          showCreateChannel ? (
            <form className="inline-create" onSubmit={createChannel}>
              <input
                value={newChannelName}
                onChange={(e) => setNewChannelName(e.target.value)}
                placeholder="new-room"
                required
              />
              <button type="submit">Create</button>
            </form>
          ) : null
        }
      />

      <section className="main">
        <header className="main-head">
          <div className="main-head-row">
            <div className="main-head-left">
              <div className="main-head-title-row">
                <h1 className="main-head-title">Rooms</h1>
              </div>
              <div className="main-head-meta">
                <span>Pick a room or person from the left to open a chat.</span>
              </div>
            </div>
          </div>
        </header>
        <div className="messages">
          <div className="empty-state" style={{ marginTop: 40 }}>
            <p style={{ marginBottom: 16 }}>Rooms open group chat. People open a private DM.</p>
            {textChannels.slice(0, 4).map((row) => (
              <button
                key={String(row.channel.id)}
                type="button"
                className="screen-btn"
                style={{ margin: 4 }}
                onClick={() => openChannel(row.channel.id)}
              >
                #{row.channel.name}
              </button>
            ))}
            {dmMembers.slice(0, 4).map((row) => (
              <button
                key={String(row.user.id)}
                type="button"
                className="screen-btn primary"
                style={{ margin: 4 }}
                disabled={busyUserId === String(row.user.id)}
                onClick={() => void openDm(row.user.id)}
              >
                Message {row.user.name.split(" ")[0]}
              </button>
            ))}
          </div>
        </div>
        {error && (
          <p className="error-text" style={{ padding: "0 20px 20px" }}>
            {error}
          </p>
        )}
      </section>

      <CommandPalette workspaceId={workspaceId} channels={textChannels.map((row) => row.channel)} />
    </main>
  );
}

export default function WorkspacePage() {
  return (
    <Suspense fallback={<p>Loading...</p>}>
      <WorkspaceView />
    </Suspense>
  );
}
