'use client';

import { useRef, useState, useEffect, useCallback } from 'react';

import Box from '@mui/material/Box';
import List from '@mui/material/List';
import Stack from '@mui/material/Stack';
import Alert from '@mui/material/Alert';
import Badge from '@mui/material/Badge';
import Avatar from '@mui/material/Avatar';
import Button from '@mui/material/Button';
import Dialog from '@mui/material/Dialog';
import Divider from '@mui/material/Divider';
import TextField from '@mui/material/TextField';
import Typography from '@mui/material/Typography';
import IconButton from '@mui/material/IconButton';
import DialogTitle from '@mui/material/DialogTitle';
import ListItemText from '@mui/material/ListItemText';
import DialogContent from '@mui/material/DialogContent';
import DialogActions from '@mui/material/DialogActions';
import InputAdornment from '@mui/material/InputAdornment';
import ListItemButton from '@mui/material/ListItemButton';
import CircularProgress from '@mui/material/CircularProgress';

import { paths } from 'src/routes/paths';

import { useChatWebSocket } from 'src/hooks/use-chat-websocket';

import {
  createChat,
  getMessages,
  searchUsers,
  sendMessage,
  getConversations,
  markMessagesAsRead,
  getChatMessagesByUuid,
} from 'src/utils/chat-api';

import { DashboardContent } from 'src/layouts/dashboard';

import { Iconify } from 'src/components/iconify';
import { CustomBreadcrumbs } from 'src/components/custom-breadcrumbs';

import { useAuthContext } from 'src/auth/hooks';

// ----------------------------------------------------------------------

function formatTime(ts) {
  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 dateKey(ts) {
  if (!ts) return '';
  const d = new Date(ts);
  if (Number.isNaN(d.getTime())) return '';
  return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;
}

function formatDayHeader(ts) {
  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() - 86400000).toISOString());
  const k = dateKey(ts);
  if (k === todayKey) return 'Сегодня';
  if (k === yKey) return 'Вчера';
  return `${String(d.getDate()).padStart(2, '0')}.${String(d.getMonth() + 1).padStart(2, '0')}.${d.getFullYear()}`;
}

function getInitials(name) {
  return (name || 'Ч')
    .trim()
    .split(/\s+/)
    .slice(0, 2)
    .map((p) => p[0])
    .join('')
    .toUpperCase();
}

function stripHtml(s) {
  if (typeof s !== 'string') return '';
  return s.replace(/<[^>]*>/g, '').trim();
}

// ----------------------------------------------------------------------

function NewChatDialog({ open, onClose, onCreated }) {
  const [query, setQuery] = useState('');
  const [results, setResults] = useState([]);
  const [searching, setSearching] = useState(false);
  const [creating, setCreating] = useState(false);
  const [error, setError] = useState(null);

  const handleSearch = useCallback(async (q) => {
    if (!q.trim()) {
      setResults([]);
      return;
    }
    try {
      setSearching(true);
      const users = await searchUsers(q.trim());
      setResults(users);
    } catch {
      setResults([]);
    } finally {
      setSearching(false);
    }
  }, []);

  useEffect(() => {
    const timer = setTimeout(() => handleSearch(query), 400);
    return () => clearTimeout(timer);
  }, [query, handleSearch]);

  const handleCreate = async (userId) => {
    try {
      setCreating(true);
      setError(null);
      const chat = await createChat(userId);
      onCreated(chat);
      onClose();
    } catch (e) {
      setError(e?.response?.data?.detail || e?.message || 'Ошибка создания чата');
    } finally {
      setCreating(false);
    }
  };

  const handleClose = () => {
    setQuery('');
    setResults([]);
    setError(null);
    onClose();
  };

  return (
    <Dialog open={open} onClose={handleClose} maxWidth="sm" fullWidth>
      <DialogTitle>Новый чат</DialogTitle>
      <DialogContent>
        <TextField
          label="Поиск пользователя"
          value={query}
          onChange={(e) => setQuery(e.target.value)}
          fullWidth
          autoFocus
          sx={{ mt: 1 }}
          InputProps={{
            endAdornment: searching ? (
              <InputAdornment position="end">
                <CircularProgress size={18} />
              </InputAdornment>
            ) : null,
          }}
        />
        {error && (
          <Alert severity="error" sx={{ mt: 1 }}>
            {error}
          </Alert>
        )}
        <List sx={{ mt: 1 }}>
          {results.map((u) => {
            const name = `${u.first_name || ''} ${u.last_name || ''}`.trim() || u.email || '';
            return (
              <ListItemButton
                key={u.id}
                onClick={() => handleCreate(u.id)}
                disabled={creating}
                sx={{ borderRadius: 1 }}
              >
                <Avatar sx={{ mr: 1.5, width: 36, height: 36 }}>{getInitials(name)}</Avatar>
                <ListItemText primary={name} secondary={u.email} />
              </ListItemButton>
            );
          })}
          {!searching && query.trim() && results.length === 0 && (
            <Typography variant="body2" color="text.secondary" sx={{ px: 2, py: 1 }}>
              Пользователи не найдены
            </Typography>
          )}
        </List>
      </DialogContent>
      <DialogActions>
        <Button onClick={handleClose}>Отмена</Button>
      </DialogActions>
    </Dialog>
  );
}

// ----------------------------------------------------------------------

function ChatList({ chats, selectedUuid, onSelect, onNew, loading }) {
  const [q, setQ] = useState('');

  const filtered = chats.filter((c) => {
    if (!q.trim()) return true;
    const qq = q.toLowerCase();
    return (
      (c.participant_name || '').toLowerCase().includes(qq) ||
      (c.last_message || '').toLowerCase().includes(qq)
    );
  });

  return (
    <Box
      sx={{
        width: { xs: '100%', md: 300 },
        flexShrink: 0,
        borderRight: '1px solid',
        borderColor: 'divider',
        display: 'flex',
        flexDirection: 'column',
        height: '100%',
      }}
    >
      <Stack direction="row" spacing={1} sx={{ p: 1.5, borderBottom: '1px solid', borderColor: 'divider' }}>
        <TextField
          value={q}
          onChange={(e) => setQ(e.target.value)}
          placeholder="Поиск"
          size="small"
          fullWidth
          InputProps={{
            startAdornment: (
              <InputAdornment position="start">
                <Iconify icon="eva:search-outline" width={18} />
              </InputAdornment>
            ),
          }}
        />
        <IconButton onClick={onNew} color="primary" size="small">
          <Iconify icon="eva:edit-outline" width={22} />
        </IconButton>
      </Stack>

      <Box sx={{ flex: 1, overflowY: 'auto' }}>
        {loading ? (
          <Box sx={{ display: 'flex', justifyContent: 'center', py: 4 }}>
            <CircularProgress size={28} />
          </Box>
        ) : filtered.length === 0 ? (
          <Typography variant="body2" color="text.secondary" sx={{ p: 2 }}>
            {q ? 'Не найдено' : 'Нет чатов'}
          </Typography>
        ) : (
          <List disablePadding>
            {filtered.map((chat) => {
              const selected = !!selectedUuid && chat.uuid === selectedUuid;
              return (
                <ListItemButton
                  key={chat.uuid || chat.id}
                  selected={selected}
                  onClick={() => onSelect(chat)}
                  sx={{ py: 1.25, px: 1.5 }}
                >
                  <Avatar sx={{ mr: 1.5, width: 38, height: 38 }}>
                    {getInitials(chat.participant_name)}
                  </Avatar>
                  <ListItemText
                    primary={
                      <Stack direction="row" justifyContent="space-between" alignItems="center">
                        <Typography variant="subtitle2" noWrap sx={{ maxWidth: 140 }}>
                          {chat.participant_name || 'Чат'}
                        </Typography>
                        {!!chat.unread_count && (
                          <Badge
                            badgeContent={chat.unread_count}
                            color="primary"
                            sx={{ '& .MuiBadge-badge': { fontSize: 10, minWidth: 16, height: 16 } }}
                          />
                        )}
                      </Stack>
                    }
                    secondary={
                      <Typography variant="caption" noWrap color="text.secondary">
                        {stripHtml(chat.last_message || '')}
                      </Typography>
                    }
                    primaryTypographyProps={{ component: 'div' }}
                    secondaryTypographyProps={{ component: 'div' }}
                  />
                </ListItemButton>
              );
            })}
          </List>
        )}
      </Box>
    </Box>
  );
}

// ----------------------------------------------------------------------

function ChatWindow({ chat, currentUserId, onBack }) {
  const [messages, setMessages] = useState([]);
  const [loading, setLoading] = useState(false);
  const [loadingMore, setLoadingMore] = useState(false);
  const [page, setPage] = useState(1);
  const [hasMore, setHasMore] = useState(false);
  const [text, setText] = useState('');
  const [sending, setSending] = useState(false);
  const listRef = useRef(null);
  const markedRef = useRef(new Set());
  const lastSentRef = useRef(null);
  const lastWheelUpRef = useRef(0);

  const chatUuid = chat?.uuid || null;

  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.id;
      const muuid = m.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.uuid != null && String(x.uuid) === String(muuid);
          return sameId || sameUuid;
        });
        if (isDuplicate) return prev;
        return [...prev, m];
      });
    },
  });

  useEffect(() => {
    if (!chat) return undefined;
    setLoading(true);
    setPage(1);
    setHasMore(false);
    markedRef.current = new Set();
    lastSentRef.current = null;

    const fetchMessages = async () => {
      try {
        const PAGE_SIZE = 30;
        const resp = chatUuid
          ? await getChatMessagesByUuid(chatUuid, { page: 1, page_size: PAGE_SIZE })
          : await getMessages(chat.id, { page: 1, page_size: PAGE_SIZE });
        const sorted = (resp.results || []).slice().sort((a, b) => {
          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.next || (resp.count ?? 0) > sorted.length);
        requestAnimationFrame(() => {
          const el = listRef.current;
          if (el) el.scrollTop = el.scrollHeight;
        });
      } finally {
        setLoading(false);
      }
    };
    fetchMessages();
    return undefined;
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [chat?.id, chatUuid]);

  useEffect(() => {
    if (!chatUuid || !listRef.current || messages.length === 0) return undefined;
    const container = listRef.current;
    const observer = new IntersectionObserver(
      (entries) => {
        const toMark = [];
        entries.forEach((e) => {
          if (!e.isIntersecting) return;
          const uuid = e.target.getAttribute('data-message-uuid');
          const isMine = e.target.getAttribute('data-is-mine') === 'true';
          if (uuid && !isMine && !markedRef.current.has(uuid)) {
            toMark.push(uuid);
            markedRef.current.add(uuid);
          }
        });
        if (toMark.length > 0) {
          markMessagesAsRead(chatUuid, toMark).catch(() => {});
        }
      },
      { root: container, threshold: 0.5 }
    );
    container.querySelectorAll('[data-message-uuid]').forEach((n) => observer.observe(n));
    return () => observer.disconnect();
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [chatUuid, messages]);

  const loadOlder = 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 PAGE_SIZE = 30;
      const resp = chatUuid
        ? await getChatMessagesByUuid(chatUuid, { page: nextPage, page_size: PAGE_SIZE })
        : await getMessages(chat.id, { page: nextPage, page_size: PAGE_SIZE });
      const batch = (resp.results || []).slice().sort((a, b) => {
        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 keys = new Set(prev.map((m) => m.uuid || m.id));
        const toAdd = batch.filter((m) => !keys.has(m.uuid || m.id));
        return [...toAdd, ...prev].sort((a, b) => {
          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;
        });
      });
      setPage(nextPage);
      setHasMore(!!resp.next);
    } finally {
      setTimeout(() => {
        const c = listRef.current;
        if (!c) return;
        c.scrollTop = prevScrollTop + (c.scrollHeight - prevScrollHeight);
      }, 0);
      setLoadingMore(false);
    }
  }, [chat, chatUuid, hasMore, loading, loadingMore, page]);

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

  if (!chat) {
    return (
      <Box
        sx={{
          flex: 1,
          display: 'flex',
          alignItems: 'center',
          justifyContent: 'center',
          color: 'text.secondary',
        }}
      >
        <Typography>Выберите чат из списка</Typography>
      </Box>
    );
  }

  const seen = new Set();
  const uniqueMessages = messages.filter((m) => {
    const k = String(m.uuid ?? m.id ?? '');
    if (!k || seen.has(k)) return false;
    seen.add(k);
    return true;
  });

  const grouped = [];
  let prevDay = '';
  uniqueMessages.forEach((m, idx) => {
    const day = dateKey(m.created_at);
    if (day && day !== prevDay) {
      grouped.push({ type: 'day', key: `day-${day}`, label: formatDayHeader(m.created_at) });
      prevDay = day;
    }
    const senderId = m.sender_id ?? (typeof m.sender === 'number' ? m.sender : m.sender?.id ?? null);
    const isMine = !!currentUserId && senderId === currentUserId;
    const isSystem =
      m.message_type === 'system' ||
      (typeof m.sender === 'string' && m.sender.toLowerCase() === 'system') ||
      (!senderId && m.sender_name === 'System');
    grouped.push({
      type: 'msg',
      key: m.uuid || m.id || `msg-${idx}`,
      msg: m,
      isMine,
      isSystem,
    });
  });

  return (
    <Box sx={{ flex: 1, display: 'flex', flexDirection: 'column', minHeight: 0, overflow: 'hidden' }}>
      {/* Header */}
      <Stack
        direction="row"
        alignItems="center"
        spacing={1.5}
        sx={{ px: 2, py: 1.5, borderBottom: '1px solid', borderColor: 'divider', flexShrink: 0 }}
      >
        {onBack && (
          <IconButton onClick={onBack} size="small" sx={{ display: { md: 'none' } }}>
            <Iconify icon="eva:arrow-back-outline" />
          </IconButton>
        )}
        <Avatar sx={{ width: 38, height: 38 }}>{getInitials(chat.participant_name)}</Avatar>
        <Box>
          <Typography variant="subtitle2">{chat.participant_name || 'Чат'}</Typography>
          {chat.other_is_online && (
            <Typography variant="caption" color="success.main">
              Онлайн
            </Typography>
          )}
        </Box>
      </Stack>

      {/* Messages */}
      <Box
        ref={listRef}
        sx={{ flex: 1, overflowY: 'auto', px: 2, py: 1, display: 'flex', flexDirection: 'column', gap: 0.75 }}
        onWheel={(e) => {
          if (e.deltaY < 0) lastWheelUpRef.current = Date.now();
        }}
        onScroll={(e) => {
          const el = e.currentTarget;
          if (el.scrollTop < 40 && Date.now() - lastWheelUpRef.current < 200) loadOlder();
        }}
      >
        {loadingMore && (
          <Typography variant="caption" color="text.secondary" textAlign="center">
            Загрузка…
          </Typography>
        )}
        {loading ? (
          <Box sx={{ display: 'flex', justifyContent: 'center', py: 4 }}>
            <CircularProgress size={28} />
          </Box>
        ) : (
          grouped.map((item) => {
            if (item.type === 'day') {
              return (
                <Box key={item.key} sx={{ alignSelf: 'center', my: 0.5 }}>
                  <Typography
                    variant="caption"
                    sx={{
                      px: 1.5,
                      py: 0.4,
                      borderRadius: 999,
                      bgcolor: 'background.neutral',
                      color: 'text.secondary',
                    }}
                  >
                    {item.label}
                  </Typography>
                </Box>
              );
            }
            const { msg, isMine, isSystem } = item;
            const msgUuid = msg.uuid ? String(msg.uuid) : null;
            return (
              <Box
                key={item.key}
                data-message-uuid={msgUuid || undefined}
                data-is-mine={String(isMine)}
                sx={{
                  alignSelf: isSystem ? 'center' : isMine ? 'flex-end' : 'flex-start',
                  maxWidth: isSystem ? '85%' : '70%',
                  px: 1.5,
                  py: 0.75,
                  borderRadius: 2,
                  bgcolor: isSystem
                    ? 'action.hover'
                    : isMine
                      ? 'primary.main'
                      : 'background.paper',
                  color: isSystem ? 'text.secondary' : isMine ? 'primary.contrastText' : 'text.primary',
                  border: '1px solid',
                  borderColor: isSystem ? 'divider' : isMine ? 'transparent' : 'divider',
                  boxShadow: isMine ? 0 : 1,
                }}
              >
                <Typography variant="body2" sx={{ whiteSpace: 'pre-wrap', wordBreak: 'break-word' }}>
                  {stripHtml(msg.content || '')}
                </Typography>
                <Typography
                  variant="caption"
                  sx={{ display: 'block', textAlign: 'right', opacity: 0.6, mt: 0.25 }}
                >
                  {formatTime(msg.created_at)}
                </Typography>
              </Box>
            );
          })
        )}
      </Box>

      {/* Input */}
      <Divider />
      <Stack direction="row" spacing={1} sx={{ p: 1.5, flexShrink: 0 }}>
        <TextField
          value={text}
          onChange={(e) => setText(e.target.value)}
          placeholder="Сообщение…"
          fullWidth
          multiline
          minRows={1}
          maxRows={4}
          size="small"
          onKeyDown={(e) => {
            if (e.key === 'Enter' && !e.shiftKey) {
              e.preventDefault();
              handleSend();
            }
          }}
        />
        <IconButton
          onClick={handleSend}
          disabled={!text.trim() || sending}
          color="primary"
          sx={{ alignSelf: 'flex-end' }}
        >
          {sending ? <CircularProgress size={20} /> : <Iconify icon="eva:paper-plane-outline" />}
        </IconButton>
      </Stack>
    </Box>
  );
}

// ----------------------------------------------------------------------

export function ChatPlatformView() {
  const { user } = useAuthContext();
  const [chats, setChats] = useState([]);
  const [loading, setLoading] = useState(true);
  const [selectedChat, setSelectedChat] = useState(null);
  const [newChatOpen, setNewChatOpen] = useState(false);
  const [error, setError] = useState(null);
  const mobileShowWindow = !!selectedChat;

  const load = useCallback(async () => {
    try {
      const res = await getConversations({ page_size: 50 });
      setChats(res.results);
    } catch (e) {
      setError(e?.response?.data?.detail || e?.message || 'Ошибка загрузки чатов');
    } finally {
      setLoading(false);
    }
  }, []);

  useEffect(() => {
    load();
  }, [load]);

  const handleChatCreated = (chat) => {
    setChats((prev) => {
      const exists = prev.some((c) => c.uuid === chat.uuid || c.id === chat.id);
      if (exists) return prev;
      return [chat, ...prev];
    });
    setSelectedChat(chat);
  };

  return (
    <DashboardContent sx={{ p: 0, display: 'flex', flexDirection: 'column', flex: 1 }} maxWidth={false} disablePadding>
      <Box sx={{ px: 3, py: 2, borderBottom: '1px solid', borderColor: 'divider' }}>
        <CustomBreadcrumbs
          heading="Чат"
          links={[{ name: 'Главная', href: paths.dashboard.root }, { name: 'Чат' }]}
        />
      </Box>

      {error && (
        <Alert severity="error" sx={{ mx: 3, mt: 2 }}>
          {error}
        </Alert>
      )}

      <Box sx={{ display: 'flex', flex: 1, minHeight: 0, height: 'calc(100vh - 180px)' }}>
        <Box sx={{ display: { xs: mobileShowWindow ? 'none' : 'flex', md: 'flex' }, height: '100%' }}>
          <ChatList
            chats={chats}
            selectedUuid={selectedChat?.uuid}
            onSelect={setSelectedChat}
            onNew={() => setNewChatOpen(true)}
            loading={loading}
          />
        </Box>

        <Box
          sx={{
            flex: 1,
            display: { xs: mobileShowWindow ? 'flex' : 'none', md: 'flex' },
            flexDirection: 'column',
            minHeight: 0,
          }}
        >
          <ChatWindow
            chat={selectedChat}
            currentUserId={user?.id || null}
            onBack={() => setSelectedChat(null)}
          />
        </Box>
      </Box>

      <NewChatDialog
        open={newChatOpen}
        onClose={() => setNewChatOpen(false)}
        onCreated={handleChatCreated}
      />
    </DashboardContent>
  );
}
