"use client";

import Link from "next/link";
import { Suspense, useEffect, useState } from "react";
import { useSearchParams } from "next/navigation";
import type { Message } from "@slackwsh/contracts";
import { AppShell, ScreenHeader, useWorkspaceIdParam } from "../../components/AppShell";
import { api, ApiError } from "../../lib/api";
import { normalizeChannelRows, textChannels, type ConversationRow } from "../../lib/conversations";

interface SearchResult {
  message: Message;
  channelName: string | null;
  authorName: string;
}

interface SearchMemberRow {
  member: { deactivatedAt?: string | null };
  user: { id: string | number; name: string; email: string; username?: string | null };
}

function handleFromMember(row: SearchMemberRow): string {
  const username = row.user.username?.trim();
  if (username) return username;
  const localPart = row.user.email.split("@")[0] ?? row.user.name;
  return localPart.toLowerCase().replace(/[^a-z0-9._-]+/g, "");
}

function SearchView() {
  const workspaceId = useWorkspaceIdParam();
  const params = useSearchParams();
  const [query, setQuery] = useState(params.get("q") ?? "");
  const [fromUser, setFromUser] = useState("");
  const [inChannel, setInChannel] = useState("");
  const [members, setMembers] = useState<SearchMemberRow[]>([]);
  const [channels, setChannels] = useState<ConversationRow[]>([]);
  const [results, setResults] = useState<SearchResult[]>([]);
  const [busy, setBusy] = useState(false);
  const [error, setError] = useState<string | null>(null);

  async function runSearch(q: string) {
    if (!workspaceId || !q.trim()) {
      setResults([]);
      return;
    }
    setBusy(true);
    setError(null);
    try {
      const res = await api.search(workspaceId, q.trim());
      setResults(res.results as SearchResult[]);
    } catch (err) {
      setError(err instanceof ApiError ? JSON.stringify(err.body) : String(err));
    } finally {
      setBusy(false);
    }
  }

  function buildSearchQuery() {
    const parts = [query.trim()];
    if (fromUser) parts.push(`from:${fromUser}`);
    if (inChannel) parts.push(`in:${inChannel}`);
    return parts.filter(Boolean).join(" ");
  }

  useEffect(() => {
    const q = params.get("q");
    if (q) {
      setQuery(q);
      runSearch(q);
    }
  }, [workspaceId]);

  useEffect(() => {
    if (!workspaceId) return;
    api.members(workspaceId).then((res) => setMembers(res.members)).catch(() => undefined);
    api
      .listChannels(workspaceId)
      .then((res) => setChannels(textChannels(normalizeChannelRows(res.channels))))
      .catch(() => undefined);
  }, [workspaceId]);

  async function onSubmit(e: React.FormEvent) {
    e.preventDefault();
    const effectiveQuery = buildSearchQuery();
    const url = new URL(window.location.href);
    url.searchParams.set("q", effectiveQuery);
    window.history.replaceState({}, "", url.toString());
    await runSearch(effectiveQuery);
  }

  return (
    <AppShell active="home" title="Search" subtitle="Find messages across the workspace">
      <ScreenHeader title="Search" subtitle={busy ? "Searching…" : `${results.length} results`} />
      <div className="screen-body">
        <form className="search-form" onSubmit={onSubmit}>
          <input
            value={query}
            onChange={(e) => setQuery(e.target.value)}
            placeholder="Search messages"
            aria-label="Search messages"
            autoFocus
          />
          <div className="search-filters" aria-label="Search filters">
            <select value={fromUser} onChange={(e) => setFromUser(e.target.value)} aria-label="Filter by sender">
              <option value="">Any sender</option>
              {members
                .filter((row) => !row.member.deactivatedAt)
                .map((row) => {
                  const handle = handleFromMember(row);
                  return (
                    <option value={handle} key={String(row.user.id)}>
                      From {row.user.name}
                    </option>
                  );
                })}
            </select>
            <select value={inChannel} onChange={(e) => setInChannel(e.target.value)} aria-label="Filter by channel">
              <option value="">Any channel</option>
              {channels.map((row) => (
                <option value={row.channel.name ?? ""} key={row.channel.id}>
                  In #{row.channel.name}
                </option>
              ))}
            </select>
          </div>
          <button className="screen-btn primary" type="submit" disabled={busy}>
            Search
          </button>
        </form>
        {error && <p className="error-text">{error}</p>}
        <div className="screen-list tall" style={{ marginTop: 16 }}>
          {results.map((hit) => (
            <div className="screen-thread" key={hit.message.id}>
              <div className="screen-thread-main">
                <span className="screen-thread-meta">
                  {hit.authorName} · #{hit.channelName ?? "channel"} · {new Date(hit.message.createdAt).toLocaleString()}
                </span>
                <span className="screen-thread-text">{hit.message.text || "(attachment)"}</span>
                <Link
                  className="screen-btn"
                  href={`/channel?workspaceId=${workspaceId}&channelId=${hit.message.channelId}`}
                  style={{ alignSelf: "flex-start", marginTop: 8 }}
                >
                  Open channel
                </Link>
              </div>
            </div>
          ))}
          {!busy && query.trim() && results.length === 0 && (
            <div className="empty-state">No messages matched “{query}”.</div>
          )}
        </div>
      </div>
    </AppShell>
  );
}

export default function SearchPage() {
  return (
    <Suspense fallback={<main className="page"><div className="empty-state">Loading search…</div></main>}>
      <SearchView />
    </Suspense>
  );
}
