import React, {useEffect, useRef, useState} from "react";
import {ActionIcon, Alert, Badge, Box, CloseButton, Group, Paper, ScrollArea, Text, Textarea, Tooltip, UnstyledButton} from "@mantine/core";
import {IconAlertCircle, IconCoins, IconRobot, IconSend, IconTrash} from "@tabler/icons-react";
import ChatMessage from "./ChatMessage";
import UsageDetailModal from "./UsageDetailModal";
import {ChatMessage as ChatMessageType, SessionMessage, SessionUsage, ToolResult} from "../types/chatTypes";
import {
    clearConversationHistory,
    createAssistantMessage,
    createLoadingMessage,
    createOrResumeSession,
    createUserMessage,
    getSessionUsage,
    sendMessage,
    syncEntitiesToSession
} from "../services/diagramAI";
import {getEntitiesForSync} from "../services/entityBridge";
import {getPath} from "../../util/functions/getPath";
import log from "loglevel";
import {v4 as uuidv4} from 'uuid';

const logger = log.getLogger('ChatPanel');

interface ChatPanelProps {
    width?: number;
    onClose?: () => void;
}

const WELCOME_MESSAGE = "Hello! I can help you create and modify 3D diagrams. Try saying things like:\n\n• \"Add a blue box labeled 'Server'\"\n• \"Create a red sphere called 'Database'\"\n• \"Connect Server to Database\"\n• \"What's in my diagram?\"\n\nHow can I help you today?";

/**
 * Convert session messages to ChatMessage format
 */
function sessionMessageToChatMessage(msg: SessionMessage): ChatMessageType | null {
    // Skip messages with non-string content (e.g., tool result objects)
    if (typeof msg.content !== 'string') {
        return null;
    }
    return {
        id: uuidv4(),
        role: msg.role,
        content: msg.content,
        timestamp: new Date(msg.timestamp),
        toolResults: msg.toolResults
    };
}

export default function ChatPanel({width = 400, onClose}: ChatPanelProps) {
    const [messages, setMessages] = useState<ChatMessageType[]>([]);
    const [inputValue, setInputValue] = useState('');
    const [isLoading, setIsLoading] = useState(false);
    const [isInitializing, setIsInitializing] = useState(true);
    const [error, setError] = useState<string | null>(null);
    const [usage, setUsage] = useState<SessionUsage | null>(null);
    const [usageModalOpen, setUsageModalOpen] = useState(false);
    const scrollAreaRef = useRef<HTMLDivElement>(null);
    const textareaRef = useRef<HTMLTextAreaElement>(null);

    // Fetch usage stats
    const fetchUsage = async () => {
        const usageData = await getSessionUsage();
        if (usageData) {
            setUsage(usageData);
        }
    };

    // Clear conversation history
    const handleClearConversation = async () => {
        const cleared = await clearConversationHistory();
        if (cleared) {
            setMessages([createAssistantMessage(WELCOME_MESSAGE)]);
            logger.info('Conversation cleared');
        } else {
            setError('Failed to clear conversation');
        }
    };

    // Initialize or resume session on mount
    useEffect(() => {
        const initSession = async () => {
            const diagramId = getPath() || 'default';
            logger.info('Initializing session for diagram:', diagramId);

            try {
                // Create or resume session
                const {session, isNew} = await createOrResumeSession(diagramId);
                logger.info(`Session ${isNew ? 'created' : 'resumed'}:`, session.id);

                // Fetch existing usage stats for this session
                await fetchUsage();

                // Sync current entities to server
                const entities = await getEntitiesForSync();
                if (entities.length > 0) {
                    await syncEntitiesToSession(entities);
                    logger.info('Synced', entities.length, 'entities to session');
                }

                // Restore conversation history or show welcome message
                if (!isNew && session.conversationHistory && session.conversationHistory.length > 0) {
                    const restoredMessages = session.conversationHistory
                        .map(sessionMessageToChatMessage)
                        .filter((msg): msg is ChatMessageType => msg !== null);
                    if (restoredMessages.length > 0) {
                        setMessages(restoredMessages);
                        logger.info('Restored', restoredMessages.length, 'messages from session');
                    } else {
                        setMessages([createAssistantMessage(WELCOME_MESSAGE)]);
                    }
                } else {
                    setMessages([createAssistantMessage(WELCOME_MESSAGE)]);
                }
            } catch (err) {
                logger.error('Failed to initialize session:', err);
                // Fall back to welcome message
                setMessages([createAssistantMessage(WELCOME_MESSAGE)]);
            } finally {
                setIsInitializing(false);
            }
        };

        initSession();
    }, []);

    // Auto-scroll when messages change
    useEffect(() => {
        if (scrollAreaRef.current) {
            scrollAreaRef.current.scrollTo({
                top: scrollAreaRef.current.scrollHeight,
                behavior: 'smooth'
            });
        }
    }, [messages]);

    const handleSend = async () => {
        const trimmedInput = inputValue.trim();
        if (!trimmedInput || isLoading) return;

        setError(null);
        const userMessage = createUserMessage(trimmedInput);
        setMessages(prev => [...prev, userMessage]);
        setInputValue('');
        setIsLoading(true);

        const loadingMessage = createLoadingMessage();
        setMessages(prev => [...prev, loadingMessage]);

        try {
            // Sync current entities before sending message so Claude has latest state
            const entities = await getEntitiesForSync();
            if (entities.length > 0) {
                await syncEntitiesToSession(entities);
                logger.debug('Synced', entities.length, 'entities before message');
            }

            const allToolResults: ToolResult[] = [];

            const {response, toolResults} = await sendMessage(
                trimmedInput,
                messages,
                (result) => {
                    allToolResults.push(result);
                    logger.debug('Tool executed:', result);
                }
            );

            setMessages(prev => {
                const filtered = prev.filter(m => m.id !== loadingMessage.id);
                return [...filtered, createAssistantMessage(response, toolResults)];
            });

            // Fetch updated usage stats
            await fetchUsage();
        } catch (err) {
            logger.error('Chat error:', err);
            setMessages(prev => prev.filter(m => m.id !== loadingMessage.id));
            setError(err instanceof Error ? err.message : 'Failed to send message');
        } finally {
            setIsLoading(false);
            // Refocus the input after message completes
            textareaRef.current?.focus();
        }
    };

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

    return <>
        <Paper
            shadow="xl"
            style={{
                width,
                height: '100vh',
                display: 'flex',
                flexDirection: 'column',
                borderLeft: '1px solid var(--mantine-color-dark-4)',
                backgroundColor: 'var(--mantine-color-dark-7)',
            }}
        >
            {/* Header */}
            <Box
                style={{
                    padding: '1rem',
                    borderBottom: '1px solid var(--mantine-color-dark-4)',
                    flexShrink: 0,
                }}
            >
                <Group justify="space-between">
                    <Group gap="xs">
                        <IconRobot size={24}/>
                        <Text fw={600}>Diagram Assistant</Text>
                    </Group>
                    <Group gap="xs">
                        {usage && (
                            <Tooltip
                                label="Click for details"
                                position="bottom"
                            >
                                <UnstyledButton onClick={() => setUsageModalOpen(true)}>
                                    <Group gap={4} style={{ cursor: 'pointer' }}>
                                        <IconCoins size={16} style={{ opacity: 0.7 }} />
                                        <Text size="xs" c="dimmed">{usage.totalCostFormatted}</Text>
                                    </Group>
                                </UnstyledButton>
                            </Tooltip>
                        )}
                        {usage && usage.contextPercent !== undefined && (
                            <Tooltip
                                label={`${(usage.contextUsed || 0).toLocaleString()} / ${(usage.contextLimit || 0).toLocaleString()} tokens`}
                                position="bottom"
                            >
                                <Badge
                                    size="sm"
                                    variant="light"
                                    color={usage.contextPercent > 80 ? 'red' : usage.contextPercent > 50 ? 'yellow' : 'green'}
                                >
                                    {usage.contextPercent.toFixed(0)}%
                                </Badge>
                            </Tooltip>
                        )}
                        <Tooltip label="Clear conversation" position="bottom">
                            <ActionIcon
                                variant="subtle"
                                color="gray"
                                onClick={handleClearConversation}
                                disabled={isLoading}
                            >
                                <IconTrash size={18} />
                            </ActionIcon>
                        </Tooltip>
                        {onClose && <CloseButton onClick={onClose}/>}
                    </Group>
                </Group>
            </Box>

            {/* Messages */}
            <ScrollArea
                style={{flex: 1}}
                viewportRef={scrollAreaRef}
                p="md"
            >
                {messages.map((message) => (
                    <ChatMessage key={message.id} message={message}/>
                ))}
            </ScrollArea>

            {/* Error Alert */}
            {error && (
                <Alert
                    color="red"
                    icon={<IconAlertCircle size={16}/>}
                    withCloseButton
                    onClose={() => setError(null)}
                    style={{margin: '0 1rem'}}
                >
                    {error}
                </Alert>
            )}

            {/* Input */}
            <Box
                style={{
                    padding: '1rem',
                    borderTop: '1px solid var(--mantine-color-dark-4)',
                    flexShrink: 0,
                }}
            >
                <Group gap="xs" align="flex-end">
                    <Textarea
                        ref={textareaRef}
                        placeholder={isInitializing ? "Connecting..." : "Describe what you want to create..."}
                        value={inputValue}
                        onChange={(e) => setInputValue(e.currentTarget.value)}
                        onKeyDown={handleKeyDown}
                        autosize
                        minRows={1}
                        maxRows={4}
                        disabled={isLoading || isInitializing}
                        style={{flex: 1}}
                    />
                    <ActionIcon
                        size="lg"
                        variant="filled"
                        onClick={handleSend}
                        disabled={!inputValue.trim() || isLoading || isInitializing}
                        loading={isLoading || isInitializing}
                    >
                        <IconSend size={18}/>
                    </ActionIcon>
                </Group>
            </Box>

        </Paper>

        {/* Usage Detail Modal */}
        <UsageDetailModal
            opened={usageModalOpen}
            onClose={() => setUsageModalOpen(false)}
            usage={usage}
        />
    </>;
}
