import { useState, useRef, useEffect } from 'react';
import maplibregl from 'maplibre-gl';
import 'maplibre-gl/dist/maplibre-gl.css';
import { fetchSensitivityEvaluationGeojson } from '@components/prediction/services/predictionApi';
import type { OilSpillReportData } from '@interfaces/reports/ReportsInterface';
import { S, parseCoord, getSeasonKey, SENS_LEVELS } from '../OilSpillReportTemplate';

export function SensitivityMapSection({
  data,
  editing,
  onChange,
}: {
  data: OilSpillReportData;
  editing: boolean;
  onChange: (d: OilSpillReportData) => void;
}) {
  const mapContainerRef = useRef<HTMLDivElement>(null);
  const mapRef = useRef<maplibregl.Map | null>(null);
  const [mapVisible, setMapVisible] = useState(false);
  const [loading, setLoading] = useState(false);
  const [capturing, setCapturing] = useState(false);
  const acdntSn = data.acdntSn;

  const handleLoad = async () => {
    if (!acdntSn) return;
    setLoading(true);
    try {
      const geojson = await fetchSensitivityEvaluationGeojson(acdntSn);
      const seasonKey = getSeasonKey(data.incident.occurTime);

      // 레벨 계산 및 면적 집계 (레벨 1 제외)
      const areaByLevel: Record<number, number> = {};
      geojson.features.forEach((f) => {
        const p = (f as { properties: Record<string, unknown> }).properties;
        const lvl = Number(p[seasonKey] ?? 1);
        if (lvl >= 2) areaByLevel[lvl] = (areaByLevel[lvl] ?? 0) + Number(p['area_km2'] ?? 0);
      });
      const sensitivityRows = SENS_LEVELS.map((s) => ({
        level: s.level,
        color: s.color,
        area: areaByLevel[s.key] != null ? areaByLevel[s.key].toFixed(2) : '',
      }));
      onChange({ ...data, sensitivity: sensitivityRows });

      // 레벨 속성 추가 + 레벨 1 제외한 표시용 GeoJSON
      const displayGeojson = {
        ...geojson,
        features: geojson.features
          .map((f) => {
            const p = (f as { properties: Record<string, unknown> }).properties;
            return { ...(f as object), properties: { ...p, level: Number(p[seasonKey] ?? 1) } };
          })
          .filter((f) => (f as { properties: { level: number } }).properties.level >= 2),
      };

      setMapVisible(true);
      setTimeout(() => {
        if (!mapContainerRef.current) return;
        const map = new maplibregl.Map({
          container: mapContainerRef.current,
          style: 'https://basemaps.cartocdn.com/gl/positron-gl-style/style.json',
          center: [127.5, 35.5],
          zoom: 8,
          preserveDrawingBuffer: true,
        } as maplibregl.MapOptions);
        mapRef.current = map;
        map.on('load', () => {
          // eslint-disable-next-line @typescript-eslint/no-explicit-any
          map.addSource('sensitivity', { type: 'geojson', data: displayGeojson as any });
          const colorExpr: maplibregl.ExpressionSpecification = [
            'case',
            ['==', ['get', 'level'], 5],
            '#ef4444',
            ['==', ['get', 'level'], 4],
            '#f97316',
            ['==', ['get', 'level'], 3],
            '#eab308',
            ['==', ['get', 'level'], 2],
            '#22c55e',
            'transparent',
          ];
          map.addLayer({
            id: 'sensitivity-fill',
            type: 'fill',
            source: 'sensitivity',
            filter: ['==', '$type', 'Polygon'],
            paint: { 'fill-color': colorExpr, 'fill-opacity': 0.6 },
          });
          map.addLayer({
            id: 'sensitivity-line',
            type: 'line',
            source: 'sensitivity',
            filter: ['==', '$type', 'Polygon'],
            paint: { 'line-color': colorExpr, 'line-width': 0.5, 'line-opacity': 0.4 },
          });
          map.addLayer({
            id: 'sensitivity-circle',
            type: 'circle',
            source: 'sensitivity',
            filter: ['==', '$type', 'Point'],
            paint: { 'circle-radius': 5, 'circle-color': colorExpr },
          });

          // fitBounds
          const coords: [number, number][] = [];
          displayGeojson.features.forEach((f) => {
            const geom = (f as unknown as { geometry: { type: string; coordinates: unknown } }).geometry;
            if (geom.type === 'Point') coords.push(geom.coordinates as [number, number]);
            else if (geom.type === 'Polygon')
              (geom.coordinates as [number, number][][])[0]?.forEach((c) => coords.push(c));
            else if (geom.type === 'MultiPolygon')
              (geom.coordinates as [number, number][][][]).forEach((rings) =>
                rings[0]?.forEach((c) => coords.push(c)),
              );
          });
          if (coords.length > 0) {
            const lngs = coords.map((c) => c[0]);
            const lats = coords.map((c) => c[1]);
            map.fitBounds(
              [
                [Math.min(...lngs), Math.min(...lats)],
                [Math.max(...lngs), Math.max(...lats)],
              ],
              { padding: 60, maxZoom: 13 },
            );
          }
          // 사고 위치 마커 (캔버스 레이어 — 캡처에 포함)
          const incLat = parseCoord(data.incident.lat);
          const incLon = parseCoord(data.incident.lon);
          if (incLat != null && incLon != null) {
            map.addSource('incident-point', {
              type: 'geojson',
              data: {
                type: 'Feature',
                geometry: { type: 'Point', coordinates: [incLon, incLat] },
                properties: {},
              },
            });
            map.addLayer({
              id: 'incident-circle',
              type: 'circle',
              source: 'incident-point',
              paint: {
                'circle-radius': 7,
                'circle-color': '#ef4444',
                'circle-stroke-width': 2,
                'circle-stroke-color': '#ffffff',
              },
            });
            map.addLayer({
              id: 'incident-label',
              type: 'symbol',
              source: 'incident-point',
              layout: {
                'text-field': '사고위치',
                'text-size': 11,
                'text-offset': [0, 1.6],
                'text-anchor': 'top',
                'text-font': ['Open Sans Bold', 'Arial Unicode MS Bold'],
              },
              paint: {
                'text-color': '#ffffff',
                'text-halo-color': '#ef4444',
                'text-halo-width': 3,
              },
            });
          }
        });
      }, 100);
    } catch {
      alert('통합민감도 평가 데이터를 불러오지 못했습니다.');
    } finally {
      setLoading(false);
    }
  };

  const handleCapture = () => {
    const map = mapRef.current;
    if (!map) return;
    setCapturing(true);
    map.once('idle', () => {
      const dataUrl = map.getCanvas().toDataURL('image/png');
      onChange({ ...data, sensitivityMapImage: dataUrl });
      setCapturing(false);
    });
    map.triggerRepaint();
  };

  const handleReset = () => {
    if (mapRef.current) {
      mapRef.current.remove();
      mapRef.current = null;
    }
    setMapVisible(false);
    onChange({ ...data, sensitivityMapImage: undefined });
  };

  useEffect(() => {
    return () => {
      mapRef.current?.remove();
    };
  }, []);

  if (!editing) {
    if (data.sensitivityMapImage) {
      return (
        <img
          src={data.sensitivityMapImage}
          alt="통합민감도 평가 지도"
          style={{
            width: '100%',
            height: 'auto',
            display: 'block',
            border: '1px solid #ddd',
            borderRadius: 4,
            marginBottom: 16,
          }}
        />
      );
    }
    return <div style={S.mapPlaceholder}>통합민감도 평가 지도</div>;
  }

  if (!acdntSn) return <div style={S.mapPlaceholder}>통합민감도 평가 지도</div>;

  if (data.sensitivityMapImage) {
    return (
      <div style={{ position: 'relative' }}>
        <img
          src={data.sensitivityMapImage}
          alt="통합민감도 평가 지도"
          style={{
            width: '100%',
            height: 'auto',
            display: 'block',
            border: '1px solid #ddd',
            borderRadius: 4,
          }}
        />
        <button
          onClick={handleReset}
          style={{
            position: 'absolute',
            top: 8,
            right: 8,
            background: 'rgba(0,0,0,0.6)',
            color: '#fff',
            border: 'none',
            borderRadius: 4,
            padding: '3px 8px',
            fontSize: 11,
            cursor: 'pointer',
          }}
        >
          재캡처
        </button>
      </div>
    );
  }

  return (
    <div style={{ position: 'relative' }}>
      {!mapVisible ? (
        <div style={{ ...S.mapPlaceholder, flexDirection: 'column', gap: 8 }}>
          <span>민감도 분포(10km내) 지도</span>
          <button
            onClick={handleLoad}
            disabled={loading}
            style={{
              background: '#0891b2',
              color: '#fff',
              border: 'none',
              borderRadius: 4,
              padding: '5px 14px',
              fontSize: 12,
              cursor: loading ? 'not-allowed' : 'pointer',
              opacity: loading ? 0.7 : 1,
            }}
          >
            {loading ? '불러오는 중...' : '지도 불러오기'}
          </button>
        </div>
      ) : (
        <div style={{ position: 'relative' }}>
          <div
            ref={mapContainerRef}
            style={{ width: '100%', height: 440, borderRadius: 4, overflow: 'hidden' }}
          />
          <div style={{ display: 'flex', gap: 8, marginTop: 6, justifyContent: 'flex-end' }}>
            <button
              onClick={handleReset}
              style={{
                background: 'transparent',
                color: '#6b7280',
                border: '1px solid #374151',
                borderRadius: 4,
                padding: '3px 10px',
                fontSize: 11,
                cursor: 'pointer',
              }}
            >
              취소
            </button>
            <button
              onClick={handleCapture}
              disabled={capturing}
              style={{
                background: '#0891b2',
                color: '#fff',
                border: 'none',
                borderRadius: 4,
                padding: '3px 12px',
                fontSize: 11,
                cursor: capturing ? 'not-allowed' : 'pointer',
                opacity: capturing ? 0.7 : 1,
              }}
            >
              {capturing ? '캡처 중...' : '이 화면으로 캡처'}
            </button>
          </div>
        </div>
      )}
    </div>
  );
}
