"use client";

import { useEffect, useRef } from "react";
import {
  createChart,
  type CandlestickData,
  type IChartApi,
  type ISeriesApi,
  type LineData,
  type UTCTimestamp,
} from "lightweight-charts";
import type { ChartPayload, LatestPredictionResponse } from "../lib/api";

type Props = {
  chart: ChartPayload;
  prediction?: LatestPredictionResponse | null;
};

function dateToUtcTs(d: string): UTCTimestamp {
  // 'YYYY-MM-DD' → UTC midnight epoch seconds
  return (Date.UTC(
    Number(d.slice(0, 4)),
    Number(d.slice(5, 7)) - 1,
    Number(d.slice(8, 10)),
  ) / 1000) as UTCTimestamp;
}

export function StockChart({ chart, prediction }: Props) {
  const containerRef = useRef<HTMLDivElement | null>(null);
  const chartRef = useRef<IChartApi | null>(null);
  const candleRef = useRef<ISeriesApi<"Candlestick"> | null>(null);
  const predRef = useRef<ISeriesApi<"Line"> | null>(null);
  const predLowRef = useRef<ISeriesApi<"Line"> | null>(null);
  const predHighRef = useRef<ISeriesApi<"Line"> | null>(null);

  // create chart once
  useEffect(() => {
    if (!containerRef.current) return;
    const c = createChart(containerRef.current, {
      layout: {
        background: { color: "transparent" },
        textColor: "#cbd5e1",
      },
      grid: {
        vertLines: { color: "#1f2937" },
        horzLines: { color: "#1f2937" },
      },
      rightPriceScale: { borderColor: "#374151" },
      timeScale: { borderColor: "#374151", timeVisible: false },
      autoSize: true,
    });
    const candle = c.addCandlestickSeries({
      upColor: "#22c55e",
      downColor: "#ef4444",
      borderUpColor: "#22c55e",
      borderDownColor: "#ef4444",
      wickUpColor: "#22c55e",
      wickDownColor: "#ef4444",
    });
    chartRef.current = c;
    candleRef.current = candle;
    return () => {
      c.remove();
      chartRef.current = null;
      candleRef.current = null;
      predRef.current = null;
      predLowRef.current = null;
      predHighRef.current = null;
    };
  }, []);

  // push candle data
  useEffect(() => {
    if (!candleRef.current) return;
    const data: CandlestickData[] = chart.ohlcv
      .filter((p) => p.open !== null && p.high !== null && p.low !== null && p.close !== null)
      .map((p) => ({
        time: dateToUtcTs(p.date),
        open: p.open as number,
        high: p.high as number,
        low: p.low as number,
        close: p.close as number,
      }));
    candleRef.current.setData(data);
    chartRef.current?.timeScale().fitContent();
  }, [chart]);

  // push prediction overlay
  useEffect(() => {
    if (!chartRef.current) return;
    // remove previous overlay
    if (predRef.current) {
      chartRef.current.removeSeries(predRef.current);
      predRef.current = null;
    }
    if (predLowRef.current) {
      chartRef.current.removeSeries(predLowRef.current);
      predLowRef.current = null;
    }
    if (predHighRef.current) {
      chartRef.current.removeSeries(predHighRef.current);
      predHighRef.current = null;
    }
    if (!prediction || !prediction.found || !prediction.steps?.length) return;
    const baseDate = prediction.base_date!;
    const baseClose = prediction.base_close;
    if (!baseClose) return;
    const sorted = [...prediction.steps].sort((a, b) => a.horizon - b.horizon);

    const med: LineData[] = [
      { time: dateToUtcTs(baseDate), value: baseClose },
      ...sorted
        .filter((s) => s.point_close !== null)
        .map((s) => ({ time: dateToUtcTs(s.target_date), value: s.point_close as number })),
    ];
    const lo: LineData[] = [
      { time: dateToUtcTs(baseDate), value: baseClose },
      ...sorted
        .filter((s) => s.ci_low !== null)
        .map((s) => ({ time: dateToUtcTs(s.target_date), value: s.ci_low as number })),
    ];
    const hi: LineData[] = [
      { time: dateToUtcTs(baseDate), value: baseClose },
      ...sorted
        .filter((s) => s.ci_high !== null)
        .map((s) => ({ time: dateToUtcTs(s.target_date), value: s.ci_high as number })),
    ];

    const medLine = chartRef.current.addLineSeries({
      color: "#a78bfa",
      lineWidth: 2,
      lineStyle: 2, // dashed
      priceLineVisible: false,
      lastValueVisible: true,
      title: "예측 median",
    });
    medLine.setData(med);
    const loLine = chartRef.current.addLineSeries({
      color: "#7c3aed",
      lineWidth: 1,
      lineStyle: 1,
      priceLineVisible: false,
      lastValueVisible: false,
      title: "q10",
    });
    loLine.setData(lo);
    const hiLine = chartRef.current.addLineSeries({
      color: "#7c3aed",
      lineWidth: 1,
      lineStyle: 1,
      priceLineVisible: false,
      lastValueVisible: false,
      title: "q90",
    });
    hiLine.setData(hi);
    predRef.current = medLine;
    predLowRef.current = loLine;
    predHighRef.current = hiLine;
    chartRef.current.timeScale().fitContent();
  }, [prediction]);

  return (
    <div className="h-[460px] w-full rounded-md border border-zinc-800 bg-zinc-900/30 p-2">
      <div ref={containerRef} className="h-full w-full" />
    </div>
  );
}
