import { useEffect, useRef, useState } from "react";
import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@/components/ui/dialog";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Send, X } from "lucide-react";
import socketService from "@/utils/socketService";
import { API_ROOT, BUCKET_ROOT } from "@/utils/apis";

interface Message {
    _id: string;
    orderId: string;
    senderId: string;
    receiver_id: string;
    message: string;
    senderType: "restaurant" | "driver";
    createdAt: string;
}

interface ChatModalProps {
    isOpen: boolean;
    onClose: () => void;
    order: any;
    restaurantId: string;
    userId: string;
}

const ChatModal = ({ isOpen, onClose, order, restaurantId, userId }: ChatModalProps) => {
    const [messages, setMessages] = useState<Message[]>([]);
    const [newMessage, setNewMessage] = useState("");
    const [isInitialLoading, setIsInitialLoading] = useState(false);
    const [connectionId, setConnectionId] = useState<string | null>(null);
    const [loadingError, setLoadingError] = useState<string | null>(null);
    const messagesEndRef = useRef<HTMLDivElement>(null);
    const connectionTimeoutRef = useRef<NodeJS.Timeout | null>(null);

    const driverId = order?.driver_id?._id;
    const orderId = order?._id;

    const scrollToBottom = () => {
        messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
    };

    useEffect(() => {
        scrollToBottom();
    }, [messages]);

    // ✅ Main effect for socket connection and chat setup
    useEffect(() => {
        if (!isOpen || !driverId || !orderId) return;

        console.log("🚀 ChatModal opened with:", { orderId, driverId, restaurantId, userId });

        setIsInitialLoading(true);
        setLoadingError(null);
        setConnectionId(null);
        setMessages([]); // Clear messages when opening

        // Ensure socket is connected
        const SOCKET_URL = API_ROOT || ''
        const token = order?.userInfo?.access_token || "";

        if (!socketService.isConnected()) {
            console.log("📡 Connecting socket...");
            socketService.connect(SOCKET_URL, restaurantId, token);
        }

        // Set connection timeout
        connectionTimeoutRef.current = setTimeout(() => {
            if (!connectionId) {
                console.error("⏱️ Connection timeout");
                setLoadingError("Connection timeout. Please try again.");
                setIsInitialLoading(false);
            }
        }, 10000);

        // ✅ STEP 1: Listen for the create-connection response
        const unsubscribeConnection = socketService.onConnectionCreated((res: any) => {
            console.log("✅ create-connection response received:", res);

            // Clear timeout on success
            if (connectionTimeoutRef.current) {
                clearTimeout(connectionTimeoutRef.current);
            }

            // Extract connection_id from response
            const connId = res?.response || res?.connection_id;

            if (connId) {
                console.log("✅ connection_id extracted:", connId);
                setConnectionId(connId);

                // ✅ STEP 2: Fetch all messages using the connection_id
                socketService.getAllMessages(orderId, connId, (fetchedMessages) => {
                    console.log("📨 Messages fetched:", fetchedMessages);

                    // ✅ Map messages with correct sender identification
                    const normalizedMessages: Message[] = fetchedMessages.map((msg: any) => {
                        const msgSenderId = msg.senderId || msg.sender_id || msg.sent_id || msg.sent_by;
                        const isFromCurrentUser = msgSenderId === userId;

                        return {
                            _id: msg._id || `msg-${Date.now()}-${Math.random()}`,
                            orderId: msg.orderId || msg.order_id || orderId,
                            senderId: msgSenderId,
                            receiver_id: msg.receiver_id || msg.receiverId,
                            message: msg.message,
                            // ✅ Determine if message is from restaurant (current user) or driver
                            senderType: (isFromCurrentUser ? "restaurant" : "driver") as "restaurant" | "driver",
                            createdAt: msg.createdAt || msg.created_at || new Date().toISOString(),
                        };
                    });

                    setMessages(normalizedMessages);
                    setIsInitialLoading(false);
                });
            } else {
                console.error("❌ No connection_id in response:", res);
                setLoadingError("Failed to establish connection");
                setIsInitialLoading(false);
            }
        });

        // ✅ STEP 3: Emit the create-connection request
        console.log("🔗 Emitting createConnection...");
        socketService.createConnection(orderId, restaurantId, driverId);

        // Cleanup function
        return () => {
            console.log("🧹 Cleaning up ChatModal connection");
            if (connectionTimeoutRef.current) {
                clearTimeout(connectionTimeoutRef.current);
            }
            unsubscribeConnection();
        };
    }, [isOpen, driverId, orderId, restaurantId, userId]);

    // ✅ Listen for incoming messages - separate from connection setup
    // This will keep listening even if modal stays open
    useEffect(() => {
        if (!isOpen || !orderId || !userId) return;

        console.log("📡 Setting up message listener for orderId:", orderId, "userId:", userId);

        const unsubscribeMessages = socketService.onMessage((data: any) => {
            console.log("📩 New message received in ChatModal:", {
                data,
                currentOrderId: orderId,
                currentUserId: userId
            });

            // Check if message is for this order
            const messageOrderId = data.orderId || data.order_id;
            if (messageOrderId && messageOrderId !== orderId) {
                console.log("⏭️ Message is for different order:", messageOrderId, "vs", orderId);
                return;
            }

            // ✅ Extract sender ID from various possible fields
            const messageSenderId = data.senderId || data.sender_id || data.sent_id || data.sent_by;

            console.log("🔍 Sender comparison:", {
                messageSenderId,
                userId,
                isMatch: messageSenderId === userId,
                types: {
                    messageSenderIdType: typeof messageSenderId,
                    userIdType: typeof userId
                }
            });

            // ✅ IMPORTANT: Only add message if it's NOT from the current user
            // This prevents showing your own sent messages twice
            if (messageSenderId === userId) {
                console.log("⏭️ Skipping own message from socket event");
                return;
            }

            const newMsg: Message = {
                _id: data._id || `temp-${Date.now()}`,
                orderId: messageOrderId || orderId,
                senderId: messageSenderId,
                receiver_id: data.receiver_id || data.receiverId,
                message: data.message,
                senderType: "driver", // Since we filtered out restaurant messages above
                createdAt: data.createdAt || data.created_at || new Date().toISOString(),
            };

            console.log("✅ Processing new message:", newMsg);

            // ✅ Check if message already exists (prevent duplicates)
            setMessages((prev) => {
                const exists = prev.some(msg => {
                    const match = msg._id === newMsg._id ||
                        (msg.message === newMsg.message &&
                            Math.abs(new Date(msg.createdAt).getTime() - new Date(newMsg.createdAt).getTime()) < 1000);
                    return match;
                });

                if (exists) {
                    console.log("⏭️ Message already exists, skipping");
                    return prev;
                }
                console.log("✅ Adding new message to chat, total messages:", prev.length + 1);
                return [...prev, newMsg];
            });

            // Use setTimeout to ensure state is updated before scrolling
            setTimeout(() => scrollToBottom(), 100);
        });

        return () => {
            console.log("🧹 Removing message listener for orderId:", orderId);
            unsubscribeMessages();
        };
    }, [isOpen, orderId, userId]);

    const handleSendMessage = () => {
        if (!newMessage.trim() || !driverId || !orderId) return;

        if (!connectionId) {
            setLoadingError("Connection not established. Please try reopening the chat.");
            return;
        }

        const tempId = `temp-${Date.now()}-${Math.random()}`;
        const optimisticMessage: Message = {
            _id: tempId,
            orderId,
            senderId: userId,
            receiver_id: driverId,
            message: newMessage.trim(),
            senderType: "restaurant",
            createdAt: new Date().toISOString(),
        };

        // ✅ Add optimistically to local state
        setMessages((prev) => [...prev, optimisticMessage]);

        // ✅ Send to server
        socketService.sendMessage({
            connection_id: connectionId,
            order_id: orderId,
            receiver_id: driverId,
            message: newMessage.trim(),
            receiver_type: "driver",
        });

        setNewMessage("");
        setTimeout(() => scrollToBottom(), 100);
    };

    const handleKeyPress = (e: React.KeyboardEvent) => {
        if (e.key === "Enter" && !e.shiftKey) {
            e.preventDefault();
            handleSendMessage();
        }
    };

    const handleClose = () => {
        if (connectionId) {
            socketService.closeConnection(orderId);
        }
        setMessages([]);
        setConnectionId(null);
        onClose();
    };

    if (!driverId) {
        return (
            <Dialog open={isOpen} onOpenChange={handleClose}>
                <DialogContent className="max-w-md">
                    <DialogHeader>
                        <DialogTitle>Chat with Driver</DialogTitle>
                    </DialogHeader>
                    <div className="p-4 text-center text-gray-500">No driver assigned yet.</div>
                </DialogContent>
            </Dialog>
        );
    }

    return (
        <Dialog open={isOpen} onOpenChange={handleClose}>
            <DialogContent className="max-w-md h-[600px] flex flex-col p-0">
                <DialogHeader className="p-4 border-b flex justify-between items-center">
                    <div className="flex items-center gap-3">
                        <img
                            src={order.driver_id?.image ? `${BUCKET_ROOT}${order.driver_id.image}` : "/default-avatar.png"}
                            alt={order.driver_id?.name || "Driver"}
                            className="w-10 h-10 rounded-full object-cover"
                        />
                        <div>
                            <DialogTitle className="text-base">{order.driver_id?.name || "Driver"}</DialogTitle>
                            <p className="text-xs text-gray-500">Order #{order.order_id}</p>
                        </div>
                    </div>
                    <Button variant="ghost" size="icon" onClick={handleClose}>
                        <X className="h-4 w-4" />
                    </Button>
                </DialogHeader>

                <div className="flex-1 overflow-y-auto p-4 space-y-3 bg-gray-50">
                    {isInitialLoading ? (
                        <div className="flex flex-col justify-center items-center h-full text-gray-500">
                            <div className="animate-spin rounded-full h-8 w-8 border-b-2 border-[var(--primary-brand)] mb-2"></div>
                            <p>Loading messages...</p>
                        </div>
                    ) : loadingError ? (
                        <div className="flex flex-col justify-center items-center h-full text-center">
                            <p className="text-red-500 mb-2">{loadingError}</p>
                            <Button
                                onClick={() => {
                                    setLoadingError(null);
                                    setIsInitialLoading(true);
                                    setMessages([]);
                                    socketService.createConnection(orderId, restaurantId, driverId);
                                }}
                                className="bg-[var(--primary-brand)] hover:bg-[#5028d4]"
                            >
                                Retry
                            </Button>
                        </div>
                    ) : messages.length === 0 ? (
                        <div className="flex justify-center items-center h-full text-gray-500">
                            No messages yet. Start the conversation!
                        </div>
                    ) : (
                        messages.map((msg) => {
                            const isRestaurant = msg.senderType === "restaurant";
                            return (
                                <div key={msg._id} className={`flex ${isRestaurant ? "justify-end" : "justify-start"}`}>
                                    <div
                                        className={`max-w-[70%] rounded-lg px-4 py-2 ${isRestaurant ? "bg-[var(--primary-brand)] text-white" : "bg-white text-gray-800 border border-gray-200"
                                            }`}
                                    >
                                        <p className="text-sm break-words">{msg.message}</p>
                                        <p className={`text-[10px] mt-1 ${isRestaurant ? "text-orange-200" : "text-gray-400"}`}>
                                            {new Date(msg.createdAt).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" })}
                                        </p>
                                    </div>
                                </div>
                            );
                        })
                    )}
                    <div ref={messagesEndRef} />
                </div>

                <div className="p-4 border-t bg-white flex gap-2">
                    <Input
                        value={newMessage}
                        onChange={(e) => setNewMessage(e.target.value)}
                        onKeyPress={handleKeyPress}
                        placeholder="Type a message..."
                        className="flex-1"
                        disabled={isInitialLoading || !!loadingError}
                    />
                    <Button
                        onClick={handleSendMessage}
                        disabled={!newMessage.trim() || isInitialLoading || !!loadingError}
                        className="bg-[var(--primary-brand)] hover:bg-[var(--primary-brand)]"
                    >
                        <Send className="h-4 w-4 text-white" />
                    </Button>
                </div>
            </DialogContent>
        </Dialog>
    );
};

export default ChatModal;