import React, { useCallback, useEffect, useRef } from 'react';
import type { ChartManager } from '../utils/ChartManager';
import type { ChartPaneSeparatorOptions, PaneSeparatorStyle } from '../types/chartPaneSeparator';
import { classifyPaneBoundary, paneSeparatorOptionsKey } from '../types/chartPaneSeparator';
import { plotColorCss } from '../utils/plotColorUtils';

interface Props {
  manager: ChartManager;
  options: ChartPaneSeparatorOptions;
}

function applyLineDash(ctx: CanvasRenderingContext2D, style: PaneSeparatorStyle['lineStyle']) {
  if (style === 'dashed') ctx.setLineDash([6, 4]);
  else if (style === 'dotted') ctx.setLineDash([2, 3]);
  else ctx.setLineDash([]);
}

function strokeBoundary(
  ctx: CanvasRenderingContext2D,
  cssW: number,
  y: number,
  style: PaneSeparatorStyle,
) {
  if (!style.visible) return;
  ctx.strokeStyle = plotColorCss(style.color);
  ctx.lineWidth = style.width;
  applyLineDash(ctx, style.lineStyle);
  const lineY = y + style.width / 2;
  ctx.beginPath();
  ctx.moveTo(0, lineY);
  ctx.lineTo(cssW, lineY);
  ctx.stroke();
}

const PaneSeparatorOverlay: React.FC<Props> = ({ manager, options }) => {
  const canvasRef = useRef<HTMLCanvasElement>(null);
  const optionsKey = paneSeparatorOptionsKey(options);

  const redraw = useCallback(() => {
    const canvas = canvasRef.current;
    const container = manager.getContainer();
    if (!canvas || !container) return;

    const cssW = container.clientWidth;
    const cssH = container.clientHeight;
    if (cssW <= 0 || cssH <= 0) return;

    const dpr = window.devicePixelRatio || 1;
    canvas.width = Math.round(cssW * dpr);
    canvas.height = Math.round(cssH * dpr);
    canvas.style.width = `${cssW}px`;
    canvas.style.height = `${cssH}px`;

    const ctx = canvas.getContext('2d');
    if (!ctx) return;
    ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
    ctx.clearRect(0, 0, cssW, cssH);

    const layouts = manager.getPaneLayouts()
      .filter(l => l.height > 8)
      .sort((a, b) => a.topY - b.topY);
    if (layouts.length < 2) return;

    for (let i = 0; i < layouts.length - 1; i++) {
      const lower = layouts[i];
      const upper = layouts[i + 1];
      const kind = classifyPaneBoundary(lower.paneIndex, upper.paneIndex);
      if (kind === 'other') continue;

      const style = kind === 'mainToIndicator'
        ? options.mainToIndicator
        : options.indicatorToIndicator;
      const y = lower.topY + lower.height;
      strokeBoundary(ctx, cssW, y, style);
    }
  }, [manager, options, optionsKey]);

  useEffect(() => {
    redraw();
    let layoutRaf = 0;
    const scheduleRedraw = () => {
      cancelAnimationFrame(layoutRaf);
      layoutRaf = requestAnimationFrame(redraw);
    };
    const unsub = manager.subscribePaneLayout(scheduleRedraw);
    const container = manager.getContainer();
    const ro = new ResizeObserver(scheduleRedraw);
    if (container) ro.observe(container);
    const raf1 = requestAnimationFrame(redraw);
    const raf2 = requestAnimationFrame(() => requestAnimationFrame(redraw));
    return () => {
      unsub();
      ro.disconnect();
      cancelAnimationFrame(layoutRaf);
      cancelAnimationFrame(raf1);
      cancelAnimationFrame(raf2);
    };
  }, [manager, redraw, optionsKey]);

  return (
    <canvas
      ref={canvasRef}
      className="pane-separator-overlay"
      aria-hidden
      style={{
        position: 'absolute',
        inset: 0,
        pointerEvents: 'none',
        zIndex: 4,
      }}
    />
  );
};

export default PaneSeparatorOverlay;
