/**
 * Ichimoku Cloud Fill Plugin
 * LWC v5 ISeriesPrimitive를 이용해 선행스팬A/B 사이 구름 영역을 캔버스에 직접 렌더링합니다.
 *
 * 한국 관례:
 *   SpanA > SpanB  → 양운 (빨간 구름, 상승 신호)
 *   SpanA <= SpanB → 음운 (청록 구름, 하락 신호)
 */
import type {
  ISeriesPrimitive,
  IPrimitivePaneView,
  IPrimitivePaneRenderer,
  SeriesAttachedParameter,
  ISeriesApi,
  SeriesType,
  Time,
  IChartApiBase,
} from 'lightweight-charts';

export interface IchimokuCloudPoint {
  time:  number;   // Unix timestamp (seconds)
  spanA: number;
  spanB: number;
}

function toCanvasFillColor(color: string): string {
  if (color.startsWith('rgba(') || color.startsWith('rgb(')) return color;
  const hex = color.startsWith('#') ? color.slice(1) : color;
  if (hex.length < 6) return color;
  const r = parseInt(hex.slice(0, 2), 16);
  const g = parseInt(hex.slice(2, 4), 16);
  const b = parseInt(hex.slice(4, 6), 16);
  const a = hex.length >= 8
    ? parseInt(hex.slice(6, 8), 16) / 255
    : 1;
  return `rgba(${r}, ${g}, ${b}, ${a})`;
}

// ─── Renderer ──────────────────────────────────────────────────────────────
class CloudRenderer implements IPrimitivePaneRenderer {
  private _chart:  IChartApiBase<Time>;
  private _series: ISeriesApi<SeriesType>;
  private _data:   IchimokuCloudPoint[];
  private _bullishColor: string;
  private _bearishColor: string;

  constructor(
    chart:  IChartApiBase<Time>,
    series: ISeriesApi<SeriesType>,
    data:   IchimokuCloudPoint[],
    bullishColor: string,
    bearishColor: string,
  ) {
    this._chart  = chart;
    this._series = series;
    this._data   = data;
    this._bullishColor = bullishColor;
    this._bearishColor = bearishColor;
  }

  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  draw(target: any): void {
    if (this._data.length < 2) return;
    const timeScale = this._chart.timeScale();

    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    target.useBitmapCoordinateSpace(({ context: ctx, horizontalPixelRatio: hpr, verticalPixelRatio: vpr }: any) => {
      for (let i = 0; i < this._data.length - 1; i++) {
        const a = this._data[i];
        const b = this._data[i + 1];

        const x1 = timeScale.timeToCoordinate(a.time as Time);
        const x2 = timeScale.timeToCoordinate(b.time as Time);
        if (x1 == null || x2 == null) continue;

        const aAy = this._series.priceToCoordinate(a.spanA);
        const aBy = this._series.priceToCoordinate(a.spanB);
        const bAy = this._series.priceToCoordinate(b.spanA);
        const bBy = this._series.priceToCoordinate(b.spanB);
        if (aAy == null || aBy == null || bAy == null || bBy == null) continue;

        // 한국 관례: SpanA > SpanB → 양운(빨강), SpanA <= SpanB → 음운(청록)
        const bullish = (a.spanA + b.spanA) > (a.spanB + b.spanB);

        ctx.save();
        ctx.beginPath();
        ctx.moveTo(x1 * hpr, aAy * vpr);
        ctx.lineTo(x2 * hpr, bAy * vpr);
        ctx.lineTo(x2 * hpr, bBy * vpr);
        ctx.lineTo(x1 * hpr, aBy * vpr);
        ctx.closePath();
        ctx.fillStyle = bullish ? this._bullishColor : this._bearishColor;
        ctx.fill();
        ctx.restore();
      }
    });
  }
}

// ─── Pane View ─────────────────────────────────────────────────────────────
class CloudPaneView implements IPrimitivePaneView {
  private _plugin: IchimokuCloudPlugin;
  constructor(plugin: IchimokuCloudPlugin) { this._plugin = plugin; }

  renderer(): IPrimitivePaneRenderer | null {
    const chart  = this._plugin.getChart();
    const series = this._plugin.getSeries();
    if (!chart || !series) return null;
    return new CloudRenderer(
      chart,
      series,
      this._plugin.getCloudData(),
      this._plugin.getBullishColor(),
      this._plugin.getBearishColor(),
    );
  }
}

// ─── Plugin ────────────────────────────────────────────────────────────────
export class IchimokuCloudPlugin implements ISeriesPrimitive<Time> {
  private _chart:    IChartApiBase<Time> | null = null;
  private _series:   ISeriesApi<SeriesType> | null = null;
  private _data:     IchimokuCloudPoint[] = [];
  private _bullishColor = 'rgba(239, 83, 80, 0.2)';
  private _bearishColor = 'rgba(38, 166, 154, 0.2)';
  private _updateFn: (() => void) | null = null;

  attached({ chart, series, requestUpdate }: SeriesAttachedParameter<Time>): void {
    this._chart    = chart;
    this._series   = series;
    this._updateFn = requestUpdate;
  }

  detached(): void {
    this._chart  = null;
    this._series = null;
  }

  setCloudData(data: IchimokuCloudPoint[]): void {
    this._data = data;
    this._updateFn?.();
  }

  setColors(bullishColor: string, bearishColor: string): void {
    this._bullishColor = toCanvasFillColor(bullishColor);
    this._bearishColor = toCanvasFillColor(bearishColor);
    this._updateFn?.();
  }

  getBullishColor() { return this._bullishColor; }
  getBearishColor() { return this._bearishColor; }

  paneViews(): readonly IPrimitivePaneView[] {
    if (!this._chart || !this._series) return [];
    return [new CloudPaneView(this)];
  }

  getChart()     { return this._chart; }
  getSeries()    { return this._series; }
  getCloudData() { return this._data; }
}
