import { useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import {
  LineChart,
  Line,
  XAxis,
  YAxis,
  CartesianGrid,
  Tooltip,
  ResponsiveContainer,
  ScatterChart,
  Scatter,
  ZAxis,
  Cell,
} from 'recharts';
import type { SeismicDto, PressureDto } from '../../services/sensorApi';

interface Props {
  seismicData: SeismicDto[];
  pressureData: PressureDto[];
  currentTime: number;
  historyMinutes: number;
}

const MINUTE = 60_000;
const BUCKET_COUNT = 48;

function formatTickTime(epoch: number): string {
  const d = new Date(epoch);
  const pad = (n: number) => String(n).padStart(2, '0');
  return `${pad(d.getMonth() + 1)}/${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}`;
}

function buildTicks(currentTime: number, historyMinutes: number): number[] {
  const interval = historyMinutes * MINUTE;
  const ticks: number[] = [];
  for (let i = 8; i >= 0; i--) {
    ticks.push(currentTime - i * interval);
  }
  return ticks;
}

/**
 * 지진 데이터: 버킷이 아닌 실제 이벤트 포인트로 변환
 */
function prepareSeismicPoints(
  data: SeismicDto[],
  rangeStart: number,
  rangeEnd: number,
): { time: number; magnitude: number; place: string }[] {
  return data
    .filter(ev => ev.timestamp >= rangeStart && ev.timestamp <= rangeEnd)
    .map(ev => ({ time: ev.timestamp, magnitude: ev.magnitude, place: ev.place }));
}

/**
 * 기압 데이터: 관측소별 시간순 포인트 (버킷 없이 원본 사용)
 * connectNulls 대신, 데이터가 있는 포인트만 연결
 */
function preparePressureByStation(
  data: PressureDto[],
  rangeStart: number,
  rangeEnd: number,
): Record<string, { time: number; value: number }[]> {
  const byStation: Record<string, { time: number; value: number }[]> = {};
  for (const r of data) {
    if (r.timestamp < rangeStart || r.timestamp > rangeEnd) continue;
    if (!byStation[r.station]) byStation[r.station] = [];
    byStation[r.station].push({ time: r.timestamp, value: r.pressureHpa });
  }
  // 시간순 정렬
  for (const arr of Object.values(byStation)) {
    arr.sort((a, b) => a.time - b.time);
  }
  return byStation;
}

function generateDemoData(
  rangeStart: number,
  rangeEnd: number,
  baseValue: number,
  variance: number,
): { time: number; value: number }[] {
  const bucketSize = (rangeEnd - rangeStart) / BUCKET_COUNT;
  return Array.from({ length: BUCKET_COUNT }, (_, i) => {
    const t = rangeStart + (i + 0.5) * bucketSize;
    const seed = Math.sin(t / 100_000) * 10000;
    const noise = (seed - Math.floor(seed)) * 2 - 1;
    return { time: t, value: Math.max(0, baseValue + noise * variance) };
  });
}

const STATION_COLORS: Record<string, string> = {
  'tehran': '#ef4444',
  'isfahan': '#f97316',
  'bandar-abbas': '#3b82f6',
  'shiraz': '#22c55e',
  'tabriz': '#a855f7',
};

const MAGNITUDE_COLORS = ['#fbbf24', '#f97316', '#ef4444', '#dc2626', '#991b1b'];
function getMagnitudeColor(mag: number): string {
  if (mag < 2.5) return MAGNITUDE_COLORS[0];
  if (mag < 3.5) return MAGNITUDE_COLORS[1];
  if (mag < 4.5) return MAGNITUDE_COLORS[2];
  if (mag < 5.5) return MAGNITUDE_COLORS[3];
  return MAGNITUDE_COLORS[4];
}

export function SensorChart({ seismicData, pressureData, currentTime, historyMinutes }: Props) {
  const { t } = useTranslation();

  const totalMinutes = historyMinutes * 8;
  const rangeStart = currentTime - totalMinutes * MINUTE;
  const rangeEnd = currentTime;

  const ticks = useMemo(() => buildTicks(currentTime, historyMinutes), [currentTime, historyMinutes]);

  const seismicPoints = useMemo(
    () => prepareSeismicPoints(seismicData, rangeStart, rangeEnd),
    [seismicData, rangeStart, rangeEnd],
  );

  const pressureByStation = useMemo(
    () => preparePressureByStation(pressureData, rangeStart, rangeEnd),
    [pressureData, rangeStart, rangeEnd],
  );

  const noiseChart = useMemo(
    () => generateDemoData(rangeStart, rangeEnd, 45, 30),
    [rangeStart, rangeEnd],
  );
  const radiationChart = useMemo(
    () => generateDemoData(rangeStart, rangeEnd, 0.08, 0.06),
    [rangeStart, rangeEnd],
  );

  const commonXAxis = {
    type: 'number' as const,
    domain: [rangeStart, rangeEnd] as [number, number],
    ticks,
    tickFormatter: formatTickTime,
    tick: { fontSize: 9, fill: '#888' },
  };

  // 지진 y축: 데이터가 있으면 0~max+1, 없으면 0~6
  const maxMag = seismicPoints.length > 0
    ? Math.max(...seismicPoints.map(p => p.magnitude))
    : 0;
  const seismicYMax = Math.max(maxMag + 1, 6);

  return (
    <div className="sensor-chart">
      <h3>{t('sensor.title')}</h3>
      <div className="chart-grid">
        {/* 지진파: Scatter (이벤트 점) */}
        <div className="chart-item">
          <h4>
            {t('sensor.seismicActivity')}
            {seismicPoints.length > 0 && (
              <span className="text-[9px] text-kcg-muted ml-1">
                ({seismicPoints.length} events)
              </span>
            )}
          </h4>
          <ResponsiveContainer width="100%" height={80}>
            <ScatterChart>
              <CartesianGrid strokeDasharray="3 3" stroke="#333" />
              <XAxis dataKey="time" {...commonXAxis} />
              <YAxis dataKey="magnitude" domain={[0, seismicYMax]} tick={{ fontSize: 10, fill: '#888' }} name="M" />
              <ZAxis dataKey="magnitude" range={[30, 200]} name="Size" />
              <Tooltip
                contentStyle={{ background: '#1a1a2e', border: '1px solid #333', fontSize: 10 }}
                labelFormatter={formatTickTime}
                formatter={(v: number, name: string) => {
                  if (name === 'M') return [`M${v.toFixed(1)}`, 'Magnitude'];
                  return [v, name];
                }}
              />
              <Scatter data={seismicPoints} shape="circle">
                {seismicPoints.map((p, i) => (
                  <Cell key={i} fill={getMagnitudeColor(p.magnitude)} />
                ))}
              </Scatter>
            </ScatterChart>
          </ResponsiveContainer>
        </div>

        {/* 기압: 관측소별 개별 라인 */}
        <div className="chart-item">
          <h4>{t('sensor.airPressureHpa')}</h4>
          <ResponsiveContainer width="100%" height={80}>
            <LineChart>
              <CartesianGrid strokeDasharray="3 3" stroke="#333" />
              <XAxis dataKey="time" {...commonXAxis} />
              <YAxis domain={['auto', 'auto']} tick={{ fontSize: 10, fill: '#888' }} />
              <Tooltip
                contentStyle={{ background: '#1a1a2e', border: '1px solid #333', fontSize: 10 }}
                labelFormatter={formatTickTime}
                formatter={(v: number, name: string) => [`${v.toFixed(1)} hPa`, name]}
              />
              {Object.entries(pressureByStation).map(([station, points]) => (
                <Line
                  key={station}
                  data={points}
                  dataKey="value"
                  name={station}
                  stroke={STATION_COLORS[station] || '#888'}
                  dot={false}
                  strokeWidth={1.2}
                  connectNulls
                  isAnimationActive={false}
                />
              ))}
            </LineChart>
          </ResponsiveContainer>
        </div>

        <div className="chart-item">
          <h4>
            {t('sensor.noiseLevelDb')}{' '}
            <span className="chart-demo-label">(DEMO)</span>
          </h4>
          <ResponsiveContainer width="100%" height={80}>
            <LineChart data={noiseChart}>
              <CartesianGrid strokeDasharray="3 3" stroke="#333" />
              <XAxis dataKey="time" {...commonXAxis} />
              <YAxis domain={[0, 140]} tick={{ fontSize: 10, fill: '#888' }} />
              <Tooltip
                contentStyle={{ background: '#1a1a2e', border: '1px solid #333' }}
                labelFormatter={formatTickTime}
                formatter={(v: number) => [v.toFixed(1), 'dB']}
              />
              <Line type="monotone" dataKey="value" stroke="#f97316" dot={false} strokeWidth={1.5} />
            </LineChart>
          </ResponsiveContainer>
        </div>

        <div className="chart-item">
          <h4>
            {t('sensor.radiationUsv')}{' '}
            <span className="chart-demo-label">(DEMO)</span>
          </h4>
          <ResponsiveContainer width="100%" height={80}>
            <LineChart data={radiationChart}>
              <CartesianGrid strokeDasharray="3 3" stroke="#333" />
              <XAxis dataKey="time" {...commonXAxis} />
              <YAxis domain={[0, 0.3]} tick={{ fontSize: 10, fill: '#888' }} />
              <Tooltip
                contentStyle={{ background: '#1a1a2e', border: '1px solid #333' }}
                labelFormatter={formatTickTime}
                formatter={(v: number) => [v.toFixed(3), 'μSv/h']}
              />
              <Line type="monotone" dataKey="value" stroke="#22c55e" dot={false} strokeWidth={1.5} />
            </LineChart>
          </ResponsiveContainer>
        </div>
      </div>
    </div>
  );
}
