/**
 * MessageItem Component
 *
 * Renders a single chat message with role-appropriate styling.
 * Displays a formatted timestamp and optional export record links.
 * When an export record is present, shows a clickable card to preview the document.
 *
 * Requirements: 5.4, 5.5
 *
 * @module components/ChatPanel/MessageItem
 */

import React, { memo, useCallback, useState } from 'react';
import { Typography, Card, message as antdMessage, Spin } from 'antd';
import { FileTextOutlined, DownloadOutlined, LoadingOutlined } from '@ant-design/icons';
import { formatDate } from '../../utils/formatDate';
import type { ChatMessage } from '../../types/chat';
import { useDocumentStore } from '../../stores/documentStore';
import { useChatStore } from '../../stores/chatStore';

const { Text } = Typography;

// ── Styles ──────────────────────────────────────────────────────────────────

const messageRowStyle = (role: ChatMessage['role']): React.CSSProperties => ({
  display: 'flex',
  flexDirection: 'column',
  alignItems: role === 'user' ? 'flex-end' : 'flex-start',
  gap: '4px',
  contentVisibility: 'auto',
  containIntrinsicSize: '0 96px',
});

const bubbleStyle = (role: ChatMessage['role']): React.CSSProperties => ({
  maxWidth: '80%',
  padding: '10px 14px',
  borderRadius: role === 'user' ? '16px 16px 4px 16px' : '16px 16px 16px 4px',
  backgroundColor: role === 'user' ? '#1677ff' : '#f0f0f0',
  color: role === 'user' ? '#ffffff' : 'rgba(0, 0, 0, 0.85)',
  wordBreak: 'break-word',
  whiteSpace: 'pre-wrap',
  lineHeight: '1.6',
  fontSize: '14px',
});

const metaRowStyle = (role: ChatMessage['role']): React.CSSProperties => ({
  display: 'flex',
  flexDirection: role === 'user' ? 'row-reverse' : 'row',
  alignItems: 'center',
  gap: '8px',
});

const timestampStyle: React.CSSProperties = {
  fontSize: '11px',
  color: 'rgba(0, 0, 0, 0.45)',
};

const exportCardStyle: React.CSSProperties = {
  maxWidth: '80%',
  marginTop: '8px',
  cursor: 'pointer',
  transition: 'all 0.2s',
  position: 'relative',
};

const exportCardBodyStyle: React.CSSProperties = {
  padding: '12px 16px',
};

const exportCardHeaderStyle: React.CSSProperties = {
  display: 'flex',
  alignItems: 'center',
  gap: '8px',
  marginBottom: '4px',
};

const exportCardIconStyle: React.CSSProperties = {
  fontSize: '16px',
  color: '#1677ff',
};

const exportCardTitleStyle: React.CSSProperties = {
  fontSize: '14px',
  fontWeight: 500,
  color: '#262626',
  flex: 1,
};

const exportCardActionsStyle: React.CSSProperties = {
  display: 'flex',
  alignItems: 'center',
  gap: '12px',
  marginTop: '8px',
  fontSize: '12px',
  color: '#8c8c8c',
};

const exportCardActionStyle: React.CSSProperties = {
  display: 'flex',
  alignItems: 'center',
  gap: '4px',
  cursor: 'pointer',
  transition: 'color 0.2s',
};

// ── Component ────────────────────────────────────────────────────────────────

/**
 * Props for the MessageItem component
 */
export interface MessageItemProps {
  /** The chat message to display */
  message: ChatMessage;
  /** Callback when export record card is clicked to preview document */
  onPreviewDocument?: (documentId: string, documentName?: string) => void;
  className?: string;
}

/**
 * MessageItem
 *
 * Renders a single chat message bubble with its timestamp.
 * If the message includes an export record, displays a clickable card
 * that allows the user to preview or download the generated document.
 *
 * The component is wrapped in `React.memo` to avoid unnecessary re-renders
 * when the parent (MessageList) re-renders due to new messages arriving.
 *
 * @example
 * ```tsx
 * <MessageItem
 *   message={msg}
 *   onPreviewDocument={(docId) => {  Handle preview  }}
 * />
 * ```
 */
const MessageItem: React.FC<MessageItemProps> = memo(
  ({ message, onPreviewDocument, className }) => {
    const { role, content, timestamp, exportRecord } = message;
    const [isCreatingDocument, setIsCreatingDocument] = useState(false);
    const createDocument = useDocumentStore((state) => state.createDocument);
    const currentSessionId = useChatStore((state) => state.currentSessionId);

    /**
     * Handle preview document click
     * 
     * 点击预览文档时的处理逻辑:
     * 1. 检查本地缓存是否已有该导出记录对应的 documentId
     * 2. 如果有缓存且文档仍然存在,直接使用
     * 3. 如果没有缓存或文档已被删除,调用 POST /api/v1/documents 创建新文档
     * 4. 创建文档时传递 sessionId,确保同一会话中的多个文档共用相同的 sessionId
     * 5. 缓存 documentId 并打开编辑器
     */
    const handlePreviewClick = useCallback(async () => {
      if (!exportRecord || !onPreviewDocument || isCreatingDocument) return;

      try {
        setIsCreatingDocument(true);
        
        // Step 1: Check localStorage cache
        const { default: apiClient, isApiError } = await import('../../services/api');
        const cacheKey = `doc_cache_${currentSessionId}_${exportRecord.recordId}`;
        const cachedDocId = localStorage.getItem(cacheKey);
        
        let documentId: string;
        
        if (cachedDocId) {
          // Step 2: Verify cached document still exists
          try {
            await apiClient.get(`/api/v1/documents/${cachedDocId}`);
            // Document exists, reuse it
            documentId = cachedDocId;
          } catch (error) {
            if (!isApiError(error) || error.status !== 404) {
              throw error;
            }

            // Document no longer exists, clear cache and create new
            localStorage.removeItem(cacheKey);
            
            // Create new document with sessionId
            // 重要: 传递 sessionId 确保文档关联到当前会话
            const response = await createDocument({
              userId: 'default-user', // TODO: Get from auth context
              fileUrl: exportRecord.downloadUrl,
              sessionId: currentSessionId || 'default-session',
            });
            
            documentId = response.documentId;
            localStorage.setItem(cacheKey, documentId);
          }
        } else {
          // Step 3: No cache, create new document with sessionId
          // 重要: 每次生成新文档都会调用此API,传递相同的sessionId
          // 这样在数据库中就会有多条记录,id不同但session_id相同
          const response = await createDocument({
            userId: 'default-user', // TODO: Get from auth context
            fileUrl: exportRecord.downloadUrl,
            sessionId: currentSessionId || 'default-session',
          });
          
          documentId = response.documentId;
          
          // Step 4: Cache the mapping
          localStorage.setItem(cacheKey, documentId);
        }
        
        // Step 5: Open the preview with the document ID
        onPreviewDocument(documentId, exportRecord.fileName);
        
      } catch (error) {
        antdMessage.error('打开文档失败: ' + (error instanceof Error ? error.message : '未知错误'));
      } finally {
        setIsCreatingDocument(false);
      }
    }, [exportRecord, onPreviewDocument, isCreatingDocument, createDocument, currentSessionId]);

    /**
     * Handle download document click
     */
    const handleDownloadClick = useCallback(
      async (e: React.MouseEvent) => {
        e.stopPropagation(); // Prevent card click
        if (!exportRecord?.downloadUrl) return;
        
        try {
          // Extract recordId from downloadUrl
          // URL format: http://xxx/api/v1/export/records/{recordId}/download?userId=xxx
          const urlMatch = exportRecord.downloadUrl.match(/\/export\/records\/([^/]+)\/download/);
          if (!urlMatch) {
            return;
          }
          
          const recordId = urlMatch[1];
          const urlParams = new URL(exportRecord.downloadUrl).searchParams;
          const userId = urlParams.get('userId') || 'default-user';
          
          // Use apiClient to download (no mixed content warning)
          const { default: apiClient } = await import('../../services/api');
          const response = await apiClient.get(
            `/api/v1/export/records/${recordId}/download`,
            {
              params: { userId },
              responseType: 'blob',
            }
          );
          
          // Get filename from export record or Content-Disposition header
          let fileName = exportRecord.fileName || 'document.doc';
          const contentDisposition = response.headers['content-disposition'];
          if (contentDisposition) {
            const match = contentDisposition.match(/filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/);
            if (match && match[1]) {
              fileName = match[1].replace(/['"]/g, '');
            }
          }
          
          // Create blob and download
          const blob = new Blob([response.data], { type: 'application/msword' });
          const blobUrl = URL.createObjectURL(blob);
          
          const link = document.createElement('a');
          link.href = blobUrl;
          link.download = fileName;
          link.style.display = 'none';
          
          document.body.appendChild(link);
          link.click();
          
          // Clean up
          setTimeout(() => {
            document.body.removeChild(link);
            URL.revokeObjectURL(blobUrl);
          }, 100);
        } catch (error) {
          antdMessage.error(
            `下载文档失败: ${error instanceof Error ? error.message : '未知错误'}`
          );
        }
      },
      [exportRecord]
    );

    return (
      <div
        style={messageRowStyle(role)}
        className={className}
        data-testid={`message-item-${message.id}`}
        data-role={role}
      >
        {/* Message bubble */}
        <div style={bubbleStyle(role)} data-testid="message-bubble">
          {content}
        </div>

        {/* Export record card (if present) */}
        {exportRecord && (
          <Card
            style={exportCardStyle}
            styles={{ body: exportCardBodyStyle }}
            hoverable
            onClick={handlePreviewClick}
            data-testid="export-record-card"
          >
            {isCreatingDocument && (
              <div
                style={{
                  position: 'absolute',
                  top: 0,
                  left: 0,
                  right: 0,
                  bottom: 0,
                  display: 'flex',
                  alignItems: 'center',
                  justifyContent: 'center',
                  backgroundColor: 'rgba(255, 255, 255, 0.8)',
                  zIndex: 1,
                }}
              >
                <Spin indicator={<LoadingOutlined style={{ fontSize: 24 }} spin />} />
              </div>
            )}
            <div style={exportCardHeaderStyle}>
              <FileTextOutlined style={exportCardIconStyle} />
              <div style={exportCardTitleStyle}>{exportRecord.fileName}</div>
            </div>
            <div style={exportCardActionsStyle}>
              <div
                style={exportCardActionStyle}
                onClick={handleDownloadClick}
                onMouseEnter={(e) => {
                  (e.currentTarget as HTMLElement).style.color = '#1677ff';
                }}
                onMouseLeave={(e) => {
                  (e.currentTarget as HTMLElement).style.color = '#8c8c8c';
                }}
                data-testid="export-download-action"
              >
                <DownloadOutlined />
                <span>下载</span>
              </div>
              <div>
                <span>点击预览和编辑</span>
              </div>
            </div>
          </Card>
        )}

        {/* Meta row: timestamp */}
        <div style={metaRowStyle(role)} data-testid="message-meta">
          <Text style={timestampStyle} data-testid="message-timestamp">
            {formatDate(timestamp)}
          </Text>
        </div>
      </div>
    );
  }
);

MessageItem.displayName = 'MessageItem';

export default MessageItem;
