import React, { useCallback, useEffect, useRef, useState } from 'react';
import ReactMarkdown from 'react-markdown';
import remarkGfm from 'remark-gfm';
import { ChevronDown, ChevronUp } from 'lucide-react';
import {
  PanelPayload,
  PortfolioAction,
  PortfolioActionSeed,
  TerminalEntry,
} from '../../types/terminal';
import { CompanyPanel } from '../Panels/CompanyPanel';
import { PortfolioPanel } from '../Panels/PortfolioPanel';
import { NewsPanel } from '../Panels/NewsPanel';
import { AnalysisPanel } from '../Panels/AnalysisPanel';
import { ErrorPanel } from '../Panels/ErrorPanel';
import { FinancialsPanel } from '../Panels/FinancialsPanel';
import { CashFlowPanel } from '../Panels/CashFlowPanel';
import { DividendsPanel } from '../Panels/DividendsPanel';
import { EarningsPanel } from '../Panels/EarningsPanel';

interface TerminalOutputProps {
  history: TerminalEntry[];
  outputRef: React.RefObject<HTMLDivElement | null>;
  onRunCommand: (command: string) => void;
  onStartPortfolioAction: (
    action: PortfolioAction,
    seed?: PortfolioActionSeed,
  ) => void;
}

export const TerminalOutput: React.FC<TerminalOutputProps> = ({
  history,
  outputRef,
  onRunCommand,
  onStartPortfolioAction,
}) => {
  const contentRef = useRef<HTMLDivElement | null>(null);
  const shouldStickToBottomRef = useRef(true);
  const [collapsedThinkingEntries, setCollapsedThinkingEntries] = useState<Set<string>>(new Set());

  const toggleThinkingEntry = useCallback((entryId: string) => {
    setCollapsedThinkingEntries((prev) => {
      const next = new Set(prev);
      if (next.has(entryId)) {
        next.delete(entryId);
      } else {
        next.add(entryId);
      }
      return next;
    });
  }, []);

  const isNearBottom = useCallback((element: HTMLDivElement) => {
    const distanceFromBottom =
      element.scrollHeight - element.scrollTop - element.clientHeight;
    return distanceFromBottom < 48;
  }, []);

  const scrollToBottom = useCallback(() => {
    const element = outputRef.current;
    if (!element || !shouldStickToBottomRef.current) {
      return;
    }

    requestAnimationFrame(() => {
      requestAnimationFrame(() => {
        element.scrollTop = element.scrollHeight;
      });
    });
  }, [outputRef]);

  useEffect(() => {
    const element = outputRef.current;
    if (!element) {
      return;
    }

    const handleScroll = () => {
      shouldStickToBottomRef.current = isNearBottom(element);
    };

    handleScroll();
    element.addEventListener('scroll', handleScroll);

    return () => {
      element.removeEventListener('scroll', handleScroll);
    };
  }, [isNearBottom, outputRef]);

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

  useEffect(() => {
    const element = outputRef.current;
    const content = contentRef.current;
    if (!element || !content || typeof ResizeObserver === 'undefined') {
      return;
    }

    const observer = new ResizeObserver(() => {
      if (shouldStickToBottomRef.current) {
        element.scrollTop = element.scrollHeight;
      }
    });

    observer.observe(content);
    return () => observer.disconnect();
  }, [outputRef]);

  const renderPlainText = (content: string) => {
    const lines = content.split('\n');
    return (
      <div className="whitespace-pre-wrap break-words font-mono text-[14px] leading-relaxed">
        {lines.map((line, i) => (
          <div key={i} className="break-words">{line || '\u00A0'}</div>
        ))}
      </div>
    );
  };

  const renderMarkdown = (content: string) => (
    <div className="break-words text-[14px] leading-7 text-term-text [&_strong]:font-semibold [&_strong]:text-term-text">
      <ReactMarkdown
        remarkPlugins={[remarkGfm]}
        components={{
          h1: ({ children }) => (
            <h1 className="mb-3 mt-1 text-[1.35rem] font-semibold tracking-[-0.02em] text-term-text">
              {children}
            </h1>
          ),
          h2: ({ children }) => (
            <h2 className="mb-2 mt-4 text-[1.15rem] font-semibold text-term-text">
              {children}
            </h2>
          ),
          h3: ({ children }) => (
            <h3 className="mb-2 mt-3 text-[1rem] font-semibold text-term-text">
              {children}
            </h3>
          ),
          p: ({ children }) => <p className="my-2">{children}</p>,
          ul: ({ children }) => <ul className="my-3 list-disc space-y-1 pl-5">{children}</ul>,
          ol: ({ children }) => <ol className="my-3 list-decimal space-y-1 pl-5">{children}</ol>,
          li: ({ children }) => <li className="pl-1">{children}</li>,
          blockquote: ({ children }) => (
            <blockquote className="my-3 border-l-2 border-info/50 pl-4 italic text-term-text-muted">
              {children}
            </blockquote>
          ),
          a: ({ href, children }) => (
            <a
              href={href}
              target="_blank"
              rel="noreferrer"
              className="break-all text-info underline decoration-info/50 underline-offset-4 transition-colors hover:text-term-text"
            >
              {children}
            </a>
          ),
          hr: () => <hr className="my-4 border-term-border" />,
          table: ({ children }) => (
            <div className="my-4 overflow-x-auto">
              <table className="min-w-full border-collapse text-left text-[13px]">
                {children}
              </table>
            </div>
          ),
          thead: ({ children }) => <thead className="border-b border-term-border text-term-text-muted">{children}</thead>,
          tbody: ({ children }) => <tbody>{children}</tbody>,
          tr: ({ children }) => <tr className="border-b border-term-border-subtle last:border-b-0">{children}</tr>,
          th: ({ children }) => <th className="px-3 py-2 font-semibold">{children}</th>,
          td: ({ children }) => <td className="px-3 py-2 align-top text-term-text">{children}</td>,
          code: ({ className, children }) => {
            const value = String(children).replace(/\n$/, '');
            const isBlock = Boolean(className?.includes('language-')) || value.includes('\n');

            return isBlock ? (
              <code className="block overflow-x-auto rounded-xl border border-term-border bg-term-bg px-4 py-3 font-mono text-[13px] leading-6 text-term-text break-all">
                {value}
              </code>
            ) : (
              <code className="rounded bg-term-surface px-1.5 py-0.5 font-mono text-[0.92em] text-warning break-all">
                {value}
              </code>
            );
          },
          pre: ({ children }) => <pre className="my-4 overflow-x-auto">{children}</pre>,
        }}
      >
        {content}
      </ReactMarkdown>
    </div>
  );

  const renderContent = (entry: TerminalEntry) => {
    if (typeof entry.content !== 'string') {
      return null;
    }

    if (entry.renderMode === 'markdown') {
      return renderMarkdown(entry.content);
    }

    return renderPlainText(entry.content);
  };

  const getEntryColor = (type: TerminalEntry['type']) => {
    switch (type) {
      case 'command':
        return 'text-term-text';
      case 'response':
        return 'text-info';
      case 'system':
        return 'text-term-text-tertiary italic';
      case 'thinking':
        return 'text-term-text-muted';
      case 'error':
        return 'text-negative';
      case 'panel':
        return '';
      default:
        return 'text-term-text';
    }
  };

  const getEntrySpacing = (type: TerminalEntry['type']) => {
    // Context-aware spacing based on entry type
    switch (type) {
      case 'panel':
        return 'mb-6'; // More space for panels
      case 'command':
        return 'mb-2'; // Less space after commands
      case 'error':
        return 'mb-4'; // Moderate space for errors
      case 'thinking':
        return 'mb-3';
      default:
        return 'mb-3'; // Default space
    }
  };

  const shouldShowTimestamp = (entry: TerminalEntry) => {
    // Only show timestamps for commands and errors, not for panels
    return entry.type === 'command' || entry.type === 'error';
  };

  const getAnimationDelay = (type: TerminalEntry['type']) => {
    // Faster animation for panels, slower for text
    switch (type) {
      case 'panel':
        return 'duration-150';
      case 'command':
        return 'duration-200';
      default:
        return 'duration-200';
    }
  };

  const renderPanel = (entry: TerminalEntry) => {
    if (entry.type !== 'panel' || typeof entry.content === 'string') {
      return null;
    }

    const panelData = entry.content as PanelPayload;

    switch (panelData.type) {
      case 'company':
        return <CompanyPanel company={panelData.data} />;
      case 'error':
        return <ErrorPanel error={panelData.data} />;
      case 'portfolio':
        return (
          <PortfolioPanel
            portfolio={panelData.data}
            onRunCommand={onRunCommand}
            onStartAction={onStartPortfolioAction}
            onSelectHolding={(symbol) => onRunCommand(`/search ${symbol}`)}
          />
        );
      case 'news':
        return (
          <NewsPanel
            news={panelData.data}
            ticker={panelData.ticker}
            onRunCommand={onRunCommand}
          />
        );
      case 'analysis':
        return <AnalysisPanel analysis={panelData.data} />;
      case 'financials':
        return <FinancialsPanel data={panelData.data} />;
      case 'cashFlow':
        return <CashFlowPanel data={panelData.data} />;
      case 'dividends':
        return <DividendsPanel data={panelData.data} />;
      case 'earnings':
        return <EarningsPanel data={panelData.data} onRunCommand={onRunCommand} />;
      default:
        return null;
    }
  };

  const getPreviewText = (content: string, maxLength: number = 50): string => {
    const trimmed = content.trim();
    if (trimmed.length <= maxLength) return trimmed;
    return trimmed.slice(0, maxLength).trim() + '...';
  };

  const renderThinkingContent = (entry: TerminalEntry) => {
    if (typeof entry.content !== 'string') return null;

    // Always render thinking as markdown, regardless of entry.renderMode
    return (
      <div className="break-words text-[13px] leading-6 text-term-text-muted [&_strong]:font-semibold [&_strong]:text-term-text-muted [&_em]:italic">
        <ReactMarkdown
          remarkPlugins={[remarkGfm]}
          components={{
            // Same components as renderMarkdown, but slightly smaller/muted for thinking
            p: ({ children }) => <p className="my-1.5">{children}</p>,
            ul: ({ children }) => <ul className="my-2 list-disc space-y-0.5 pl-4">{children}</ul>,
            ol: ({ children }) => <ol className="my-2 list-decimal space-y-0.5 pl-4">{children}</ol>,
            li: ({ children }) => <li className="pl-0.5">{children}</li>,
            code: ({ className, children }) => {
              const value = String(children).replace(/\n$/, '');
              const isBlock = Boolean(className?.includes('language-')) || value.includes('\n');
              return isBlock ? (
                <code className="block overflow-x-auto rounded-lg border border-term-border bg-term-bg px-3 py-2 font-mono text-[12px] leading-5 text-term-text-muted break-all">
                  {value}
                </code>
              ) : (
                <code className="rounded bg-term-surface px-1 py-0.5 font-mono text-[0.9em] text-warning break-all">
                  {value}
                </code>
              );
            },
            pre: ({ children }) => <pre className="my-3 overflow-x-auto">{children}</pre>,
            blockquote: ({ children }) => (
              <blockquote className="my-2 border-l-2 border-term-border pl-3 text-term-text-muted">
                {children}
              </blockquote>
            ),
            // Use same styling as renderMarkdown for other elements
            h1: ({ children }) => <h1 className="mb-2 mt-1 text-[1.2rem] font-semibold text-term-text-muted">{children}</h1>,
            h2: ({ children }) => <h2 className="mb-2 mt-3 text-[1.1rem] font-semibold text-term-text-muted">{children}</h2>,
            h3: ({ children }) => <h3 className="mb-2 mt-2 text-[1rem] font-semibold text-term-text-muted">{children}</h3>,
            a: ({ href, children }) => (
              <a
                href={href}
                target="_blank"
                rel="noreferrer"
                className="break-all text-info/80 underline decoration-info/40 underline-offset-4 transition-colors hover:text-info"
              >
                {children}
              </a>
            ),
            hr: () => <hr className="my-3 border-term-border" />,
            table: ({ children }) => (
              <div className="my-3 overflow-x-auto">
                <table className="min-w-full border-collapse text-left text-[12px]">
                  {children}
                </table>
              </div>
            ),
            thead: ({ children }) => <thead className="border-b border-term-border text-term-text-muted">{children}</thead>,
            tbody: ({ children }) => <tbody>{children}</tbody>,
            tr: ({ children }) => <tr className="border-b border-term-border-subtle last:border-b-0">{children}</tr>,
            th: ({ children }) => <th className="px-2 py-1.5 font-semibold">{children}</th>,
            td: ({ children }) => <td className="px-2 py-1.5 align-top text-term-text-muted">{children}</td>,
          }}
        >
          {entry.content}
        </ReactMarkdown>
      </div>
    );
  };

  return (
    <div
      ref={outputRef}
      className="min-h-0 min-w-0 flex-1 overflow-x-hidden overflow-y-auto px-6 py-4"
      style={{
        scrollbarWidth: 'thin',
        scrollbarColor: 'var(--term-border) var(--term-bg-elevated)'
      }}
    >
      <div ref={contentRef} className="min-w-0 break-words">
        {history.map((entry) => (
          <div
            key={entry.id}
            className={`animate-in fade-in slide-in-from-bottom-2 ${getAnimationDelay(entry.type)} ${getEntrySpacing(entry.type)}`}
          >
            {/* Entry Header */}
            {entry.type === 'command' && (
              <div className="flex items-start gap-2">
                <span className="text-info font-mono select-none">{'>'}</span>
                <div className={getEntryColor(entry.type)}>
                  {renderContent(entry)}
                </div>
              </div>
            )}

            {entry.type === 'thinking' && (
              <div className="rounded-lg border border-term-border bg-term-surface/70 overflow-hidden">
                {/* Header - Always Visible */}
                <button
                  type="button"
                  onClick={() => toggleThinkingEntry(entry.id)}
                  className="w-full flex items-center justify-between gap-2 px-3 py-2 text-left transition-colors hover:bg-term-highlight/50"
                >
                  <div className="flex items-center gap-2 min-w-0 flex-1">
                    <span className="text-[10px] font-mono uppercase tracking-[0.24em] text-term-text-tertiary flex-shrink-0">
                      Thinking
                    </span>
                    {collapsedThinkingEntries.has(entry.id) && typeof entry.content === 'string' && (
                      <span className="text-[11px] text-term-text-muted truncate">
                        {getPreviewText(entry.content, 50)}
                      </span>
                    )}
                  </div>
                  <div className="flex-shrink-0 text-term-text-tertiary">
                    {collapsedThinkingEntries.has(entry.id) ? (
                      <ChevronDown className="h-3.5 w-3.5" />
                    ) : (
                      <ChevronUp className="h-3.5 w-3.5" />
                    )}
                  </div>
                </button>

                {/* Collapsible Content */}
                <div
                  className={`transition-[grid-template-rows] duration-300 ease-in-out ${
                    collapsedThinkingEntries.has(entry.id) ? 'grid-rows-[0fr]' : 'grid-rows-[1fr]'
                  }`}
                  style={{ display: 'grid' }}
                >
                  <div className="overflow-hidden">
                    <div className="px-3 pb-3">
                      {renderThinkingContent(entry)}
                    </div>
                  </div>
                </div>
              </div>
            )}

            {entry.type !== 'command' &&
              entry.type !== 'panel' &&
              entry.type !== 'thinking' && (
                <div className={getEntryColor(entry.type)}>
                  {renderContent(entry)}
                </div>
              )}

            {/* Render Panel */}
            {entry.type === 'panel' && renderPanel(entry)}

            {/* Timestamp - Selective display */}
            {entry.timestamp && shouldShowTimestamp(entry) && (
              <div className="mt-1 text-[10px] font-mono text-term-text-tertiary">
                {entry.timestamp.toLocaleTimeString('en-US', { hour12: false })}
              </div>
            )}
          </div>
        ))}

        {/* Empty State */}
        {history.length === 0 && (
          <div className="py-20 text-center font-mono text-term-text-muted">
            <div className="mb-4 text-4xl">⚡</div>
            <div>Terminal ready. Type a command or load /portfolio to open portfolio tools.</div>
          </div>
        )}
      </div>
    </div>
  );
};
