'use client';

import { useState, useCallback, useRef, useEffect } from 'react';
import { Copy, ChevronRight, ChevronDown, Check } from 'lucide-react';
import { StructuredLog } from './index';
import { copyToClipboard, formatLogForCopy } from '@/lib/copy-utils';

// Types
type LogLevel = 'DEBUG' | 'INFO' | 'WARN' | 'ERROR' | 'FATAL';
type LogCategory = 'scraper' | 'browser' | 'network' | 'system';

export interface LogEntryProps {
  log: StructuredLog;
  index: number;
  isSelected: boolean;
  searchQuery?: string;
  timestampFormat: 'relative' | 'absolute';
  onSelect: (index: number, shiftKey: boolean) => void;
  onCopy: (log: StructuredLog) => void;
}

// Styling constants - matching the dark theme
const LEVEL_BADGE_COLORS: Record<LogLevel, string> = {
  DEBUG: 'bg-gray-600 text-gray-200',
  INFO: 'bg-blue-600 text-blue-100',
  WARN: 'bg-yellow-600 text-yellow-100',
  ERROR: 'bg-red-600 text-red-100',
  FATAL: 'bg-purple-600 text-purple-100',
};

const CATEGORY_BADGE_COLORS: Record<LogCategory, string> = {
  scraper: 'bg-green-700 text-green-200',
  browser: 'bg-orange-700 text-orange-200',
  network: 'bg-cyan-700 text-cyan-200',
  system: 'bg-gray-600 text-gray-200',
};

const LEVEL_ROW_COLORS: Record<LogLevel, string> = {
  DEBUG: 'text-gray-300',
  INFO: 'text-blue-300',
  WARN: 'text-yellow-300',
  ERROR: 'text-red-300',
  FATAL: 'text-purple-300',
};

/**
 * Formats a timestamp as absolute time (HH:MM:SS.mmm)
 */
function formatAbsoluteTime(timestamp: string): string {
  try {
    const date = new Date(timestamp);
    return date.toLocaleTimeString('en-US', {
      hour12: false,
      hour: '2-digit',
      minute: '2-digit',
      second: '2-digit',
      fractionalSecondDigits: 3,
    });
  } catch {
    return timestamp;
  }
}

/**
 * Formats a timestamp as relative time (e.g., "2s ago", "1m ago")
 */
function formatRelativeTime(timestampMs: number): string {
  const nowMs = Date.now();
  const diffMs = nowMs - timestampMs;
  const diffSeconds = Math.floor(diffMs / 1000);

  if (diffSeconds < 0) {
    return 'just now';
  }

  if (diffSeconds < 60) {
    return `${diffSeconds}s ago`;
  }

  const diffMinutes = Math.floor(diffSeconds / 60);
  if (diffMinutes < 60) {
    return `${diffMinutes}m ago`;
  }

  const diffHours = Math.floor(diffMinutes / 60);
  if (diffHours < 24) {
    return `${diffHours}h ago`;
  }

  const diffDays = Math.floor(diffHours / 24);
  return `${diffDays}d ago`;
}

/**
 * Highlights matching text in a string
 */
function HighlightedText({ text, query }: { text: string; query: string }) {
  if (!query || !query.trim()) {
    return <>{text}</>;
  }

  const regex = new RegExp(`(${query.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')})`, 'gi');
  const parts = text.split(regex);

  return (
    <>
      {parts.map((part, index) => {
        const isMatch = part.toLowerCase() === query.toLowerCase();
        return isMatch ? (
          <mark
            key={index}
            className="bg-yellow-500/40 text-yellow-100 rounded px-0.5"
          >
            {part}
          </mark>
        ) : (
          <span key={index}>{part}</span>
        );
      })}
    </>
  );
}

/**
 * Checks if a log has expandable content (metrics or network data)
 */
function hasExpandableContent(log: StructuredLog): boolean {
  const hasMetrics = !!(log.metrics && Object.keys(log.metrics).length > 0);
  const hasNetwork = !!(log.network && Object.keys(log.network).length > 0);
  return hasMetrics || hasNetwork;
}

/**
 * LogEntry - Individual log row component with click-to-copy functionality
 *
 * Features:
 * - Click to select (with shift key support for range selection)
 * - Double-click or copy icon to copy single log entry
 * - Visual feedback on copy (brief green flash animation)
 * - Level badge with colors (DEBUG=gray, INFO=blue, WARN=yellow, ERROR=red, FATAL=purple)
 * - Category badge with colors (scraper=green, browser=orange, network=cyan, system=gray)
 * - Expandable metrics view for logs with metrics/network data
 * - Search query highlighting in message text
 */
export default function LogEntry({
  log,
  index,
  isSelected,
  searchQuery = '',
  timestampFormat,
  onSelect,
  onCopy,
}: LogEntryProps) {
  const [isExpanded, setIsExpanded] = useState(false);
  const [copyFeedback, setCopyFeedback] = useState(false);
  const [isHovered, setIsHovered] = useState(false);
  const feedbackTimeoutRef = useRef<NodeJS.Timeout | null>(null);

  // Cleanup timeout on unmount
  useEffect(() => {
    return () => {
      if (feedbackTimeoutRef.current) {
        clearTimeout(feedbackTimeoutRef.current);
      }
    };
  }, []);

  const timestamp =
    timestampFormat === 'absolute'
      ? formatAbsoluteTime(log.timestamp)
      : formatRelativeTime(log.timestamp_ms);

  const levelBadgeClass = LEVEL_BADGE_COLORS[log.level] || LEVEL_BADGE_COLORS.INFO;
  const categoryBadgeClass = CATEGORY_BADGE_COLORS[log.category] || CATEGORY_BADGE_COLORS.system;
  const messageColor = LEVEL_ROW_COLORS[log.level] || LEVEL_ROW_COLORS.INFO;

  const isEven = index % 2 === 0;
  const expandable = hasExpandableContent(log);

  // Handle single click for selection
  const handleClick = useCallback(
    (e: React.MouseEvent) => {
      onSelect(index, e.shiftKey);
    },
    [index, onSelect]
  );

  // Perform copy operation with visual feedback
  const performCopy = useCallback(async () => {
    const formattedLog = formatLogForCopy(log);
    const success = await copyToClipboard(formattedLog);

    if (success) {
      // Show visual feedback
      setCopyFeedback(true);
      onCopy(log);

      // Clear feedback after animation
      if (feedbackTimeoutRef.current) {
        clearTimeout(feedbackTimeoutRef.current);
      }
      feedbackTimeoutRef.current = setTimeout(() => {
        setCopyFeedback(false);
      }, 1000);
    }
  }, [log, onCopy]);

  // Handle double-click for copy
  const handleDoubleClick = useCallback(async () => {
    await performCopy();
  }, [performCopy]);

  // Handle copy icon click
  const handleCopyClick = useCallback(
    async (e: React.MouseEvent) => {
      e.stopPropagation(); // Prevent triggering row selection
      await performCopy();
    },
    [performCopy]
  );

  // Handle expand toggle
  const handleExpandClick = useCallback(
    (e: React.MouseEvent) => {
      e.stopPropagation(); // Prevent triggering row selection
      setIsExpanded((prev) => !prev);
    },
    []
  );

  // Build row background class
  const getRowBgClass = () => {
    if (copyFeedback) {
      return 'bg-green-900/50 border-l-2 border-green-500';
    }
    if (isSelected) {
      return 'bg-blue-900/50 border-l-2 border-blue-500';
    }
    if (isHovered) {
      return 'bg-gray-700/50';
    }
    return isEven ? 'bg-gray-900/30' : 'bg-gray-800/30';
  };

  return (
    <div
      className={`transition-all duration-150 ${copyFeedback ? 'animate-pulse' : ''}`}
      onMouseEnter={() => setIsHovered(true)}
      onMouseLeave={() => setIsHovered(false)}
    >
      {/* Main row */}
      <div
        className={`flex items-center gap-2 px-3 py-2 cursor-pointer transition-colors ${getRowBgClass()}`}
        onClick={handleClick}
        onDoubleClick={handleDoubleClick}
      >
        {/* Expand chevron (if expandable) */}
        <div className="w-4 flex-shrink-0">
          {expandable && (
            <button
              onClick={handleExpandClick}
              className="p-0.5 text-gray-500 hover:text-gray-300 transition-colors"
              title={isExpanded ? 'Collapse' : 'Expand'}
            >
              {isExpanded ? (
                <ChevronDown className="w-3.5 h-3.5" />
              ) : (
                <ChevronRight className="w-3.5 h-3.5" />
              )}
            </button>
          )}
        </div>

        {/* Timestamp */}
        <span className="text-gray-500 text-xs font-mono whitespace-nowrap w-[80px] flex-shrink-0">
          {timestamp}
        </span>

        {/* Level badge */}
        <span
          className={`px-1.5 py-0.5 text-xs font-semibold rounded ${levelBadgeClass} whitespace-nowrap flex-shrink-0 w-[50px] text-center`}
        >
          {log.level}
        </span>

        {/* Category badge */}
        <span
          className={`px-1.5 py-0.5 text-xs font-medium rounded ${categoryBadgeClass} whitespace-nowrap flex-shrink-0 w-[60px] text-center`}
        >
          {log.category}
        </span>

        {/* Message */}
        <span
          className={`flex-1 font-mono text-sm ${messageColor} ${isExpanded ? '' : 'truncate'}`}
          title={isExpanded ? undefined : log.message}
        >
          <HighlightedText text={log.message} query={searchQuery} />
        </span>

        {/* Copy button (visible on hover) */}
        <button
          onClick={handleCopyClick}
          className={`p-1.5 rounded transition-all flex-shrink-0 ${
            isHovered || copyFeedback
              ? 'opacity-100'
              : 'opacity-0'
          } ${
            copyFeedback
              ? 'text-green-400 bg-green-900/50'
              : 'text-gray-500 hover:text-gray-300 hover:bg-gray-700'
          }`}
          title="Copy log entry"
        >
          {copyFeedback ? (
            <Check className="w-4 h-4" />
          ) : (
            <Copy className="w-4 h-4" />
          )}
        </button>
      </div>

      {/* Expanded content */}
      {isExpanded && expandable && (
        <div className="px-3 py-2 ml-4 bg-gray-800/50 border-l-2 border-gray-600">
          {/* Full message (no truncation) */}
          <div className={`font-mono text-sm ${messageColor} mb-2 break-words`}>
            <HighlightedText text={log.message} query={searchQuery} />
          </div>

          {/* Metrics */}
          {log.metrics && Object.keys(log.metrics).length > 0 && (
            <div className="mb-2">
              <div className="text-xs text-gray-400 font-semibold mb-1">Metrics:</div>
              <div className="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 gap-2">
                {Object.entries(log.metrics).map(([key, value]) => (
                  <div
                    key={key}
                    className="flex items-center gap-1 text-xs bg-gray-700/50 rounded px-2 py-1"
                  >
                    <span className="text-gray-400">{key}:</span>
                    <span className="text-gray-200 font-mono">
                      {typeof value === 'number'
                        ? value.toLocaleString()
                        : typeof value === 'object'
                        ? JSON.stringify(value)
                        : String(value)}
                    </span>
                  </div>
                ))}
              </div>
            </div>
          )}

          {/* Network info */}
          {log.network && Object.keys(log.network).length > 0 && (
            <div>
              <div className="text-xs text-gray-400 font-semibold mb-1">Network:</div>
              <div className="flex flex-wrap gap-3 text-xs">
                {log.network.status !== undefined && (
                  <div className="flex items-center gap-1">
                    <span className="text-gray-400">Status:</span>
                    <span
                      className={`font-mono ${
                        log.network.status >= 200 && log.network.status < 300
                          ? 'text-green-400'
                          : log.network.status >= 400
                          ? 'text-red-400'
                          : 'text-yellow-400'
                      }`}
                    >
                      {log.network.status}
                    </span>
                  </div>
                )}
                {log.network.url && (
                  <div className="flex items-center gap-1 max-w-full">
                    <span className="text-gray-400">URL:</span>
                    <span className="text-cyan-400 font-mono truncate max-w-[300px]" title={log.network.url}>
                      {log.network.url}
                    </span>
                  </div>
                )}
                {log.network.duration !== undefined && (
                  <div className="flex items-center gap-1">
                    <span className="text-gray-400">Duration:</span>
                    <span className="text-gray-200 font-mono">
                      {log.network.duration}ms
                    </span>
                  </div>
                )}
                {/* Render any other network properties */}
                {Object.entries(log.network)
                  .filter(([key]) => !['status', 'url', 'duration'].includes(key))
                  .map(([key, value]) => (
                    <div key={key} className="flex items-center gap-1">
                      <span className="text-gray-400">{key}:</span>
                      <span className="text-gray-200 font-mono">
                        {typeof value === 'object' ? JSON.stringify(value) : String(value)}
                      </span>
                    </div>
                  ))}
              </div>
            </div>
          )}
        </div>
      )}
    </div>
  );
}

// Export types for external use
export type { LogLevel, LogCategory };
