import React, { useEffect, useState, useRef } from 'react';
import { Input, Button, Avatar, Typography, List, Popover, message as antdMessage } from 'antd';
import { SendOutlined, SmileOutlined } from '@ant-design/icons';
import { getChatsBetweenUsers, createChat } from '../api/chat';
import axios from 'axios';
import './chat.css';

const { Text } = Typography;
const { TextArea } = Input;

// 完整表情数组
const emojis = [
  "😀", "😃", "😄", "😁", "😆", "😅", "😂", "🤣", "😊", "😇",
  "🙂", "🙃", "😉", "😌", "😍", "🥰", "😘", "😗", "😙", "😚",
  "😋", "😛", "😝", "😜", "🤪", "🤨", "🧐", "🤓", "😎", "🤩",
  "🥳", "😏", "😒", "😞", "😔", "😟", "😕", "🙁", "☹️", "😣",
  "😖", "😫", "😩", "🥺", "😢", "😭", "😤", "😠", "😡", "🤬",
  "🤯", "😳", "🥵", "🥶", "😱", "😨", "😰", "😥", "😓", "🤗",
  "🤔", "🤭", "🤫", "🤥", "😶", "😐", "😑", "😬", "🙄", "😯",
  "😦", "😧", "😮", "😲", "🥱", "😴", "🤤", "😪", "😵", "🤐",
  "🥴", "🤢", "🤮", "🤧", "😷", "🤒", "🤕", "🤑", "🤠", "😈",
  "👿", "👹", "👺", "🤡", "💩", "👻", "💀", "☠️", "👽", "👾",
  "🤖", "🎃", "😺", "😸", "😹", "😻", "😼", "😽", "🙀", "😿",
  "😾", "👋", "🤚", "🖐", "✋", "🖖", "👌", "🤏", "✌️", "🤞",
  "🤟", "🤘", "🤙", "👈", "👉", "👆", "🖕", "👇", "☝️", "👍",
  "👎", "✊", "👊", "🤛", "🤜", "👏", "🙌", "👐", "🤲", "🤝",
  "🙏", "✍️", "💅", "🤳", "💪", "🦾", "🦵", "🦿", "🦶", "👂",
  "🦻", "👃", "🧠", "🦷", "🦴", "👀", "👁", "👅", "👄", "💋",
  "🩸", "💘", "💝", "💖", "💗", "💓", "💞", "💕", "💟", "❣️",
  "💔", "❤️", "🧡", "💛", "💚", "💙", "💜", "🤎", "🖤", "🤍",
  "💯", "💢", "💥", "💫", "💦", "💨", "🕳", "💣", "💬", "👁️‍🗨️",
  "🗨", "🗯", "💭", "💤", "👋", "🤚", "🖐", "✋", "🖖", "👌"
];

const ChatBox = ({ senderId, receiverId }) => {
  const [messages, setMessages] = useState([]);
  const [input, setInput] = useState('');
  const [showEmojis, setShowEmojis] = useState(false);
  const messagesEndRef = useRef(null);
  const inputRef = useRef(null);
  const [loading, setLoading] = useState(false);
  const [cursorPosition, setCursorPosition] = useState(0);
  const [users, setUsers] = useState({}); // {id: {username, avatar}}

  const formatTime = timeStr => new Date(timeStr).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });

  const fetchUserInfo = async (id) => {
    if (!id || users[id]) return;
    try {
      const res = await axios.get(`http://localhost:8080/user/getDecoration?userid=${id}`);
      const info = res.data.data;
      setUsers(u => ({ ...u, [id]: { username: info.username, avatar: info.image } }));
    } catch (e) {
      console.error('获取用户信息失败', e);
      setUsers(u => ({ ...u, [id]: { username: `用户${id}`, avatar: null } }));
    }
  };

  const fetchMessages = async () => {
    if (!senderId || !receiverId) return;
    try {
      await fetchUserInfo(senderId);
      await fetchUserInfo(receiverId);
      const data = await getChatsBetweenUsers(senderId, receiverId);
      setMessages(data.sort((a, b) => new Date(a.talkTime) - new Date(b.talkTime)));
    } catch {
      antdMessage.error('加载聊天记录失败');
    }
  };

  useEffect(fetchMessages, [senderId, receiverId]);

  useEffect(() => {
    messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
  }, [messages]);

  const handleSend = async () => {
    const trimmed = input.trim();
    if (!trimmed) return;
    setLoading(true);
    const newChat = { senderId, receiverId, content: trimmed, talkTime: new Date().toISOString() };
    try {
      await createChat(newChat);
      setInput('');
      fetchMessages();
    } catch {
      antdMessage.error('发送失败，请重试');
    }
    setLoading(false);
  };

  const handleKeyDown = e => {
    if (e.key === 'Enter' && !e.shiftKey) {
      e.preventDefault();
      handleSend();
    }
  };

  const handleEmojiInsert = emoji => {
    const start = input.slice(0, cursorPosition);
    const end = input.slice(cursorPosition);
    const newText = start + emoji + end;
    setInput(newText);
    setShowEmojis(false);
    setTimeout(() => {
      const pos = start.length + emoji.length;
      inputRef.current.focus();
      inputRef.current.setSelectionRange(pos, pos);
      setCursorPosition(pos);
    }, 0);
  };

  const handleInputSelection = () => inputRef.current && setCursorPosition(inputRef.current.selectionStart);

  const renderEmojiPicker = () => (
    <div className="emoji-picker">
      {emojis.map((e, i) => (
        <span key={i} className="emoji-item" onClick={() => handleEmojiInsert(e)}>
          {e}
        </span>
      ))}
    </div>
  );

  return (
    <div className="chatbox-container">
      <div className="chatbox-header">
        <Text strong style={{ fontSize: 20 }}>
          🟢 Chat with {users[receiverId]?.username || receiverId}
        </Text>
      </div>

      <div className="chatbox-content">
        {messages.length === 0 ? (
          <div className="no-messages">暂无聊天记录</div>
        ) : (
          <List
            dataSource={messages}
            renderItem={msg => {
              const isSender = msg.senderId === senderId;
              const otherId = isSender ? senderId : receiverId;
              const user = users[otherId] || {};
              const avatarContent = user.avatar ? (
                <Avatar src={user.avatar} className="avatar" />
              ) : (
                <Avatar className="avatar">{String(otherId).slice(-2)}</Avatar>
              );
              return (
                <List.Item key={msg.informationid} className={`chat-message ${isSender ? 'sender' : 'receiver'}`}>
                  {!isSender && avatarContent}
                  <div className="message-bubble-wrapper">
                    <div className="message-bubble">
                      <Text>{msg.content}</Text>
                      <div className="message-time">{formatTime(msg.talkTime)}</div>
                    </div>
                  </div>
                  {isSender && avatarContent}
                </List.Item>
              );
            }}
          />
        )}
        <div ref={messagesEndRef} />
      </div>

      <div className="chatbox-footer">
        <Popover
          content={renderEmojiPicker()}
          title="选择表情"
          trigger="click"
          open={showEmojis}
          onOpenChange={setShowEmojis}
          placement="topLeft"
          overlayClassName="emoji-popover"
          arrow={false}
        >
          <Button icon={<SmileOutlined />} type="text" className="emoji-btn" />
        </Popover>
        <TextArea
          ref={inputRef}
          value={input}
          onChange={e => { setInput(e.target.value); setCursorPosition(e.target.selectionStart); }}
          onClick={handleInputSelection}
          onSelect={handleInputSelection}
          onKeyUp={handleInputSelection}
          onKeyDown={handleKeyDown}
          placeholder="输入消息，Enter发送，Shift+Enter换行"
          autoSize={{ minRows: 2, maxRows: 6 }}
          disabled={loading}
          maxLength={500}
          showCount
          className="chat-input"
        />
        <Button type="primary" icon={<SendOutlined />} onClick={handleSend} loading={loading} disabled={!input.trim()} className="send-btn">
          发送
        </Button>
      </div>
    </div>
  );
};

export default ChatBox;