'use client';

import { Suspense, useCallback, useEffect, useMemo, useState } from 'react';
import Link from 'next/link';
import { usePathname, useRouter, useSearchParams } from 'next/navigation';
import { DashboardLayout } from '@/components/layout/DashboardLayout';
import { ConversationList } from '@/components/messages/ConversationList';
import {
  filterConversations,
  MessagesInboxHeader,
  MessagesSelectPrompt,
  type InboxFilter,
} from '@/components/messages/MessagesInboxHeader';
import { Button } from '@/components/ui/button';
import { useAuth } from '@/contexts/AuthContext';
import { useSocket, SOCKET_EVENTS } from '@/contexts/SocketContext';
import { api } from '@/lib/api';
import { buildCreateJobUrl } from '@/lib/createJob';
import { JOBS_FEATURE_ENABLED } from '@/lib/features';
import { ChatMessage, Conversation, conversationMatchesThread, formatMessageTime } from '@/lib/messages';
import { cn } from '@/lib/utils';

interface MessagesShellProps {
  role: 'customer' | 'worker';
  children: React.ReactNode;
}

function MessagesShellContent({ role, children }: MessagesShellProps) {
  const { user } = useAuth();
  const { socket } = useSocket();
  const router = useRouter();
  const pathname = usePathname();
  const searchParams = useSearchParams();
  const jobId = searchParams.get('jobId');
  const workerId = searchParams.get('workerId');
  const seedContext = searchParams.get('seedContext');

  const [conversations, setConversations] = useState<Conversation[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState('');
  const [search, setSearch] = useState('');
  const [inboxFilter, setInboxFilter] = useState<InboxFilter>('all');

  const basePath = `/${role}/messages`;
  const activeId = useMemo(() => {
    const match = pathname.match(new RegExp(`^/${role}/messages/([^/]+)$`));
    return match?.[1];
  }, [pathname, role]);

  /** True while resolving ?jobId= or ?workerId= on the inbox route (not yet on a thread). */
  const isResolvingDeepLink = Boolean((jobId || workerId) && !activeId);

  const loadConversations = useCallback(async () => {
    setError('');
    try {
      const res = await api<{ data: Conversation[] }>('/messages');
      setConversations(res.data);
    } catch (err: unknown) {
      const message = err instanceof Error ? err.message : 'Failed to load messages';
      setError(message);
      console.error(err);
    } finally {
      setLoading(false);
    }
  }, []);

  useEffect(() => {
    if (!user) {
      setLoading(false);
      return;
    }

    if (!isResolvingDeepLink) {
      if (!activeId) {
        loadConversations();
      } else {
        setLoading(false);
        loadConversations();
      }
      return;
    }

    const openConversation = async () => {
      setError('');
      try {
        if (jobId) {
          const params = new URLSearchParams();
          if (seedContext === '1' || seedContext === 'true') params.set('seedContext', '1');
          const query = params.toString();
          const res = await api<{ data: Conversation }>(
            `/messages/by-job/${jobId}${query ? `?${query}` : ''}`
          );
          const threadQuery = workerId ? `?workerId=${workerId}` : '';
          router.replace(`${basePath}/${res.data.id}${threadQuery}`);
        } else if (workerId && role === 'customer') {
          const params = new URLSearchParams();
          if (seedContext === '1' || seedContext === 'true') params.set('seedContext', '1');
          const query = params.toString();
          const res = await api<{ data: Conversation }>(
            `/messages/by-worker/${workerId}${query ? `?${query}` : ''}`
          );
          router.replace(`${basePath}/${res.data.id}?workerId=${workerId}`);
        }
        setLoading(false);
        loadConversations();
      } catch (err: unknown) {
        const message = err instanceof Error ? err.message : 'Failed to open conversation';
        setError(message);
        setLoading(false);
      }
    };

    openConversation();
  }, [
    user,
    jobId,
    workerId,
    seedContext,
    role,
    activeId,
    isResolvingDeepLink,
    basePath,
    router,
    loadConversations,
  ]);

  useEffect(() => {
    const onFocus = () => {
      if (!isResolvingDeepLink) loadConversations();
    };
    window.addEventListener('focus', onFocus);
    return () => window.removeEventListener('focus', onFocus);
  }, [isResolvingDeepLink, loadConversations]);

  useEffect(() => {
    if (!socket || !user || isResolvingDeepLink) return;

    const onMessage = (message: ChatMessage & { conversationId?: string }) => {
      const convId = message.conversationId;
      if (!convId) return;

      setConversations((prev) => {
        const idx = prev.findIndex((c) =>
          conversationMatchesThread(c, convId)
        );
        const isFromOther = message.senderId !== user.id;

        if (idx === -1) {
          loadConversations();
          return prev;
        }

        const updated = [...prev];
        const conv = { ...updated[idx] };
        conv.messages = [message, ...conv.messages.filter((m) => m.id !== message.id)];
        conv.updatedAt = message.createdAt;
        if (isFromOther) {
          conv.unreadCount = (conv.unreadCount ?? 0) + 1;
        }
        updated.splice(idx, 1);
        updated.unshift(conv);
        return updated;
      });
    };

    socket.on(SOCKET_EVENTS.RECEIVE_MESSAGE, onMessage);
    return () => {
      socket.off(SOCKET_EVENTS.RECEIVE_MESSAGE, onMessage);
    };
  }, [socket, user, isResolvingDeepLink, loadConversations]);

  const filteredConversations = useMemo(
    () => (user ? filterConversations(conversations, search, user.id, inboxFilter) : []),
    [conversations, search, user, inboxFilter]
  );

  const unreadTotal = useMemo(
    () => conversations.reduce((sum, c) => sum + (c.unreadCount ?? 0), 0),
    [conversations]
  );

  const showListOnMobile = !activeId;

  if (isResolvingDeepLink) {
    return (
      <DashboardLayout role={role} flush>
        <div className="flex flex-col items-center justify-center py-20 gap-3 px-4">
          {error ? (
            <>
              <p className="text-sm text-red-500 text-center max-w-md">{error}</p>
              {role === 'customer' && workerId && !jobId && JOBS_FEATURE_ENABLED ? (
                <Link href={buildCreateJobUrl()}>
                  <Button size="sm">Post a job</Button>
                </Link>
              ) : null}
              {role === 'customer' && workerId && !jobId && !JOBS_FEATURE_ENABLED ? (
                <div className="flex flex-col items-center gap-2">
                  <Link href="/customer/verification">
                    <Button size="sm">Go to verification</Button>
                  </Link>
                  <Link href={`/workers/${workerId}`}>
                    <Button size="sm" variant="outline">
                      View worker profile
                    </Button>
                  </Link>
                </div>
              ) : null}
              <button
                type="button"
                onClick={() => router.replace(basePath)}
                className="text-sm text-primary font-semibold"
              >
                Back to messages
              </button>
            </>
          ) : (
            <div className="loading-spinner" />
          )}
        </div>
      </DashboardLayout>
    );
  }

  if (loading && !activeId) {
    return (
      <DashboardLayout role={role} flush>
        <div className="flex flex-col items-center justify-center py-20 gap-3 px-4">
          {error ? (
            <>
              <p className="text-sm text-red-500 text-center max-w-md">{error}</p>
              <button
                type="button"
                onClick={() => loadConversations()}
                className="text-sm text-primary font-semibold"
              >
                Try again
              </button>
            </>
          ) : (
            <div className="loading-spinner" />
          )}
        </div>
      </DashboardLayout>
    );
  }

  return (
    <DashboardLayout role={role} hideMobileHeader={!!activeId} flush>
      <div className="flex h-full min-h-0 w-full flex-1 overflow-hidden bg-[var(--home-sand)]/30">
        <aside
          className={cn(
            'flex h-full min-h-0 w-full shrink-0 flex-col border-r border-[#e2ddd2] bg-[#fffdf9] lg:w-[min(100%,400px)]',
            !showListOnMobile && 'hidden lg:flex'
          )}
        >
          <MessagesInboxHeader
            role={role}
            search={search}
            onSearchChange={setSearch}
            filter={inboxFilter}
            onFilterChange={setInboxFilter}
            totalCount={conversations.length}
            unreadTotal={unreadTotal}
          />
          <div className="min-h-0 flex-1 overflow-y-auto bg-[var(--home-sand)]/25">
            {error ? (
              <p className="px-4 py-8 text-center text-sm text-red-500">{error}</p>
            ) : (
              <ConversationList
                conversations={filteredConversations}
                currentUserId={user!.id}
                basePath={basePath}
                activeId={activeId}
                role={role}
                searchQuery={search}
                filter={inboxFilter}
              />
            )}
          </div>
        </aside>

        <main
          className={cn(
            'flex h-full min-h-0 min-w-0 flex-1 flex-col overflow-hidden bg-[#fffdf9]',
            showListOnMobile && !activeId ? 'hidden lg:flex' : 'flex'
          )}
        >
          {activeId ? children : <MessagesSelectPrompt role={role} />}
        </main>
      </div>
    </DashboardLayout>
  );
}

export function MessagesShell({ role, children }: MessagesShellProps) {
  return (
    <Suspense
      fallback={
        <DashboardLayout role={role} flush>
          <div className="flex items-center justify-center py-20">
            <div className="loading-spinner" />
          </div>
        </DashboardLayout>
      }
    >
      <MessagesShellContent role={role}>{children}</MessagesShellContent>
    </Suspense>
  );
}
