'use client';

import { useAuth } from '@clerk/nextjs';
import { useRouter } from 'next/navigation';
import { useCallback, useEffect, useRef, useState } from 'react';

import { useApiClient } from '@/lib/apiClient';
import { components } from '@/lib/gen';

type SessionSchema = components['schemas']['SessionSchema'];
type ListSessionResponse = components['schemas']['ListSessionResponse'];

interface ChatMessage {
  role: string;
  content: string;
  message_id?: string;
  timestamp?: string;
  tool_calls?: string;
  tool_call_id?: string;
}

interface OrpheusClientProps {
  initialChatId?: string;
  redirectToChat?: boolean;
}

const OrpheusClient = ({
  initialChatId,
  redirectToChat,
}: OrpheusClientProps) => {
  const { getToken } = useAuth();
  const apiClient = useApiClient();
  const [uid, setUid] = useState('');
  const [chatId, setChatId] = useState(initialChatId ?? '');
  const [sessions, setSessions] = useState<SessionSchema[]>([]);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [selectedSession, setSelectedSession] = useState<string | null>(null);
  const [chatHistory, setChatHistory] = useState<ChatMessage[]>([]);
  const [historyLoading, setHistoryLoading] = useState(false);
  const [expandedTools, setExpandedTools] = useState<Set<string>>(new Set());
  const lastLoadedChatIdRef = useRef<string | null>(null);
  const router = useRouter();

  const updateQueryParams = useCallback(
    (params: Record<string, string | null>) => {
      if (typeof window === 'undefined') {
        return;
      }
      const currentParams = new URLSearchParams(window.location.search);
      Object.entries(params).forEach(([key, value]) => {
        if (value === null || value === '') {
          currentParams.delete(key);
        } else {
          currentParams.set(key, value);
        }
      });
      const queryString = currentParams.toString();
      const pathname = window.location.pathname;
      const newUrl = queryString
        ? `${window.location.pathname}?${queryString}`
        : window.location.pathname;
      const currentUrl = `${pathname}${window.location.search}`;
      if (newUrl === currentUrl) {
        return;
      }
      router.replace(newUrl, { scroll: false });
    },
    [router]
  );

  const handleSearch = async (e: React.FormEvent) => {
    e.preventDefault();
    if (!uid.trim()) {
      setError('Please enter a user UID');
      return;
    }

    updateQueryParams({ chat_id: null, redirect: null });
    lastLoadedChatIdRef.current = null;
    setLoading(true);
    setError(null);
    setSessions([]);
    setSelectedSession(null);
    setChatHistory([]);

    try {
      const { data, error: apiError } = await apiClient.GET(
        '/api/orpheus/sessions/user/{uid}',
        {
          params: {
            path: {
              uid: uid.trim(),
            },
          },
        }
      );

      if (apiError) {
        throw new Error('Failed to fetch sessions');
      }

      setSessions((data as ListSessionResponse).sessions || []);
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Something went wrong');
    } finally {
      setLoading(false);
    }
  };

  const fetchChatHistory = useCallback(
    async (sessionId: string) => {
      setHistoryLoading(true);
      try {
        const token = await getToken();
        const env =
          process.env.NEXT_PUBLIC_ORPHEUS_ENV ??
          (process.env.NEXT_PUBLIC_NODE_ENV === 'production' ? 'prod' : 'dev');
        const MODAL_SRV = `https://suno-ai--orpheus-${env}-web.modal.run`;

        const response = await fetch(`${MODAL_SRV}/chat-history/${sessionId}`, {
          headers: {
            'Content-Type': 'application/json',
            Authorization: `Bearer ${token}`,
          },
        });

        const data = await response
          .json()
          .catch(() => ({ messages: undefined }));

        if (!response.ok) {
          const message =
            (data &&
              typeof data === 'object' &&
              data !== null &&
              ('detail' in data || 'message' in data) &&
              (typeof (data as any).detail === 'string'
                ? (data as any).detail
                : typeof (data as any).message === 'string'
                  ? (data as any).message
                  : null)) ||
            'Failed to fetch chat history';
          throw new Error(message);
        }

        if (data && typeof data === 'object' && 'messages' in data) {
          const messages: ChatMessage[] = [];

          const rawMessages: Record<string, any> = (data as any).messages ?? {};
          for (const msgKey in rawMessages) {
            const msg = rawMessages[msgKey];
            messages.push({
              role: msg?.role || 'unknown',
              content: msg?.content || '',
              message_id: msg?.message_id,
              timestamp: msg?.timestamp,
              tool_calls: msg?.tool_calls,
              tool_call_id: msg?.tool_call_id,
            });
          }

          messages.sort((a, b) => {
            const timeA = a.timestamp || '';
            const timeB = b.timestamp || '';
            return timeA.localeCompare(timeB);
          });

          setError(null);
          setChatHistory(messages);
        } else {
          setError(null);
          setChatHistory([]);
        }
        return true;
      } catch (err) {
        console.error('Error fetching chat history:', err);
        setChatHistory([]);
        setError(
          err instanceof Error ? err.message : 'Failed to fetch chat history'
        );
        return false;
      } finally {
        setHistoryLoading(false);
      }
    },
    [getToken]
  );

  const loadChatById = useCallback(
    async (
      rawChatId: string,
      options?: { updateUrl?: boolean; removeOnFailure?: boolean }
    ) => {
      const trimmed = rawChatId.trim();
      if (!trimmed) {
        setError('Please enter a chat ID');
        return false;
      }

      setError(null);
      setChatId(trimmed);
      setSelectedSession(trimmed);
      setChatHistory([]);
      setExpandedTools(new Set<string>());

      const success = await fetchChatHistory(trimmed);
      lastLoadedChatIdRef.current = trimmed;

      const shouldUpdateUrl = options?.updateUrl ?? true;
      const shouldRemoveOnFailure = options?.removeOnFailure ?? shouldUpdateUrl;

      if (shouldUpdateUrl) {
        if (success) {
          updateQueryParams({ chat_id: trimmed, redirect: null });
        } else if (shouldRemoveOnFailure) {
          updateQueryParams({ chat_id: null, redirect: null });
        }
      } else if (!success && shouldRemoveOnFailure) {
        updateQueryParams({ chat_id: null, redirect: null });
      }

      if (!success) {
        setSelectedSession(null);
      }

      return success;
    },
    [fetchChatHistory, updateQueryParams]
  );

  const handleChatIdSubmit = async (event: React.FormEvent) => {
    event.preventDefault();
    await loadChatById(chatId);
  };

  const handleResetView = () => {
    updateQueryParams({ chat_id: null, redirect: null });
    setSelectedSession(null);
    setChatHistory([]);
    setExpandedTools(new Set<string>());
    setError(null);
    lastLoadedChatIdRef.current = null;
  };

  const handleSessionClick = (sessionId: string) => {
    void loadChatById(sessionId);
  };

  const formatDate = (dateString: string) => {
    const date = new Date(dateString);
    return date.toLocaleString();
  };

  const toggleTool = (toolId: string) => {
    setExpandedTools((prev) => {
      const next = new Set(prev);
      if (next.has(toolId)) {
        next.delete(toolId);
      } else {
        next.add(toolId);
      }
      return next;
    });
  };

  useEffect(() => {
    if (!initialChatId) {
      return;
    }
    setChatId(initialChatId);
  }, [initialChatId]);

  useEffect(() => {
    if (!initialChatId) {
      return;
    }
    if (lastLoadedChatIdRef.current === initialChatId) {
      return;
    }
    if (redirectToChat) {
      lastLoadedChatIdRef.current = initialChatId;
      window.location.replace(`/chat/${initialChatId}`);
      return;
    }
    void loadChatById(initialChatId, {
      updateUrl: false,
      removeOnFailure: true,
    });
  }, [initialChatId, redirectToChat, loadChatById]);

  const renderMessageContent = (message: ChatMessage, messageIdx: number) => {
    if (message.role === 'assistant' && message.tool_calls) {
      try {
        const toolCalls = JSON.parse(message.tool_calls) as Array<{
          function?: { name?: string; arguments?: string };
        }>;
        return (
          <div>
            {message.content && <p className='mb-2'>{message.content}</p>}
            <div className='mt-2 space-y-2'>
              {toolCalls.map((call, idx) => {
                const toolId = `${messageIdx}-${idx}`;
                const isExpanded = expandedTools.has(toolId);
                return (
                  <div
                    key={idx}
                    className='border-border bg-muted/30 rounded border'
                  >
                    <button
                      className='hover:bg-muted/50 flex w-full items-center justify-between p-3 text-left'
                      onClick={() => toggleTool(toolId)}
                    >
                      <span className='text-foreground text-sm font-medium'>
                        🔧 {call.function?.name || 'Unknown'}
                      </span>
                      <span className='text-muted-foreground'>
                        {isExpanded ? '▼' : '▶'}
                      </span>
                    </button>
                    {isExpanded && (
                      <div className='border-border border-t p-3'>
                        <pre className='bg-background text-foreground overflow-x-auto rounded p-2 text-xs'>
                          {call.function?.arguments
                            ? JSON.stringify(
                                JSON.parse(call.function.arguments),
                                null,
                                2
                              )
                            : 'No arguments'}
                        </pre>
                      </div>
                    )}
                  </div>
                );
              })}
            </div>
          </div>
        );
      } catch {
        return <p>{message.content}</p>;
      }
    }

    if (message.role === 'tool') {
      const toolId = `tool-${messageIdx}`;
      const isExpanded = expandedTools.has(toolId);

      return (
        <div className='border-border bg-muted/30 rounded border'>
          <button
            className='hover:bg-muted/50 flex w-full items-center justify-between p-3 text-left'
            onClick={() => toggleTool(toolId)}
          >
            <span className='text-foreground text-sm font-medium'>
              📦 Tool Response
            </span>
            <span className='text-muted-foreground'>
              {isExpanded ? '▼' : '▶'}
            </span>
          </button>
          {isExpanded && (
            <div className='border-border border-t p-3'>
              <pre className='bg-background text-foreground overflow-x-auto rounded p-2 text-xs'>
                {message.content}
              </pre>
            </div>
          )}
        </div>
      );
    }

    return <p>{message.content}</p>;
  };

  return (
    <div className='bg-background w-full overflow-y-auto p-6 pb-40'>
      <div className='mx-auto max-w-7xl'>
        {!selectedSession && (
          <>
            <div className='mb-8'>
              <h1 className='text-foreground mb-2 text-4xl font-bold'>
                Orpheus Session Viewer
              </h1>
              <p className='text-muted-foreground'>
                Internal tool to view user chat sessions and history
              </p>
            </div>

            {error && (
              <div className='bg-destructive/10 text-destructive mb-4 rounded-md p-4 text-center'>
                {error}
              </div>
            )}

            <div className='border-border bg-card mb-6 rounded-lg border p-6 shadow-sm'>
              <div className='space-y-6'>
                <div>
                  <h2 className='text-foreground mb-3 text-lg font-semibold'>
                    Search by User UID
                  </h2>
                  <form onSubmit={handleSearch} className='flex gap-4'>
                    <div className='flex-1'>
                      <input
                        id='uid-input'
                        type='text'
                        value={uid}
                        onChange={(e) => setUid(e.target.value)}
                        placeholder='Enter User UID...'
                        className='border-border bg-background text-foreground placeholder:text-muted-foreground w-full rounded-md border p-2'
                        required
                      />
                    </div>
                    <button
                      type='submit'
                      disabled={loading}
                      className='rounded-md bg-blue-600 px-6 py-2 text-white hover:bg-blue-700 disabled:opacity-50'
                    >
                      {loading ? 'Loading...' : 'Search'}
                    </button>
                  </form>
                </div>
                <div className='border-border border-t pt-6'>
                  <h2 className='text-foreground mb-3 text-lg font-semibold'>
                    Load Conversation by Chat ID
                  </h2>
                  <p className='text-muted-foreground mb-4 text-sm'>
                    Paste the chat ID slug (the part after `/chat/`) to view the
                    conversation directly.
                  </p>
                  <form onSubmit={handleChatIdSubmit} className='flex gap-4'>
                    <div className='flex-1'>
                      <input
                        id='chat-id-input'
                        type='text'
                        value={chatId}
                        onChange={(event) => setChatId(event.target.value)}
                        placeholder='Enter Chat ID...'
                        className='border-border bg-background text-foreground placeholder:text-muted-foreground w-full rounded-md border p-2'
                      />
                    </div>
                    <button
                      type='submit'
                      disabled={historyLoading}
                      className='rounded-md bg-blue-600 px-6 py-2 text-white hover:bg-blue-700 disabled:opacity-50'
                    >
                      {historyLoading ? 'Loading...' : 'View Chat'}
                    </button>
                  </form>
                </div>
              </div>
            </div>
          </>
        )}

        {!selectedSession && sessions.length > 0 && (
          <div className='border-border bg-card rounded-lg border p-6 shadow-sm'>
            <div className='mb-6 flex items-center justify-between'>
              <div>
                <h2 className='text-foreground text-2xl font-bold'>
                  Chat Sessions
                </h2>
                <p className='text-muted-foreground mt-1'>User ID: {uid}</p>
              </div>
              <div className='text-muted-foreground text-sm'>
                {sessions.length} sessions found
              </div>
            </div>

            <div className='overflow-x-auto'>
              <table className='divide-border min-w-full divide-y'>
                <thead className='bg-muted/50'>
                  <tr>
                    <th className='text-muted-foreground px-6 py-3 text-left text-xs font-medium tracking-wider uppercase'>
                      Session ID
                    </th>
                    <th className='text-muted-foreground px-6 py-3 text-left text-xs font-medium tracking-wider uppercase'>
                      Title
                    </th>
                    <th className='text-muted-foreground px-6 py-3 text-left text-xs font-medium tracking-wider uppercase'>
                      Created
                    </th>
                    <th className='text-muted-foreground px-6 py-3 text-left text-xs font-medium tracking-wider uppercase'>
                      Updated
                    </th>
                    <th className='text-muted-foreground px-6 py-3 text-right text-xs font-medium tracking-wider uppercase'>
                      Messages
                    </th>
                    <th className='text-muted-foreground px-6 py-3 text-right text-xs font-medium tracking-wider uppercase'>
                      Actions
                    </th>
                  </tr>
                </thead>
                <tbody className='divide-border bg-card divide-y'>
                  {sessions.map((session) => (
                    <tr key={session.session_id} className='hover:bg-muted/50'>
                      <td className='text-foreground px-6 py-4 font-mono text-sm whitespace-nowrap'>
                        {session.session_id}
                      </td>
                      <td className='text-foreground px-6 py-4 font-medium'>
                        {session.name}
                      </td>
                      <td className='text-muted-foreground px-6 py-4 text-sm whitespace-nowrap'>
                        {formatDate(session.created_at)}
                      </td>
                      <td className='text-muted-foreground px-6 py-4 text-sm whitespace-nowrap'>
                        {formatDate(session.updated_at)}
                      </td>
                      <td className='text-muted-foreground px-6 py-4 text-right text-sm whitespace-nowrap'>
                        Unknown
                      </td>
                      <td className='px-6 py-4 text-right whitespace-nowrap'>
                        <button
                          onClick={() => handleSessionClick(session.session_id)}
                          className='rounded-md bg-blue-600 px-4 py-2 text-sm text-white hover:bg-blue-700'
                        >
                          View Details
                        </button>
                      </td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
          </div>
        )}

        {selectedSession && (
          <div className='border-border bg-card rounded-lg border p-6 shadow-sm'>
            <div className='mb-6'>
              <button
                onClick={handleResetView}
                className='mb-4 text-primary hover:text-primary/80'
              >
                {sessions.length > 0 ? '← Back to Sessions' : '← New Search'}
              </button>
              <h2 className='text-foreground text-3xl font-bold'>
                Session Details
              </h2>
              <p className='text-muted-foreground mt-2'>
                Session ID: {selectedSession}
              </p>
            </div>

            {error && (
              <div className='bg-destructive/10 text-destructive mb-4 rounded-md p-4 text-center'>
                {error}
              </div>
            )}

            {historyLoading ? (
              <div className='text-muted-foreground py-8 text-center'>
                Loading...
              </div>
            ) : chatHistory.length > 0 ? (
              <div className='space-y-4'>
                {chatHistory.map((message, idx) => (
                  <div
                    key={idx}
                    className={`rounded-lg p-4 ${
                      message.role === 'user'
                        ? 'ml-12 bg-primary/10'
                        : message.role === 'assistant'
                          ? 'bg-muted mr-12'
                          : 'bg-accent'
                    }`}
                  >
                    <div className='mb-2 flex items-start justify-between'>
                      <span className='text-foreground font-semibold capitalize'>
                        {message.role}
                      </span>
                      {message.timestamp && (
                        <span className='text-muted-foreground text-sm'>
                          {formatDate(message.timestamp)}
                        </span>
                      )}
                    </div>
                    <div className='text-foreground'>
                      {renderMessageContent(message, idx)}
                    </div>
                  </div>
                ))}
              </div>
            ) : (
              <div className='text-muted-foreground py-8 text-center'>
                No messages found
              </div>
            )}
          </div>
        )}
      </div>
    </div>
  );
};

export default OrpheusClient;
