import React, { useCallback, useEffect, useRef } from 'react';
import ReactMarkdown from 'react-markdown';
import remarkGfm from 'remark-gfm';
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 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="text-[14px] leading-7 text-[#d6e9ff] break-words [&_strong]:font-semibold [&_strong]:text-white">
      <ReactMarkdown
        remarkPlugins={[remarkGfm]}
        components={{
          h1: ({ children }) => (
            <h1 className="mb-3 mt-1 text-[1.35rem] font-semibold tracking-[-0.02em] text-white">
              {children}
            </h1>
          ),
          h2: ({ children }) => (
            <h2 className="mb-2 mt-4 text-[1.15rem] font-semibold text-white">
              {children}
            </h2>
          ),
          h3: ({ children }) => (
            <h3 className="mb-2 mt-3 text-[1rem] font-semibold text-[#f3f8ff]">
              {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-[#58a6ff]/60 pl-4 italic text-[#a8cfff]">
              {children}
            </blockquote>
          ),
          a: ({ href, children }) => (
            <a
              href={href}
              target="_blank"
              rel="noreferrer"
              className="text-[#7fc0ff] underline decoration-[#58a6ff]/50 underline-offset-4 transition-colors hover:text-[#b7ddff] break-all"
            >
              {children}
            </a>
          ),
          hr: () => <hr className="my-4 border-[#223044]" />,
          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-[#223044] text-[#9cc9f6]">{children}</thead>,
          tbody: ({ children }) => <tbody>{children}</tbody>,
          tr: ({ children }) => <tr className="border-b border-[#192330] 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-[#d6e9ff]">{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-[#1d2a3a] bg-[#09111c] px-4 py-3 font-mono text-[13px] leading-6 text-[#d8ecff] break-all">
                {value}
              </code>
            ) : (
              <code className="rounded bg-[#111827] px-1.5 py-0.5 font-mono text-[0.92em] text-[#ffd580] 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-[#e0e0e0]';
      case 'response':
        return 'text-[#58a6ff]';
      case 'system':
        return 'text-[#888888] italic';
      case 'thinking':
        return 'text-[#8aa1bc]';
      case 'error':
        return 'text-[#ff4757]';
      case 'panel':
        return '';
      default:
        return 'text-[#e0e0e0]';
    }
  };

  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} />;
      default:
        return null;
    }
  };

  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: '#2a2a2a #111111'
      }}
    >
      <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-[#58a6ff] font-mono select-none">{'>'}</span>
                <div className={getEntryColor(entry.type)}>
                  {renderContent(entry)}
                </div>
              </div>
            )}

            {entry.type === 'thinking' && (
              <div className="rounded-lg border border-[#223044] bg-[#0f1724]/70 px-3 py-2">
                <div className="mb-1 text-[10px] font-mono uppercase tracking-[0.24em] text-[#5d7491]">
                  Thinking
                </div>
                <div className={getEntryColor(entry.type)}>
                  {renderContent(entry)}
                </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] text-[#666666] font-mono">
                {entry.timestamp.toLocaleTimeString('en-US', { hour12: false })}
              </div>
            )}
          </div>
        ))}

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