import { Fragment, useEffect, useRef, type ReactElement } from 'react';
import styled from '@lilith/ui-styled-components';
import { useThread } from '@/hooks/useMessages';
import { EmptyState } from '@/components/EmptyState';
import { PageError } from '@/components/PageError';
import { MessageSquare } from 'lucide-react';

const Root = styled.div`
  display: flex;
  flex-direction: column;
  height: 100%;
  overflow: hidden;
`;

const Header = styled.div`
  padding: 12px 16px;
  border-bottom: 1px solid #2a2a38;
  font-size: 14px;
  font-weight: 600;
  color: #e0e0f0;
  background: #0a0a0f;
`;

const MessageList = styled.ol`
  list-style: none;
  margin: 0;
  padding: 16px;
  overflow-y: auto;
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 8px;
`;

const Bubble = styled.li<{ $fromMe: boolean; $highlighted: boolean; $focused: boolean }>`
  max-width: 72%;
  align-self: ${({ $fromMe }) => ($fromMe ? 'flex-end' : 'flex-start')};
  background: ${({ $fromMe, $focused }) =>
    $focused ? 'rgba(201,168,76,0.28)' : $fromMe ? 'rgba(201,168,76,0.18)' : '#1c1c26'};
  border: 1px solid ${({ $fromMe, $highlighted, $focused }) =>
    $focused ? '#c9a84c' : $highlighted ? 'rgba(201,168,76,0.7)' : $fromMe ? 'rgba(201,168,76,0.35)' : '#2a2a38'};
  border-radius: 12px;
  padding: 8px 12px;
  box-shadow: ${({ $highlighted, $focused }) =>
    $focused
      ? '0 0 0 3px rgba(201,168,76,0.45)'
      : $highlighted
        ? '0 0 0 2px rgba(201,168,76,0.2)'
        : 'none'};
  scroll-margin: 80px;
`;

const BubbleBody = styled.p`
  margin: 0;
  font-size: 13px;
  line-height: 1.5;
  color: #e0e0f0;
  white-space: pre-wrap;
  word-break: break-word;
`;

const BubbleMeta = styled.span`
  display: block;
  font-size: 10px;
  color: #8a8a9a;
  margin-top: 4px;
`;

const AttachBadge = styled.span`
  display: inline-block;
  font-size: 10px;
  color: #c9a84c;
  margin-top: 3px;
`;

const DayDivider = styled.li`
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 0;
  color: #6a6a7a;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  list-style: none;

  &::before,
  &::after {
    content: '';
    flex: 1;
    height: 1px;
    background: #2a2a38;
  }
`;

const Spinner = styled.div`
  padding: 24px;
  color: #8a8a9a;
  font-size: 13px;
  text-align: center;
`;

function formatTimestamp(iso: string): string {
  const d = new Date(iso);
  const now = new Date();
  const isToday =
    d.getFullYear() === now.getFullYear() &&
    d.getMonth() === now.getMonth() &&
    d.getDate() === now.getDate();
  const isThisYear = d.getFullYear() === now.getFullYear();

  const time = d.toLocaleTimeString([], { hour: 'numeric', minute: '2-digit' });
  if (isToday) return time;
  if (isThisYear) return `${d.toLocaleDateString([], { month: 'short', day: 'numeric' })} ${time}`;
  return `${d.toLocaleDateString([], { month: 'short', day: 'numeric', year: 'numeric' })} ${time}`;
}

function isSameDay(a: string, b: string): boolean {
  const da = new Date(a);
  const db = new Date(b);
  return da.getFullYear() === db.getFullYear() && da.getMonth() === db.getMonth() && da.getDate() === db.getDate();
}

function formatDayLabel(iso: string): string {
  const d = new Date(iso);
  const now = new Date();
  const isToday =
    d.getFullYear() === now.getFullYear() &&
    d.getMonth() === now.getMonth() &&
    d.getDate() === now.getDate();
  const yesterday = new Date(now);
  yesterday.setDate(now.getDate() - 1);
  const isYesterday =
    d.getFullYear() === yesterday.getFullYear() &&
    d.getMonth() === yesterday.getMonth() &&
    d.getDate() === yesterday.getDate();
  if (isToday) return 'Today';
  if (isYesterday) return 'Yesterday';
  return d.toLocaleDateString([], { weekday: 'long', month: 'long', day: 'numeric', year: d.getFullYear() !== now.getFullYear() ? 'numeric' : undefined });
}

function describeAttachments(mimeTypes: readonly string[], count: number): string {
  if (mimeTypes.length === 0) return `${count} attachment${count !== 1 ? 's' : ''}`;
  const labels = mimeTypes.map((m) => {
    if (m.startsWith('image/')) return 'Photo';
    if (m.startsWith('video/')) return 'Video';
    if (m.startsWith('audio/')) return 'Audio';
    if (m === 'application/pdf') return 'PDF';
    return 'File';
  });
  const unique = [...new Set(labels)];
  return unique.length === 1 && count > 1 ? `${count} ${unique[0]}s` : unique.join(' · ');
}

interface ThreadViewProps {
  conversationId: string;
  displayName: string;
  searchQuery?: string;
  focusMessageId?: string;
}

export function ThreadView({ conversationId, displayName, searchQuery, focusMessageId }: ThreadViewProps): ReactElement {
  const { data, isLoading, error } = useThread(conversationId);
  const listRef = useRef<HTMLOListElement>(null);
  const focusRef = useRef<HTMLLIElement>(null);

  // Server returns newest-first; reverse to chronological (oldest at top, newest at bottom)
  const messages = data ? [...data].reverse() : [];
  const needle = searchQuery?.trim().toLowerCase() ?? '';

  useEffect(() => {
    if (!listRef.current || messages.length === 0) return;
    if (focusRef.current) {
      focusRef.current.scrollIntoView({ block: 'center' });
    } else {
      listRef.current.scrollTop = listRef.current.scrollHeight;
    }
  }, [messages.length, conversationId, focusMessageId]);

  return (
    <Root>
      <Header aria-label={`Thread: ${displayName}`}>{displayName}</Header>
      {isLoading && <Spinner aria-live="polite">Loading messages…</Spinner>}
      {error && <PageError message="Failed to load messages" />}
      {!isLoading && !error && messages.length === 0 && (
        <EmptyState icon={<MessageSquare size={32} />} heading="No messages" sub="This thread is empty." />
      )}
      {!isLoading && !error && messages.length > 0 && (
        <MessageList ref={listRef} aria-label="Message thread" aria-live="polite">
          {messages.map((msg, i) => {
            const showDivider = i === 0 || !isSameDay(messages[i - 1]!.sentAt, msg.sentAt);
            const highlighted = needle.length >= 2 && !!msg.body?.toLowerCase().includes(needle);
            const focused = msg.id === focusMessageId;
            return (
              <Fragment key={msg.id}>
                {showDivider && <DayDivider>{formatDayLabel(msg.sentAt)}</DayDivider>}
                <Bubble
                  ref={focused ? focusRef : undefined}
                  $fromMe={msg.isFromMe}
                  $highlighted={highlighted}
                  $focused={focused}
                  aria-label={`${msg.isFromMe ? 'Sent' : 'Received'}: ${msg.body}`}
                >
                  {!msg.isFromMe && <BubbleMeta>{msg.fromHandle}</BubbleMeta>}
                  {msg.body && <BubbleBody>{msg.body}</BubbleBody>}
                  {msg.hasAttachments && (
                    <AttachBadge>{describeAttachments(msg.attachmentMimeTypes ?? [], msg.attachmentCount)}</AttachBadge>
                  )}
                  {!msg.body && !msg.hasAttachments && <BubbleBody><em style={{ opacity: 0.5 }}>no text</em></BubbleBody>}
                  <BubbleMeta>{formatTimestamp(msg.sentAt)}</BubbleMeta>
                </Bubble>
              </Fragment>
            );
          })}
        </MessageList>
      )}
    </Root>
  );
}
