'use client';

/**
 * Chat Panel (v4.0)
 *
 * Chat interface met scrollable message list, auto-scroll, en scroll-lock detection.
 * V2 integratie: ActionChainCard, ClarificationCard, ProcessingIndicator
 *
 * Epic: E2 (Chat Panel & Messages), E3 (UI Components)
 * Story: E2.S3 (ChatPanel component - scrolling), E3 Integration
 */

import { useRef, useEffect, useState, useCallback } from 'react';
import { ArrowDown } from 'lucide-react';
import { AnimatePresence } from 'framer-motion';
import { ChatMessage } from './chat-message';
import { NudgeChatMessage } from './nudge-chat-message';
import { ChatInput, ChatInputHandle } from './chat-input';
import { ChatSuggestions } from './chat-suggestions';
import { ChatEmptyState } from './chat-empty-state';
import { ActionChainCard } from './action-chain-card';
import { ClarificationCard } from './clarification-card';
import { ProcessingIndicator } from './processing-indicator';
import { useCortexStore, type ChatMessage as ChatMessageType, type NoShowFlowState } from '@/stores/cortex-store';
import type { NudgeSuggestion } from '@/lib/cortex/types';
import { sendChatMessage } from '@/lib/cortex/chat-api';
import { parseActionFromResponse, shouldOpenArtifact, routeIntentToArtifact, getDefaultConfirmationMessage } from '@/lib/cortex/action-parser';
import { evaluateNudge } from '@/lib/cortex/nudge';
import { isFeatureEnabled } from '@/lib/config/feature-flags';
import { cn } from '@/lib/utils';

export function ChatPanel() {
  // Chat state
  const chatMessages = useCortexStore((s) => s.chatMessages);
  const addChatMessage = useCortexStore((s) => s.addChatMessage);
  const updateLastMessage = useCortexStore((s) => s.updateLastMessage);
  const setStreaming = useCortexStore((s) => s.setStreaming);
  const isStreaming = useCortexStore((s) => s.isStreaming);
  const setPendingAction = useCortexStore((s) => s.setPendingAction);
  const activePatient = useCortexStore((s) => s.activePatient);
  const shift = useCortexStore((s) => s.shift);

  // V2 Chain state
  const activeChain = useCortexStore((s) => s.activeChain);
  const updateActionStatus = useCortexStore((s) => s.updateActionStatus);
  const completeChain = useCortexStore((s) => s.completeChain);

  // V2 Clarification state
  const pendingClarification = useCortexStore((s) => s.pendingClarification);
  const setPendingClarification = useCortexStore((s) => s.setPendingClarification);
  const resolveClarification = useCortexStore((s) => s.resolveClarification);

  // Artifact state (E5.S2)
  const openArtifact = useCortexStore((s) => s.openArtifact);

  // Nudge state (chat-based nudges)
  const acceptSuggestion = useCortexStore((s) => s.acceptSuggestion);
  const dismissSuggestion = useCortexStore((s) => s.dismissSuggestion);

  // No-show flow state
  const setNoShowStep = useCortexStore((s) => s.setNoShowStep);
  const setNoShowContext = useCortexStore((s) => s.setNoShowContext);
  const setNoShowProcessing = useCortexStore((s) => s.setNoShowProcessing);
  const resetNoShowFlow = useCortexStore((s) => s.resetNoShowFlow);

  // Refs for scrolling
  const scrollContainerRef = useRef<HTMLDivElement>(null);
  const messagesEndRef = useRef<HTMLDivElement>(null);

  // Ref for chat input (for keyboard shortcuts)
  const chatInputRef = useRef<ChatInputHandle>(null);

  // Scroll-lock state
  const [isScrolledUp, setIsScrolledUp] = useState(false);
  const [showScrollButton, setShowScrollButton] = useState(false);

  // Intent Helper state: minimize suggestions after first message
  const [isSuggestionsMinimized, setIsSuggestionsMinimized] = useState(false);
  const hasAutoMinimizedRef = useRef(false);

  const hasMessages = chatMessages.length > 0;

  // Get active patient name for suggestion placeholders
  const activePatientName = activePatient
    ? `${activePatient.name_given?.[0] || ''} ${activePatient.name_family || ''}`.trim()
    : undefined;

  // Scroll to bottom function
  const scrollToBottom = useCallback((behavior: ScrollBehavior = 'smooth') => {
    messagesEndRef.current?.scrollIntoView({ behavior });
    setIsScrolledUp(false);
    setShowScrollButton(false);
  }, []);

  // Detect scroll position (scroll-lock detection)
  const handleScroll = useCallback(() => {
    if (!scrollContainerRef.current) return;

    const { scrollTop, scrollHeight, clientHeight } = scrollContainerRef.current;
    const isNearBottom = scrollHeight - scrollTop - clientHeight < 100; // 100px threshold

    setIsScrolledUp(!isNearBottom);

    // Show scroll button only if scrolled up AND there are messages
    setShowScrollButton(!isNearBottom && hasMessages);
  }, [hasMessages]);

  // Auto-scroll to latest message when new message arrives (unless user scrolled up)
  useEffect(() => {
    if (!isScrolledUp && hasMessages) {
      scrollToBottom('smooth');
    }
  }, [chatMessages.length, isScrolledUp, hasMessages, scrollToBottom]);

  // Initial scroll to bottom on mount
  useEffect(() => {
    scrollToBottom('auto');
  }, [scrollToBottom]);

  // Auto-minimize suggestions after first message is sent (only once)
  useEffect(() => {
    if (hasMessages && !hasAutoMinimizedRef.current) {
      hasAutoMinimizedRef.current = true;
      setIsSuggestionsMinimized(true);
    }
  }, [hasMessages]);

  // Cleanup no-show flow bij unmount
  useEffect(() => {
    return () => {
      const { noShowFlow } = useCortexStore.getState();
      if (noShowFlow.step !== 'idle' && noShowFlow.step !== 'done') {
        resetNoShowFlow();
      }
    };
  }, [resetNoShowFlow]);

  // Handle suggestion selection - fill input with selected text
  const handleSelectSuggestion = useCallback((text: string) => {
    chatInputRef.current?.setValue(text);
  }, []);

  // Global keyboard shortcuts
  useEffect(() => {
    const handleGlobalKeyDown = (e: KeyboardEvent) => {
      // ⌘K or Ctrl+K to focus chat input
      if ((e.metaKey || e.ctrlKey) && e.key === 'k') {
        e.preventDefault();
        chatInputRef.current?.focus();
      }
    };

    window.addEventListener('keydown', handleGlobalKeyDown);
    return () => window.removeEventListener('keydown', handleGlobalKeyDown);
  }, []);

  // No-show flow: stap 2→3 — annuleer afspraak + check concept brief
  const handleNoShowCancelStep = useCallback(async (_suggestion: NudgeSuggestion) => {
    const { isNoShowProcessing } = useCortexStore.getState();
    if (isNoShowProcessing) return;

    setNoShowProcessing(true);
    setNoShowStep('waiting_cancel');
    addChatMessage({ type: 'assistant', content: 'Bezig met annuleren...' });

    try {
      const patientId = activePatient?.id ?? 'demo-patient-001';

      // Stap 1: annuleer de afspraak
      const cancelRes = await fetch('/api/cortex/noshow/cancel', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ appointmentId: 'mock-appt-noshow-001', patientId }),
      });
      if (!cancelRes.ok) throw new Error('Annuleren mislukt');

      // Stap 2: check op concept brief
      const ctxRes = await fetch(`/api/cortex/noshow/context?patientId=${patientId}`);
      const ctx = await ctxRes.json();

      if (ctx.hasConceptBrief) {
        setNoShowContext({ documentId: ctx.document.id, originalContent: ctx.document.content });
        setNoShowStep('waiting_brief');

        // Construeer nudge 2 handmatig
        const briefNudge: NudgeSuggestion = {
          id: `nudge-noshow-brief-${Date.now()}`,
          trigger: { actionId: 'noshow-cancel-done', intent: 'cancel_appointment', entities: {} },
          suggestion: {
            intent: 'register_no_show',
            entities: {},
            message: 'Afspraak geannuleerd. Er staat nog een concept huisartsbrief klaar. Zal ik daar de No Show in verwerken?',
            rationale: 'noshow-brief-check',
          },
          status: 'pending',
          priority: 'high',
          expiresAt: new Date(Date.now() + 5 * 60 * 1000),
          createdAt: new Date(),
        };
        addChatMessage({ type: 'nudge', content: briefNudge.suggestion.message, nudge: briefNudge });
      } else {
        setNoShowStep('done');
        addChatMessage({
          type: 'assistant',
          content: 'Afspraak geannuleerd als No Show. Er zijn geen openstaande conceptbrieven gevonden.',
        });
      }
    } catch {
      setNoShowStep('idle');
      addChatMessage({ type: 'error', content: 'Er is iets misgegaan bij het annuleren. Probeer het opnieuw.' });
    } finally {
      setNoShowProcessing(false);
    }
  }, [activePatient, setNoShowStep, setNoShowContext, setNoShowProcessing, addChatMessage]);

  // No-show flow: stap 4→5 — rescript brief + open artifact
  const handleNoShowRescriptStep = useCallback(async () => {
    const { isNoShowProcessing, noShowFlow } = useCortexStore.getState();
    if (isNoShowProcessing) return;

    setNoShowProcessing(true);
    setNoShowStep('brief_open');
    addChatMessage({ type: 'assistant', content: 'Huisartsbrief aanpassen...' });

    try {
      const res = await fetch('/api/cortex/noshow/rescript', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          documentId: noShowFlow.documentId ?? 'mock-brief-noshow-001',
          originalContent: noShowFlow.originalContent ?? '',
          patientId: activePatient?.id ?? 'demo-patient-001',
        }),
      });

      const result = await res.json();

      openArtifact({
        type: 'register_no_show',
        title: 'Huisartsbrief n.a.v. intake',
        prefill: {
          documentId: result.documentId,
          content: result.rescriptedContent,
          title: 'Huisartsbrief n.a.v. intake',
          originalContent: result.originalContent,
          rescriptWarning: result.warning,
        },
      });

      addChatMessage({
        type: 'assistant',
        content: 'Huisartsbrief is aangepast. Kijk of je hiermee akkoord bent.',
      });
    } catch {
      setNoShowStep('waiting_brief');
      addChatMessage({ type: 'error', content: 'Herschrijven mislukt. Probeer het opnieuw.' });
    } finally {
      setNoShowProcessing(false);
    }
  }, [activePatient, setNoShowStep, setNoShowProcessing, addChatMessage, openArtifact]);

  // V2 Chain action handlers (E5.S2)
  const handleConfirmAction = useCallback((actionId: string) => {
    // Find the action in the active chain
    const action = activeChain?.actions.find((a) => a.id === actionId);
    if (!action || !activeChain) {
      console.error('[ChatPanel] Action not found:', actionId);
      return;
    }

    console.log('[ChatPanel] Confirming action:', actionId, action.intent);
    updateActionStatus(actionId, 'executing');

    // Route to artifact (uses existing artifact system)
    const artifact = routeIntentToArtifact(
      action.intent,
      action.entities,
      action.confidence
    );

    if (artifact) {
      console.log('[ChatPanel] Opening artifact:', artifact.type);
      openArtifact({
        type: artifact.type,
        prefill: artifact.prefill,
        title: artifact.title,
      });
    }

    // Mark as success (artifact is now open for user to complete)
    updateActionStatus(actionId, 'success');

    // E5.S2: Trigger nudge evaluation after successful action
    // Now adds nudges as chat messages instead of toast
    if (isFeatureEnabled('CORTEX_NUDGE')) {
      const suggestions = evaluateNudge({
        intent: action.intent,
        actionId,
        entities: action.entities,
        content: action.entities.content,
      });

      if (suggestions.length > 0) {
        console.log('[ChatPanel] Nudge suggestions (chat-based):', suggestions.length);
        suggestions.forEach((suggestion) => {
          // Add as chat message with nudge type
          addChatMessage({
            type: 'nudge',
            content: suggestion.suggestion.message,
            nudge: suggestion,
          });
        });
      }
    }
  }, [activeChain, updateActionStatus, openArtifact, addChatMessage]);

  const handleSkipAction = useCallback((actionId: string) => {
    console.log('[ChatPanel] Skipping action:', actionId);
    updateActionStatus(actionId, 'skipped');
  }, [updateActionStatus]);

  const handleRetryAction = useCallback((actionId: string) => {
    console.log('[ChatPanel] Retrying action:', actionId);
    updateActionStatus(actionId, 'pending');
    // Re-trigger confirmation flow
    setTimeout(() => {
      updateActionStatus(actionId, 'confirming');
    }, 100);
  }, [updateActionStatus]);

  const handleDismissChain = useCallback(() => {
    console.log('[ChatPanel] Dismissing chain');
    completeChain();
  }, [completeChain]);

  const handleSelectClarification = useCallback((option: string) => {
    console.log('[ChatPanel] Clarification selected:', option);
    resolveClarification(option);
    // TODO: E5 - Re-process with selected option
  }, [resolveClarification]);

  const handleDismissClarification = useCallback(() => {
    console.log('[ChatPanel] Clarification dismissed');
    setPendingClarification(null);
  }, [setPendingClarification]);

  // Nudge handlers (chat-based nudges)
  const handleAcceptNudge = useCallback(async (suggestionId: string, suggestion: ChatMessageType['nudge']) => {
    console.log('[ChatPanel] Nudge accepted:', suggestionId);
    acceptSuggestion(suggestionId);

    if (!suggestion) return;

    // No-show flow stap 2→3: declarabiliteitscheck geaccepteerd
    if (suggestion.trigger.intent === 'register_no_show') {
      await handleNoShowCancelStep(suggestion);
      return;
    }

    // No-show flow stap 4→5: brief-check geaccepteerd
    if (suggestion.suggestion.rationale === 'noshow-brief-check') {
      await handleNoShowRescriptStep();
      return;
    }

    // Generieke flow voor alle andere nudges
    const artifact = routeIntentToArtifact(
      suggestion.suggestion.intent,
      suggestion.suggestion.entities,
      0.9
    );

    if (artifact) {
      console.log('[ChatPanel] Opening artifact from nudge:', artifact.type);
      openArtifact({
        type: artifact.type,
        prefill: artifact.prefill,
        title: artifact.title,
      });
    }
  }, [acceptSuggestion, openArtifact, handleNoShowCancelStep, handleNoShowRescriptStep]);

  const handleDismissNudge = useCallback((suggestionId: string) => {
    console.log('[ChatPanel] Nudge dismissed:', suggestionId);
    dismissSuggestion(suggestionId);
  }, [dismissSuggestion]);

  // E5.S2: Sequential chain execution - auto-advance to next action
  useEffect(() => {
    if (!activeChain) return;

    const actions = activeChain.actions;
    const completedStatuses = ['success', 'skipped', 'failed'];

    // Count completed actions
    const completedCount = actions.filter((a) =>
      completedStatuses.includes(a.status)
    ).length;

    // Find next pending action
    const nextPending = actions.find((a) => a.status === 'pending');

    // If there's a completed action and a pending one, auto-advance
    if (completedCount > 0 && nextPending) {
      // Small delay for UI feedback before advancing
      const timer = setTimeout(() => {
        updateActionStatus(nextPending.id, 'confirming');
      }, 300);
      return () => clearTimeout(timer);
    }

    // If all actions are complete, finish the chain
    if (completedCount === actions.length && actions.length > 0) {
      const timer = setTimeout(() => {
        console.log('[ChatPanel] All actions complete, finishing chain');
        completeChain();
      }, 500);
      return () => clearTimeout(timer);
    }
  }, [activeChain, updateActionStatus, completeChain]);

  // Check if we should show multi-intent UI
  const showActionChain = activeChain && activeChain.actions.length > 1;

  return (
    <div className="h-full flex flex-col bg-white">
      {/* Chat messages area - scrollable */}
      <div
        ref={scrollContainerRef}
        onScroll={handleScroll}
        className="flex-1 overflow-y-auto p-6 relative"
      >
        {hasMessages ? (
          <div className="flex flex-col space-y-3">
            {chatMessages.map((message) => (
              message.type === 'nudge' && message.nudge ? (
                <NudgeChatMessage
                  key={message.id}
                  suggestion={message.nudge}
                  onAccept={(id) => handleAcceptNudge(id, message.nudge)}
                  onDismiss={handleDismissNudge}
                />
              ) : (
                <ChatMessage key={message.id} message={message} showTimestamp />
              )
            ))}

            {/* V2: Processing indicator while AI is thinking */}
            {isStreaming && (
              <div className="self-start">
                <ProcessingIndicator message="Even nadenken..." />
              </div>
            )}

            {/* V2: Multi-intent action chain (feature flagged) */}
            {isFeatureEnabled('CORTEX_MULTI_INTENT') && (
              <AnimatePresence mode="wait">
                {showActionChain && (
                  <ActionChainCard
                    key={activeChain.id}
                    chain={activeChain}
                    onConfirmAction={handleConfirmAction}
                    onSkipAction={handleSkipAction}
                    onRetryAction={handleRetryAction}
                    onDismissChain={handleDismissChain}
                  />
                )}
              </AnimatePresence>
            )}

            {/* V2: Clarification card for ambiguous input (feature flagged) */}
            {isFeatureEnabled('CORTEX_V2_ENABLED') && (
              <AnimatePresence mode="wait">
                {pendingClarification && (
                  <ClarificationCard
                    key="clarification"
                    question={pendingClarification.question}
                    options={pendingClarification.options}
                    originalInput={pendingClarification.originalInput}
                    onSelectOption={handleSelectClarification}
                    onDismiss={handleDismissClarification}
                  />
                )}
              </AnimatePresence>
            )}

            {/* Invisible element to scroll to */}
            <div ref={messagesEndRef} />
          </div>
        ) : (
          <ChatEmptyState
            onSelectAction={handleSelectSuggestion}
            activePatientName={activePatientName}
          />
        )}

        {/* Scroll to bottom button */}
        {showScrollButton && (
          <button
            onClick={() => scrollToBottom('smooth')}
            className={cn(
              'absolute bottom-4 right-4 z-10',
              'bg-white border border-slate-300 rounded-full p-2',
              'shadow-lg hover:shadow-xl',
              'transition-all duration-200',
              'hover:bg-slate-50 active:scale-95',
              'flex items-center gap-2 text-sm text-slate-700 font-medium px-3 py-2'
            )}
            aria-label="Scroll naar laatste bericht"
          >
            <ArrowDown className="w-4 h-4" />
            <span>Scroll naar beneden</span>
          </button>
        )}
      </div>

      {/* Suggestion strip above input */}
      <ChatSuggestions
        isMinimized={isSuggestionsMinimized}
        onToggleMinimize={() => setIsSuggestionsMinimized(!isSuggestionsMinimized)}
        onSelectSuggestion={handleSelectSuggestion}
        activePatientName={activePatientName}
      />

      {/* Chat input */}
      <ChatInput
        ref={chatInputRef}
        disabled={isStreaming}
        onSend={async (message) => {
          // E3.S1: Test streaming API with mock response
          setStreaming(true);

          // Add empty assistant message that will be filled by streaming
          addChatMessage({
            type: 'assistant',
            content: '',
          });

          let accumulatedContent = '';

          await sendChatMessage(
            message,
            chatMessages,
            {
              activePatient: activePatient ? {
                id: activePatient.id,
                first_name: activePatient.name_given?.[0] || '',
                last_name: activePatient.name_family || '',
              } : null,
              shift,
            },
            (chunk) => {
              // On each chunk, append to accumulated content
              accumulatedContent += chunk;

              // Filter out JSON blocks during streaming - users don't need to see the raw JSON
              // Show "Verwerken..." when JSON is being generated but no readable text yet
              const displayContent = accumulatedContent
                .replace(/```json[\s\S]*?```/g, '') // Remove complete JSON blocks
                .replace(/```json[\s\S]*$/g, '')    // Remove incomplete JSON block at end
                .trim();

              // If we have displayable content, show it; otherwise show processing message
              updateLastMessage(displayContent || 'Verwerken...');
            },
            () => {
              // On done - parse action from complete response
              setStreaming(false);

              // E3.S4: Parse action object from AI response
              const parsed = parseActionFromResponse(accumulatedContent);

              if (parsed.action) {
                console.log('[ChatPanel] Action detected:', parsed.action);

                // If textContent is empty but we have an action, generate a default confirmation message
                const displayContent = parsed.textContent.trim() || 
                  getDefaultConfirmationMessage(parsed.action.intent, parsed.action.entities);

                // Update last message with text content (or default) and action
                updateLastMessage(displayContent, parsed.action);

                // Store action in pendingAction for artifact opening (E3.S6)
                if (shouldOpenArtifact(parsed.action.confidence)) {
                  setPendingAction(parsed.action);
                  console.log('[ChatPanel] Pending action set (confidence:', parsed.action.confidence, ')');
                } else {
                  console.log('[ChatPanel] Action confidence too low:', parsed.action.confidence);
                }

                // No-show nudge trigger na register_no_show classificatie
                if (parsed.action.intent === 'register_no_show' && isFeatureEnabled('CORTEX_NUDGE')) {
                  const suggestions = evaluateNudge({
                    intent: 'register_no_show',
                    actionId: crypto.randomUUID(),
                    entities: {}, // register_no_show heeft geen entiteiten nodig
                    content: message,
                  });
                  suggestions.forEach((suggestion) => {
                    addChatMessage({ type: 'nudge', content: suggestion.suggestion.message, nudge: suggestion });
                  });
                }
              } else {
                console.log('[ChatPanel] No action detected in response');
              }
            },
            (error) => {
              // On error
              setStreaming(false);
              addChatMessage({
                type: 'error',
                content: `Er ging iets mis: ${error}`,
              });
            }
          );
        }}
      />
    </div>
  );
}
