/**
 * OrderBookDepthVisualization Component
 * Visual depth chart showing cumulative bid/ask volumes
 * Epic: OQI-003 Trading Charts
 */

import React, { useMemo, useRef, useEffect, useState, useCallback } from 'react';
import {
  ChartBarIcon,
  ArrowPathIcon,
  ArrowsPointingOutIcon,
  Cog6ToothIcon,
} from '@heroicons/react/24/solid';

// Types
export interface DepthLevel {
  price: number;
  quantity: number;
  total: number;
}

export interface DepthData {
  bids: DepthLevel[];
  asks: DepthLevel[];
  midPrice: number;
  spread: number;
  spreadPercentage: number;
  lastUpdate: Date;
}

export interface DepthChartConfig {
  showGrid: boolean;
  showMidLine: boolean;
  showTooltip: boolean;
  animateChanges: boolean;
  bidColor: string;
  askColor: string;
  fillOpacity: number;
  strokeWidth: number;
  priceRange: number; // percentage from mid price
}

interface OrderBookDepthVisualizationProps {
  data: DepthData | null;
  config?: Partial<DepthChartConfig>;
  onPriceClick?: (price: number, side: 'bid' | 'ask') => void;
  onRefresh?: () => void;
  isLoading?: boolean;
  height?: number;
  compact?: boolean;
}

const DEFAULT_CONFIG: DepthChartConfig = {
  showGrid: true,
  showMidLine: true,
  showTooltip: true,
  animateChanges: true,
  bidColor: '#22c55e',
  askColor: '#ef4444',
  fillOpacity: 0.3,
  strokeWidth: 2,
  priceRange: 5,
};

const OrderBookDepthVisualization: React.FC<OrderBookDepthVisualizationProps> = ({
  data,
  config: userConfig,
  onPriceClick,
  onRefresh,
  isLoading = false,
  height = 300,
  compact = false,
}) => {
  const canvasRef = useRef<HTMLCanvasElement>(null);
  const containerRef = useRef<HTMLDivElement>(null);
  const [tooltip, setTooltip] = useState<{
    visible: boolean;
    x: number;
    y: number;
    price: number;
    quantity: number;
    total: number;
    side: 'bid' | 'ask';
  } | null>(null);
  const [showSettings, setShowSettings] = useState(false);
  const [localConfig, setLocalConfig] = useState<DepthChartConfig>({
    ...DEFAULT_CONFIG,
    ...userConfig,
  });

  const config = useMemo(() => ({ ...DEFAULT_CONFIG, ...userConfig, ...localConfig }), [userConfig, localConfig]);

  // Calculate chart dimensions and scales
  const chartMetrics = useMemo(() => {
    if (!data || !canvasRef.current) return null;

    const canvas = canvasRef.current;
    const width = canvas.width;
    const chartHeight = canvas.height;
    const padding = { top: 20, right: 60, bottom: 30, left: 60 };

    const chartWidth = width - padding.left - padding.right;
    const drawHeight = chartHeight - padding.top - padding.bottom;

    // Find max total for Y scale
    const maxBidTotal = data.bids.length > 0 ? Math.max(...data.bids.map((d) => d.total)) : 0;
    const maxAskTotal = data.asks.length > 0 ? Math.max(...data.asks.map((d) => d.total)) : 0;
    const maxTotal = Math.max(maxBidTotal, maxAskTotal, 1);

    // Price range based on config percentage
    const priceRange = data.midPrice * (config.priceRange / 100);
    const minPrice = data.midPrice - priceRange;
    const maxPrice = data.midPrice + priceRange;

    return {
      width,
      chartHeight,
      chartWidth,
      drawHeight,
      padding,
      maxTotal,
      minPrice,
      maxPrice,
      priceRange,
      xScale: (price: number) => {
        const normalized = (price - minPrice) / (maxPrice - minPrice);
        return padding.left + normalized * chartWidth;
      },
      yScale: (total: number) => {
        const normalized = total / maxTotal;
        return chartHeight - padding.bottom - normalized * drawHeight;
      },
    };
  }, [data, config.priceRange]);

  // Draw the depth chart
  const drawChart = useCallback(() => {
    const canvas = canvasRef.current;
    const ctx = canvas?.getContext('2d');
    if (!canvas || !ctx || !data || !chartMetrics) return;

    const { width, chartHeight, padding, xScale, yScale, minPrice, maxPrice, maxTotal } = chartMetrics;

    // Clear canvas
    ctx.clearRect(0, 0, width, chartHeight);

    // Background
    ctx.fillStyle = '#1f2937';
    ctx.fillRect(0, 0, width, chartHeight);

    // Draw grid
    if (config.showGrid) {
      ctx.strokeStyle = '#374151';
      ctx.lineWidth = 0.5;

      // Horizontal grid lines (5 lines)
      for (let i = 0; i <= 4; i++) {
        const y = yScale((maxTotal / 4) * i);
        ctx.beginPath();
        ctx.moveTo(padding.left, y);
        ctx.lineTo(width - padding.right, y);
        ctx.stroke();
      }

      // Vertical grid lines (5 lines)
      const priceStep = (maxPrice - minPrice) / 4;
      for (let i = 0; i <= 4; i++) {
        const x = xScale(minPrice + priceStep * i);
        ctx.beginPath();
        ctx.moveTo(x, padding.top);
        ctx.lineTo(x, chartHeight - padding.bottom);
        ctx.stroke();
      }
    }

    // Draw mid price line
    if (config.showMidLine) {
      const midX = xScale(data.midPrice);
      ctx.strokeStyle = '#6b7280';
      ctx.lineWidth = 1;
      ctx.setLineDash([5, 5]);
      ctx.beginPath();
      ctx.moveTo(midX, padding.top);
      ctx.lineTo(midX, chartHeight - padding.bottom);
      ctx.stroke();
      ctx.setLineDash([]);
    }

    // Draw bid area (left side)
    if (data.bids.length > 0) {
      const filteredBids = data.bids.filter((b) => b.price >= minPrice && b.price <= data.midPrice);

      if (filteredBids.length > 0) {
        // Fill
        ctx.fillStyle = config.bidColor + Math.round(config.fillOpacity * 255).toString(16).padStart(2, '0');
        ctx.beginPath();
        ctx.moveTo(xScale(filteredBids[0].price), yScale(0));
        filteredBids.forEach((level) => {
          ctx.lineTo(xScale(level.price), yScale(level.total));
        });
        ctx.lineTo(xScale(filteredBids[filteredBids.length - 1].price), yScale(0));
        ctx.closePath();
        ctx.fill();

        // Stroke
        ctx.strokeStyle = config.bidColor;
        ctx.lineWidth = config.strokeWidth;
        ctx.beginPath();
        ctx.moveTo(xScale(filteredBids[0].price), yScale(filteredBids[0].total));
        filteredBids.forEach((level) => {
          ctx.lineTo(xScale(level.price), yScale(level.total));
        });
        ctx.stroke();
      }
    }

    // Draw ask area (right side)
    if (data.asks.length > 0) {
      const filteredAsks = data.asks.filter((a) => a.price <= maxPrice && a.price >= data.midPrice);

      if (filteredAsks.length > 0) {
        // Fill
        ctx.fillStyle = config.askColor + Math.round(config.fillOpacity * 255).toString(16).padStart(2, '0');
        ctx.beginPath();
        ctx.moveTo(xScale(filteredAsks[0].price), yScale(0));
        filteredAsks.forEach((level) => {
          ctx.lineTo(xScale(level.price), yScale(level.total));
        });
        ctx.lineTo(xScale(filteredAsks[filteredAsks.length - 1].price), yScale(0));
        ctx.closePath();
        ctx.fill();

        // Stroke
        ctx.strokeStyle = config.askColor;
        ctx.lineWidth = config.strokeWidth;
        ctx.beginPath();
        ctx.moveTo(xScale(filteredAsks[0].price), yScale(filteredAsks[0].total));
        filteredAsks.forEach((level) => {
          ctx.lineTo(xScale(level.price), yScale(level.total));
        });
        ctx.stroke();
      }
    }

    // Draw Y axis labels (quantity)
    ctx.fillStyle = '#9ca3af';
    ctx.font = '10px monospace';
    ctx.textAlign = 'right';
    for (let i = 0; i <= 4; i++) {
      const value = (maxTotal / 4) * i;
      const y = yScale(value);
      ctx.fillText(formatQuantity(value), padding.left - 5, y + 3);
    }

    // Draw X axis labels (price)
    ctx.textAlign = 'center';
    const priceStep = (maxPrice - minPrice) / 4;
    for (let i = 0; i <= 4; i++) {
      const price = minPrice + priceStep * i;
      const x = xScale(price);
      ctx.fillText(formatPrice(price), x, chartHeight - padding.bottom + 15);
    }

    // Draw mid price label
    ctx.fillStyle = '#ffffff';
    ctx.font = '11px monospace';
    ctx.fillText(formatPrice(data.midPrice), xScale(data.midPrice), padding.top - 5);
  }, [data, chartMetrics, config]);

  // Handle canvas resize
  useEffect(() => {
    const canvas = canvasRef.current;
    const container = containerRef.current;
    if (!canvas || !container) return;

    const resizeObserver = new ResizeObserver((entries) => {
      for (const entry of entries) {
        const { width } = entry.contentRect;
        canvas.width = width;
        canvas.height = height;
        drawChart();
      }
    });

    resizeObserver.observe(container);
    return () => resizeObserver.disconnect();
  }, [height, drawChart]);

  // Redraw on data change
  useEffect(() => {
    drawChart();
  }, [drawChart]);

  // Handle mouse move for tooltip
  const handleMouseMove = useCallback(
    (e: React.MouseEvent<HTMLCanvasElement>) => {
      if (!config.showTooltip || !data || !chartMetrics) {
        setTooltip(null);
        return;
      }

      const canvas = canvasRef.current;
      if (!canvas) return;

      const rect = canvas.getBoundingClientRect();
      const x = e.clientX - rect.left;
      const y = e.clientY - rect.top;

      const { padding, xScale, minPrice, maxPrice } = chartMetrics;

      // Check if within chart area
      if (
        x < padding.left ||
        x > canvas.width - padding.right ||
        y < padding.top ||
        y > canvas.height - padding.bottom
      ) {
        setTooltip(null);
        return;
      }

      // Find price at mouse position
      const price = minPrice + ((x - padding.left) / (canvas.width - padding.left - padding.right)) * (maxPrice - minPrice);

      // Determine side
      const side: 'bid' | 'ask' = price < data.midPrice ? 'bid' : 'ask';
      const levels = side === 'bid' ? data.bids : data.asks;

      // Find closest level
      let closest = levels[0];
      let minDist = Math.abs(price - closest?.price);
      for (const level of levels) {
        const dist = Math.abs(price - level.price);
        if (dist < minDist) {
          minDist = dist;
          closest = level;
        }
      }

      if (closest) {
        setTooltip({
          visible: true,
          x: xScale(closest.price),
          y: e.clientY - rect.top,
          price: closest.price,
          quantity: closest.quantity,
          total: closest.total,
          side,
        });
      }
    },
    [config.showTooltip, data, chartMetrics]
  );

  const handleMouseLeave = useCallback(() => {
    setTooltip(null);
  }, []);

  const handleCanvasClick = useCallback(
    (e: React.MouseEvent<HTMLCanvasElement>) => {
      if (!onPriceClick || !tooltip) return;
      onPriceClick(tooltip.price, tooltip.side);
    },
    [onPriceClick, tooltip]
  );

  // Format helpers
  const formatPrice = (price: number): string => {
    if (price >= 1000) return price.toLocaleString(undefined, { maximumFractionDigits: 2 });
    if (price >= 1) return price.toFixed(4);
    return price.toFixed(6);
  };

  const formatQuantity = (qty: number): string => {
    if (qty >= 1000000) return `${(qty / 1000000).toFixed(1)}M`;
    if (qty >= 1000) return `${(qty / 1000).toFixed(1)}K`;
    return qty.toFixed(2);
  };

  return (
    <div className={`bg-gray-800/50 rounded-lg ${compact ? 'p-2' : 'p-4'} flex flex-col`}>
      {/* Header */}
      <div className="flex items-center justify-between mb-3">
        <div className="flex items-center gap-2">
          <ChartBarIcon className="w-5 h-5 text-blue-400" />
          <h3 className={`font-semibold text-white ${compact ? 'text-xs' : 'text-sm'}`}>
            Market Depth
          </h3>
          {data && (
            <span className="text-xs text-gray-400">
              Spread: {formatPrice(data.spread)} ({data.spreadPercentage.toFixed(3)}%)
            </span>
          )}
        </div>
        <div className="flex items-center gap-1">
          <button
            onClick={() => setShowSettings(!showSettings)}
            className="p-1.5 text-gray-400 hover:text-white hover:bg-gray-700 rounded transition-colors"
            title="Settings"
          >
            <Cog6ToothIcon className="w-4 h-4" />
          </button>
          {onRefresh && (
            <button
              onClick={onRefresh}
              disabled={isLoading}
              className="p-1.5 text-gray-400 hover:text-white hover:bg-gray-700 rounded transition-colors"
              title="Refresh"
            >
              <ArrowPathIcon className={`w-4 h-4 ${isLoading ? 'animate-spin' : ''}`} />
            </button>
          )}
        </div>
      </div>

      {/* Settings Panel */}
      {showSettings && (
        <div className="mb-3 p-3 bg-gray-900/50 rounded-lg space-y-2">
          <div className="grid grid-cols-2 gap-3 text-xs">
            <label className="flex items-center gap-2">
              <input
                type="checkbox"
                checked={localConfig.showGrid}
                onChange={(e) => setLocalConfig({ ...localConfig, showGrid: e.target.checked })}
                className="rounded bg-gray-700 border-gray-600"
              />
              <span className="text-gray-300">Show Grid</span>
            </label>
            <label className="flex items-center gap-2">
              <input
                type="checkbox"
                checked={localConfig.showMidLine}
                onChange={(e) => setLocalConfig({ ...localConfig, showMidLine: e.target.checked })}
                className="rounded bg-gray-700 border-gray-600"
              />
              <span className="text-gray-300">Show Mid Line</span>
            </label>
            <div className="col-span-2">
              <label className="text-gray-300 block mb-1">Price Range: {localConfig.priceRange}%</label>
              <input
                type="range"
                min="1"
                max="20"
                value={localConfig.priceRange}
                onChange={(e) => setLocalConfig({ ...localConfig, priceRange: Number(e.target.value) })}
                className="w-full h-1 bg-gray-700 rounded-lg appearance-none cursor-pointer"
              />
            </div>
          </div>
        </div>
      )}

      {/* Chart Container */}
      <div ref={containerRef} className="relative flex-1" style={{ minHeight: height }}>
        <canvas
          ref={canvasRef}
          onMouseMove={handleMouseMove}
          onMouseLeave={handleMouseLeave}
          onClick={handleCanvasClick}
          className="w-full cursor-crosshair"
          style={{ height }}
        />

        {/* Tooltip */}
        {tooltip?.visible && (
          <div
            className="absolute pointer-events-none bg-gray-900 border border-gray-700 rounded px-2 py-1 text-xs shadow-lg z-10"
            style={{
              left: tooltip.x + 10,
              top: tooltip.y - 40,
              transform: tooltip.x > (canvasRef.current?.width || 0) / 2 ? 'translateX(-100%)' : 'none',
            }}
          >
            <div className={`font-semibold ${tooltip.side === 'bid' ? 'text-green-400' : 'text-red-400'}`}>
              {tooltip.side === 'bid' ? 'BID' : 'ASK'}
            </div>
            <div className="text-gray-300">Price: {formatPrice(tooltip.price)}</div>
            <div className="text-gray-300">Qty: {formatQuantity(tooltip.quantity)}</div>
            <div className="text-gray-400">Total: {formatQuantity(tooltip.total)}</div>
          </div>
        )}

        {/* Loading Overlay */}
        {isLoading && (
          <div className="absolute inset-0 bg-gray-900/50 flex items-center justify-center">
            <ArrowPathIcon className="w-8 h-8 text-blue-400 animate-spin" />
          </div>
        )}

        {/* Empty State */}
        {!isLoading && !data && (
          <div className="absolute inset-0 flex items-center justify-center">
            <div className="text-center text-gray-500">
              <ChartBarIcon className="w-12 h-12 mx-auto mb-2 opacity-50" />
              <p className="text-sm">No depth data available</p>
            </div>
          </div>
        )}
      </div>

      {/* Legend */}
      {!compact && (
        <div className="flex items-center justify-center gap-6 mt-3 text-xs">
          <div className="flex items-center gap-2">
            <div className="w-3 h-3 rounded" style={{ backgroundColor: config.bidColor }} />
            <span className="text-gray-400">Bids (Buy Orders)</span>
          </div>
          <div className="flex items-center gap-2">
            <div className="w-3 h-3 rounded" style={{ backgroundColor: config.askColor }} />
            <span className="text-gray-400">Asks (Sell Orders)</span>
          </div>
        </div>
      )}
    </div>
  );
};

export default OrderBookDepthVisualization;
