'use client';

import React from 'react';
import { Avatar, Box, IconButton, TextField, Typography } from '@mui/material';
import SendRoundedIcon from '@mui/icons-material/SendRounded';
import AssignmentRoundedIcon from '@mui/icons-material/AssignmentRounded';
import CheckCircleRoundedIcon from '@mui/icons-material/CheckCircleRounded';
import DeleteRoundedIcon from '@mui/icons-material/DeleteRounded';
import ScheduleRoundedIcon from '@mui/icons-material/ScheduleRounded';
import EventNoteRoundedIcon from '@mui/icons-material/EventNoteRounded';
import NotificationsActiveRoundedIcon from '@mui/icons-material/NotificationsActiveRounded';
import WarningAmberRoundedIcon from '@mui/icons-material/WarningAmberRounded';
import InfoOutlinedIcon from '@mui/icons-material/InfoOutlined';
import type { Chat, Message } from '@/api/chat';
import { getMessages, getChatMessagesByUuid, sendMessage, markMessagesAsRead } from '@/api/chat';
import { useChatWebSocket } from '@/hooks/useChatWebSocket';
import { getUserStatus, subscribeToUserStatus } from '@/hooks/usePresenceWebSocket';

function formatTime(ts?: string) {
  try {
    if (!ts) return '';
    const d = new Date(ts);
    if (Number.isNaN(d.getTime())) return '';
    return d.toLocaleTimeString('ru-RU', { hour: '2-digit', minute: '2-digit' });
  } catch {
    return '';
  }
}

function formatRelativeStamp(ts?: string) {
  if (!ts) return '';
  const d = new Date(ts);
  if (Number.isNaN(d.getTime())) return '';
  const now = new Date();
  const diffMs = now.getTime() - d.getTime();
  if (diffMs < 0) return formatTime(ts);
  const diffMin = Math.floor(diffMs / 60000);
  const diffHr = Math.floor(diffMs / 3600000);

  const pluralRu = (n: number, one: string, few: string, many: string) => {
    const mod10 = n % 10;
    const mod100 = n % 100;
    if (mod10 === 1 && mod100 !== 11) return one;
    if (mod10 >= 2 && mod10 <= 4 && (mod100 < 12 || mod100 > 14)) return few;
    return many;
  };

  if (diffMin < 1) return 'только что';
  if (diffMin < 60) return `${diffMin} ${pluralRu(diffMin, 'минуту', 'минуты', 'минут')} назад`;
  if (diffHr < 6) {
    if (diffHr === 1) return 'час назад';
    return `${diffHr} ${pluralRu(diffHr, 'час', 'часа', 'часов')} назад`;
  }
  // больше 6 часов — показываем HH:mm
  return formatTime(ts);
}

function dateKey(ts?: string) {
  if (!ts) return '';
  const d = new Date(ts);
  if (Number.isNaN(d.getTime())) return '';
  const y = d.getFullYear();
  const m = String(d.getMonth() + 1).padStart(2, '0');
  const day = String(d.getDate()).padStart(2, '0');
  return `${y}-${m}-${day}`;
}

function formatDayHeader(ts?: string) {
  if (!ts) return '';
  const d = new Date(ts);
  if (Number.isNaN(d.getTime())) return '';
  const now = new Date();
  const todayKey = dateKey(now.toISOString());
  const yKey = dateKey(new Date(now.getTime() - 24 * 3600000).toISOString());
  const k = dateKey(ts);
  if (k === todayKey) return 'Сегодня';
  if (k === yKey) return 'Вчера';
  const dd = String(d.getDate()).padStart(2, '0');
  const mm = String(d.getMonth() + 1).padStart(2, '0');
  const yyyy = String(d.getFullYear());
  return `${dd}.${mm}.${yyyy}`;
}

function formatLastSeen(iso: string | null) {
  if (!iso) return null;
  try {
    const d = new Date(iso);
    const now = new Date();
    const sameYear = d.getFullYear() === now.getFullYear();
    const sameDay = d.toDateString() === now.toDateString();
    if (sameDay) {
      return `Был(а) в сети сегодня в ${d.toLocaleTimeString('ru-RU', { hour: '2-digit', minute: '2-digit' })}`;
    }
    const datePart = d.toLocaleDateString('ru-RU', {
      day: 'numeric',
      month: 'long',
      ...(sameYear ? {} : { year: 'numeric' }),
    });
    const timePart = d.toLocaleTimeString('ru-RU', { hour: '2-digit', minute: '2-digit' });
    return `Был(а) в сети ${datePart} в ${timePart}`;
  } catch {
    return null;
  }
}

const SYSTEM_EMOJI_PREFIX = /^[\s🔔📝🗑️🗑✅📤⚠️⏰📅📚]+/;

function stripLeadingEmojis(s: string): string {
  const t = (s || '').trim();
  return t.replace(SYSTEM_EMOJI_PREFIX, '').replace(/^[-–—•\s]+/, '').trim() || t;
}

/** Убирает HTML-теги из строки (чтобы в чате не отображались теги в уведомлениях). */
function stripHtml(s: string): string {
  if (typeof s !== 'string') return '';
  return s.replace(/<[^>]*>/g, '').trim();
}

type SystemTheme = {
  icon: React.ReactNode;
  label: string;
};

function getSystemMessageTheme(content: string): SystemTheme {
  const raw = (content || '').trim();
  const lower = raw.toLowerCase();

  if (/проверено|проверен/.test(lower) && /домашнее|дз|задани/.test(lower)) {
    return { icon: <CheckCircleRoundedIcon sx={{ fontSize: 18 }} />, label: 'ДЗ проверено' };
  }
  if (/(сдано|сдал)\s|дз сдано|домашнее задание сдано/.test(lower)) {
    return { icon: <SendRoundedIcon sx={{ fontSize: 18 }} />, label: 'ДЗ сдано' };
  }
  if (/просрочено|просрочен/.test(lower)) {
    return { icon: <WarningAmberRoundedIcon sx={{ fontSize: 18 }} />, label: 'Просрочено' };
  }
  if (/напоминание|дедлайн|напоминание о дедлайне/.test(lower)) {
    return { icon: <ScheduleRoundedIcon sx={{ fontSize: 18 }} />, label: 'Напоминание' };
  }
  if (/удалено|удален|удалил|сообщение удалено/.test(lower)) {
    return { icon: <DeleteRoundedIcon sx={{ fontSize: 18 }} />, label: 'Удалено' };
  }
  if (/занятие началось|занятие завершено|урок начался|урок завершен|перенесен|отменен/.test(lower)) {
    return { icon: <EventNoteRoundedIcon sx={{ fontSize: 18 }} />, label: 'Занятие' };
  }
  if (/новое домашнее|назначено.*домашнее|домашнее задание|^дз\s|дз назначено/.test(lower)) {
    return { icon: <AssignmentRoundedIcon sx={{ fontSize: 18 }} />, label: 'Домашнее задание' };
  }
  if (/уведомление|напоминани/.test(lower) || /^🔔/.test(raw)) {
    return { icon: <NotificationsActiveRoundedIcon sx={{ fontSize: 18 }} />, label: 'Уведомление' };
  }

  return { icon: <InfoOutlinedIcon sx={{ fontSize: 18 }} />, label: 'Системное сообщение' };
}

export function ChatWindow({
  chat,
  currentUserId,
  onBack,
  onMessagesMarkedAsRead,
}: {
  chat: Chat | null;
  currentUserId: number | null;
  onBack?: () => void;
  /** Вызывается после того, как часть сообщений отмечена прочитанными (для обновления счётчика в списке чатов) */
  onMessagesMarkedAsRead?: () => void;
}) {
  const [messages, setMessages] = React.useState<Message[]>([]);
  const [loading, setLoading] = React.useState(false);
  const [loadingMore, setLoadingMore] = React.useState(false);
  const [page, setPage] = React.useState(1);
  const [hasMore, setHasMore] = React.useState(false);
  const [text, setText] = React.useState('');
  const listRef = React.useRef<HTMLDivElement>(null);
  const lastWheelUpAtRef = React.useRef<number>(0);
  const markedReadRef = React.useRef<Set<string>>(new Set());
  const lastSentRef = React.useRef<{ id: number | string; uuid?: string } | null>(null);

  const chatUuid = (chat as any)?.uuid || null;
  const otherUserId = (chat as any)?.other_user_id ?? null;
  const [presence, setPresence] = React.useState<{ is_online: boolean; last_activity: string | null } | null>(null);

  // initial from chat list + realtime updates
  React.useEffect(() => {
    if (!chat) return;
    setPresence({
      is_online: !!(chat as any).other_is_online,
      last_activity: (chat as any).other_last_activity ?? null,
    });
  }, [chat]);

  // Сброс при смене чата
  React.useEffect(() => {
    markedReadRef.current = new Set();
    lastSentRef.current = null;
  }, [chatUuid]);

  React.useEffect(() => {
    if (!otherUserId) return;
    const existing = getUserStatus(otherUserId);
    if (existing) setPresence({ is_online: existing.is_online, last_activity: existing.last_activity });
    const unsubscribe = subscribeToUserStatus((s) => {
      if (s.user_id === otherUserId) setPresence({ is_online: s.is_online, last_activity: s.last_activity });
    });
    return () => { unsubscribe?.(); };
  }, [otherUserId]);

  useChatWebSocket({
    chatUuid,
    enabled: !!chatUuid,
    onMessage: (m) => {
      const chatId = chat?.id != null ? Number(chat.id) : null;
      const msgChatId = m.chat != null ? Number(m.chat) : null;
      if (chatId == null || msgChatId !== chatId) return;
      const mid = (m as any).id;
      const muuid = (m as any).uuid;
      const sent = lastSentRef.current;
      if (sent && (String(mid) === String(sent.id) || (muuid != null && sent.uuid != null && String(muuid) === String(sent.uuid)))) {
        lastSentRef.current = null;
        return;
      }
      setMessages((prev) => {
        const isDuplicate = prev.some((x) => {
          const sameId = mid != null && x.id != null && String(x.id) === String(mid);
          const sameUuid = muuid != null && (x as any).uuid != null && String((x as any).uuid) === String(muuid);
          return sameId || sameUuid;
        });
        if (isDuplicate) return prev;
        return [...prev, m];
      });
    },
  });

  React.useEffect(() => {
    if (!chat) return;
    setLoading(true);
    setLoadingMore(false);
    setPage(1);
    setHasMore(false);

    (async () => {
      try {
        const pageSize = 30;
        const resp = chatUuid
          ? await getChatMessagesByUuid(chatUuid, { page: 1, page_size: pageSize })
          : await getMessages(chat.id, { page: 1, page_size: pageSize });
        const initial = (resp.results || []) as Message[];
        const sorted = [...initial].sort((a: any, b: any) => {
          const ta = a?.created_at ? new Date(a.created_at).getTime() : 0;
          const tb = b?.created_at ? new Date(b.created_at).getTime() : 0;
          return ta - tb;
        });
        setMessages(sorted);
        setHasMore(!!(resp as any).next || ((resp as any).count ?? 0) > sorted.length);

        // Молниеносный скролл вниз (мгновенно, без анимации)
        requestAnimationFrame(() => {
          const el = listRef.current;
          if (el) el.scrollTo({ top: el.scrollHeight, behavior: 'auto' });
        });
      } finally {
        setLoading(false);
      }
    })();
  }, [chat?.id, chatUuid]);

  // Отмечаем сообщения прочитанными, когда они попадают в зону скролла
  React.useEffect(() => {
    if (!chatUuid || !listRef.current || messages.length === 0) return;
    const container = listRef.current;
    const observer = new IntersectionObserver(
      (entries) => {
        const toMark: string[] = [];
        for (const e of entries) {
          if (!e.isIntersecting) continue;
          const uuid = (e.target as HTMLElement).getAttribute('data-message-uuid');
          const isMine = (e.target as HTMLElement).getAttribute('data-is-mine') === 'true';
          if (uuid && !isMine && !markedReadRef.current.has(uuid)) {
            toMark.push(uuid);
            markedReadRef.current.add(uuid);
          }
        }
        if (toMark.length > 0) {
          markMessagesAsRead(chatUuid, toMark)
            .then(() => onMessagesMarkedAsRead?.())
            .catch(() => {});
        }
      },
      { root: container, rootMargin: '0px', threshold: 0.5 }
    );
    const nodes = container.querySelectorAll('[data-message-uuid]');
    nodes.forEach((n) => observer.observe(n));
    return () => observer.disconnect();
  }, [chatUuid, messages, onMessagesMarkedAsRead]);

  const loadOlder = React.useCallback(async () => {
    if (!chat || loading || loadingMore || !hasMore) return;
    const container = listRef.current;
    if (!container) return;
    setLoadingMore(true);
    const prevScrollHeight = container.scrollHeight;
    const prevScrollTop = container.scrollTop;

    try {
      const nextPage = page + 1;
      const pageSize = 30;
      const resp = chatUuid
        ? await getChatMessagesByUuid(chatUuid, { page: nextPage, page_size: pageSize })
        : await getMessages(chat.id, { page: nextPage, page_size: pageSize });

      const batch = (resp.results || []) as Message[];
      const sortedBatch = [...batch].sort((a: any, b: any) => {
        const ta = a?.created_at ? new Date(a.created_at).getTime() : 0;
        const tb = b?.created_at ? new Date(b.created_at).getTime() : 0;
        return ta - tb;
      });

      setMessages((prev) => {
        const existingKeys = new Set(prev.map((m: any) => m?.uuid || m?.id));
        const toAdd = sortedBatch.filter((m: any) => !existingKeys.has(m?.uuid || m?.id));
        const merged = [...toAdd, ...prev];
        merged.sort((a: any, b: any) => {
          const ta = a?.created_at ? new Date(a.created_at).getTime() : 0;
          const tb = b?.created_at ? new Date(b.created_at).getTime() : 0;
          return ta - tb;
        });
        return merged;
      });

      setPage(nextPage);
      setHasMore(!!(resp as any).next);
    } finally {
      // сохранить позицию прокрутки
      setTimeout(() => {
        const c = listRef.current;
        if (!c) return;
        const newScrollHeight = c.scrollHeight;
        c.scrollTop = prevScrollTop + (newScrollHeight - prevScrollHeight);
      }, 0);
      setLoadingMore(false);
    }
  }, [chat, chatUuid, hasMore, loading, loadingMore, page]);

  const handleSend = async () => {
    if (!chat) return;
    const content = text.trim();
    if (!content) return;
    setText('');
    try {
      const msg = await sendMessage(chat.id, content);
      lastSentRef.current = { id: msg.id, uuid: (msg as any).uuid };
      const safeMsg = { ...msg, created_at: (msg as any).created_at || new Date().toISOString() } as Message;
      setMessages((prev) => [...prev, safeMsg]);
      requestAnimationFrame(() => {
        requestAnimationFrame(() => {
          const el = listRef.current;
          if (el) el.scrollTo({ top: el.scrollHeight, behavior: 'smooth' });
        });
      });
    } catch {
      // rollback
      setText(content);
    }
  };

  if (!chat) {
    return (
      <Box
        className="ios-glass-panel"
        sx={{
          flex: 1,
          borderRadius: '20px',
          p: 3,
          background: 'var(--ios26-glass)',
          border: '1px solid var(--ios26-glass-border)',
          backdropFilter: 'var(--ios26-blur)',
          display: 'flex',
          alignItems: 'center',
          justifyContent: 'center',
          color: 'var(--md-sys-color-on-surface-variant)',
        }}
      >
        Выберите чат из списка
      </Box>
    );
  }

  return (
    <Box
      className="ios-glass-panel"
      data-tour="chat-window"
      sx={{
        flex: 1,
        borderRadius: '20px',
        p: 2,
        background: 'var(--ios26-glass)',
        border: '1px solid var(--ios26-glass-border)',
        backdropFilter: 'var(--ios26-blur)',
        display: 'flex',
        flexDirection: 'column',
        minHeight: 0,
      }}
    >
      {/* Header */}
      <Box sx={{ px: 1, py: 1, display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
        <Box sx={{ display: 'flex', alignItems: 'center', gap: 1.25, minWidth: 0 }}>
          {onBack && (
            <IconButton
              onClick={onBack}
              sx={{ mr: 0.5, color: 'var(--md-sys-color-on-surface)' }}
              aria-label="Назад"
            >
              <span className="material-symbols-outlined" style={{ fontSize: 24 }}>
                arrow_back
              </span>
            </IconButton>
          )}
          <Avatar
            src={(chat as any).avatar_url || undefined}
            alt={chat.participant_name || 'Аватар'}
            sx={{
              width: 40,
              height: 40,
              bgcolor: 'rgba(116, 68, 253, 0.18)',
              color: 'var(--md-sys-color-primary)',
              fontWeight: 800,
            }}
          >
            {(chat.participant_name || 'Ч')
              .trim()
              .split(/\s+/)
              .slice(0, 2)
              .map((p) => p[0])
              .join('')
              .toUpperCase()}
          </Avatar>
          <Box sx={{ minWidth: 0 }}>
            <Typography
              sx={{
                fontWeight: 800,
                fontSize: 16,
                color: 'var(--md-sys-color-on-surface)',
                whiteSpace: 'nowrap',
                overflow: 'hidden',
                textOverflow: 'ellipsis',
              }}
            >
              {chat.participant_name || 'Чат'}
            </Typography>
            <Typography sx={{ fontSize: 12, color: 'var(--md-sys-color-on-surface-variant)' }}>
              {presence?.is_online
                ? 'Онлайн'
                : formatLastSeen(presence?.last_activity ?? null) || 'Оффлайн'}
            </Typography>
          </Box>
        </Box>
      </Box>

      {/* Messages */}
      <Box
        ref={listRef}
        sx={{
          flex: 1,
          minHeight: 0,
          overflowY: 'auto',
          px: 1,
          py: 1,
          display: 'flex',
          flexDirection: 'column',
          gap: 1,
        }}
        onWheel={(e) => {
          // deltaY < 0 = прокрутка вверх
          if (e.deltaY < 0) lastWheelUpAtRef.current = Date.now();
        }}
        onScroll={(e) => {
          const el = e.currentTarget;
          // Подгружаем только если:
          // - до верха осталось < 40px
          // - пользователь именно скроллит вверх (wheel up недавно)
          const nearTop = el.scrollTop < 40;
          const wheelUpRecently = Date.now() - lastWheelUpAtRef.current < 200;
          if (nearTop && wheelUpRecently) loadOlder();
        }}
      >
        {loadingMore && (
          <Typography sx={{ color: 'var(--md-sys-color-on-surface-variant)', textAlign: 'center', fontSize: 12 }}>
            Загрузка…
          </Typography>
        )}
        {loading ? (
          <Typography sx={{ color: 'var(--md-sys-color-on-surface-variant)', textAlign: 'center', mt: 2 }}>
            Загрузка…
          </Typography>
        ) : (
          (() => {
            const out: React.ReactNode[] = [];
            let prevDay = '';
            const seen = new Set<string>();
            const uniqueMessages = messages.filter((m) => {
              const k = String((m as any).uuid ?? m.id ?? '');
              if (!k || seen.has(k)) return false;
              seen.add(k);
              return true;
            });

            uniqueMessages.forEach((m, idx) => {
              const created = (m as any).created_at as string | undefined;
              const day = dateKey(created);
              if (day && day !== prevDay) {
                out.push(
                  <Box
                    key={`day-${day}`}
                    sx={{
                      alignSelf: 'center',
                      px: 1.5,
                      py: 0.5,
                      borderRadius: 999,
                      backgroundColor: 'rgba(255,255,255,0.7)',
                      border: '1px solid rgba(0,0,0,0.06)',
                      color: 'var(--md-sys-color-on-surface-variant)',
                      fontSize: 12,
                      fontWeight: 700,
                      mb: 0.5,
                    }}
                  >
                    {formatDayHeader(created)}
                  </Box>
                );
                prevDay = day;
              }

            const senderId =
              (m as any).sender_id ??
              (typeof (m as any).sender === 'number'
                ? (m as any).sender
                : (m as any).sender?.id ?? null);
            const isMine = !!currentUserId && senderId === currentUserId;
            const isSystem =
              (m as any).message_type === 'system' ||
              (typeof (m as any).sender === 'string' && (m as any).sender.toLowerCase() === 'system') ||
              (!senderId && (m as any).sender_name === 'System');
            const msgContent = (m as any).content || '';
            const sysTheme = isSystem ? getSystemMessageTheme(msgContent) : null;
            const sysDisplayContent = isSystem ? stripHtml(stripLeadingEmojis(msgContent)) : '';

            const msgUuid = (m as any).uuid ? String((m as any).uuid) : null;
            const msgKey = (m as any).uuid || m.id || `msg-${idx}`;
            out.push(
              <Box
                key={msgKey}
                data-message-uuid={msgUuid ?? undefined}
                data-is-mine={isMine}
                sx={{
                  alignSelf: isSystem ? 'center' : isMine ? 'flex-end' : 'flex-start',
                  maxWidth: isSystem ? '85%' : '75%',
                  px: 1.25,
                  py: 0.75,
                  borderRadius: 2,
                  backgroundColor: isSystem
                    ? 'rgb(245 242 253)'
                    : isMine
                      ? 'var(--md-sys-color-primary)'
                      : 'rgba(255,255,255,0.75)',
                  color: isSystem
                    ? 'var(--md-sys-color-on-surface)'
                    : isMine
                      ? 'var(--md-sys-color-on-primary)'
                      : 'var(--md-sys-color-on-surface)',
                  border: isSystem ? '1px dashed rgba(116, 68, 253, 0.25)' : isMine ? 'none' : '1px solid rgba(0,0,0,0.06)',
                }}
              >
                {isSystem && sysTheme && (
                  <>
                    <Box
                      sx={{
                        display: 'flex',
                        alignItems: 'center',
                        gap: 0.75,
                        mb: 0.25,
                        color: 'var(--md-sys-color-primary)',
                      }}
                    >
                      <Box sx={{ display: 'flex', alignItems: 'center' }}>{sysTheme.icon}</Box>
                      <Typography
                        sx={{
                          fontSize: 11,
                          fontWeight: 800,
                          letterSpacing: '0.06em',
                          color: 'inherit',
                          textTransform: 'uppercase',
                        }}
                      >
                        {sysTheme.label}
                      </Typography>
                    </Box>
                    <Typography sx={{ fontSize: 13, whiteSpace: 'pre-wrap' }}>
                      {sysDisplayContent || '—'}
                    </Typography>
                  </>
                )}
                {!isSystem && (
                  <Typography sx={{ fontSize: 13, whiteSpace: 'pre-wrap' }}>{msgContent}</Typography>
                )}
                <Typography sx={{ fontSize: 11, opacity: 0.7, mt: 0.25, textAlign: 'right' }}>
                  {formatRelativeStamp((m as any).created_at)}
                </Typography>
              </Box>
            );
            });

            return out;
          })()
        )}
      </Box>

      {/* Input */}
      <Box
        sx={{
          pt: 1.25,
          borderTop: '1px solid rgba(0,0,0,0.06)',
          display: 'flex',
          gap: 1,
          alignItems: 'center',
        }}
      >
        <TextField
          value={text}
          onChange={(e) => setText(e.target.value)}
          placeholder="Сообщение…"
          fullWidth
          multiline
          minRows={1}
          maxRows={4}
          sx={{
            '& .MuiInputBase-root': {
              borderRadius: 3,
              backgroundColor: 'rgba(255,255,255,0.85)',
            },
          }}
          onKeyDown={(e) => {
            if (e.key === 'Enter' && !e.shiftKey) {
              e.preventDefault();
              handleSend();
            }
          }}
        />
        <IconButton
          onClick={handleSend}
          sx={{
            backgroundColor: 'var(--md-sys-color-primary)',
            color: 'var(--md-sys-color-on-primary)',
            '&:hover': { backgroundColor: 'color-mix(in srgb, var(--md-sys-color-primary) 88%, #000 12%)' },
          }}
        >
          <SendRoundedIcon />
        </IconButton>
      </Box>
    </Box>
  );
}

