// data.go.kr 기상청 해양기상 API 서비스

// API Key를 환경변수에서 로드 (소스코드 노출 방지)
const API_KEY = import.meta.env.VITE_DATA_GO_KR_API_KEY || '';

// API 베이스 URL
const BASE_URL = 'https://apis.data.go.kr/1360000/VilageFcstInfoService_2.0';
const MARINE_BASE_URL = 'https://apis.data.go.kr/1360000/SeaFcstInfoService';

export interface WeatherForecastData {
  baseDate: string;
  baseTime: string;
  fcstDate: string;
  fcstTime: string;
  temperature: number;
  windSpeed: number;
  windDirection: number;
  waveHeight: number;
  precipitation: number;
  humidity: number;
}

export interface MarineWeatherData {
  regId: string; // 구역 ID
  regName: string; // 구역명
  waveHeight: number; // 파고 (m)
  windSpeed: number; // 풍속 (m/s)
  windDirection: string; // 풍향
  temperature: number; // 수온 (°C)
}

/**
 * 초단기 실황 조회
 * 기상청 단기예보 API
 */
export async function getUltraShortForecast(
  nx: number,
  ny: number,
  baseDate: string,
  baseTime: string,
): Promise<WeatherForecastData[]> {
  try {
    const params = new URLSearchParams({
      serviceKey: API_KEY,
      pageNo: '1',
      numOfRows: '100',
      dataType: 'JSON',
      base_date: baseDate,
      base_time: baseTime,
      nx: nx.toString(),
      ny: ny.toString(),
    });

    const response = await fetch(`${BASE_URL}/getUltraSrtFcst?${params}`);
    if (!response.ok) {
      throw new Error(`HTTP ${response.status}: ${response.statusText}`);
    }
    const data = await response.json();

    if (data.response?.header?.resultCode !== '00') {
      throw new Error(`API Error: ${data.response?.header?.resultMsg}`);
    }

    const items = data.response?.body?.items?.item || [];

    // 데이터를 시간대별로 그룹화
    const forecasts: WeatherForecastData[] = [];
    const grouped = new Map<string, Record<string, unknown>>();

    items.forEach((item: Record<string, string>) => {
      const key = `${item.fcstDate}-${item.fcstTime}`;
      if (!grouped.has(key)) {
        grouped.set(key, {
          baseDate: item.baseDate,
          baseTime: item.baseTime,
          fcstDate: item.fcstDate,
          fcstTime: item.fcstTime,
          temperature: 0,
          windSpeed: 0,
          windDirection: 0,
          waveHeight: 0,
          precipitation: 0,
          humidity: 0,
        });
      }

      const forecast = grouped.get(key);

      // 카테고리별 값 매핑
      switch (item.category) {
        case 'T1H': // 기온
          forecast.temperature = parseFloat(item.fcstValue);
          break;
        case 'WSD': // 풍속
          forecast.windSpeed = parseFloat(item.fcstValue);
          break;
        case 'VEC': // 풍향
          forecast.windDirection = parseFloat(item.fcstValue);
          break;
        case 'WAV': // 파고
          forecast.waveHeight = parseFloat(item.fcstValue);
          break;
        case 'RN1': // 1시간 강수량
          forecast.precipitation = parseFloat(item.fcstValue);
          break;
        case 'REH': // 습도
          forecast.humidity = parseFloat(item.fcstValue);
          break;
      }
    });

    grouped.forEach((value) => forecasts.push(value));
    return forecasts;
  } catch (error) {
    console.error('초단기 실황 조회 오류:', error);
    throw error;
  }
}

/**
 * 해상 예보 조회
 * 기상청 해상예보 API
 */
export async function getMarineForecast(
  regId: string,
  tmFc: string,
): Promise<MarineWeatherData | null> {
  try {
    const params = new URLSearchParams({
      serviceKey: API_KEY,
      pageNo: '1',
      numOfRows: '10',
      dataType: 'JSON',
      regId: regId, // 해역 구역 ID
      tmFc: tmFc, // 발표시각 (YYYYMMDDHH24)
    });

    const response = await fetch(`${MARINE_BASE_URL}/getWthrWrnList?${params}`);
    if (!response.ok) {
      throw new Error(`HTTP ${response.status}: ${response.statusText}`);
    }
    const data = await response.json();

    if (data.response?.header?.resultCode !== '00') {
      console.error('API Error:', data.response?.header?.resultMsg);
      return null;
    }

    const item = data.response?.body?.items?.item?.[0];
    if (!item) return null;

    return {
      regId: item.regId,
      regName: item.regName || '',
      waveHeight: parseFloat(item.waveHeight || '0'),
      windSpeed: parseFloat(item.windSpeed || '0'),
      windDirection: item.windDirection || '',
      temperature: parseFloat(item.temperature || '0'),
    };
  } catch (error) {
    console.error('해상 예보 조회 오류:', error);
    return null;
  }
}

/**
 * 지역 좌표를 격자 좌표로 변환
 * 기상청 API는 격자 좌표(nx, ny)를 사용
 */
export function convertToGridCoords(lat: number, lon: number): { nx: number; ny: number } {
  // 기상청 격자 변환 공식
  const RE = 6371.00877; // 지구 반경(km)
  const GRID = 5.0; // 격자 간격(km)
  const SLAT1 = 30.0; // 표준위도1(degree)
  const SLAT2 = 60.0; // 표준위도2(degree)
  const OLON = 126.0; // 기준점 경도(degree)
  const OLAT = 38.0; // 기준점 위도(degree)
  const XO = 43; // 기준점 X좌표(GRID)
  const YO = 136; // 기준점 Y좌표(GRID)

  const DEGRAD = Math.PI / 180.0;
  const re = RE / GRID;
  const slat1 = SLAT1 * DEGRAD;
  const slat2 = SLAT2 * DEGRAD;
  const olon = OLON * DEGRAD;
  const olat = OLAT * DEGRAD;

  let sn = Math.tan(Math.PI * 0.25 + slat2 * 0.5) / Math.tan(Math.PI * 0.25 + slat1 * 0.5);
  sn = Math.log(Math.cos(slat1) / Math.cos(slat2)) / Math.log(sn);
  let sf = Math.tan(Math.PI * 0.25 + slat1 * 0.5);
  sf = (Math.pow(sf, sn) * Math.cos(slat1)) / sn;
  let ro = Math.tan(Math.PI * 0.25 + olat * 0.5);
  ro = (re * sf) / Math.pow(ro, sn);

  let ra = Math.tan(Math.PI * 0.25 + lat * DEGRAD * 0.5);
  ra = (re * sf) / Math.pow(ra, sn);
  let theta = lon * DEGRAD - olon;
  if (theta > Math.PI) theta -= 2.0 * Math.PI;
  if (theta < -Math.PI) theta += 2.0 * Math.PI;
  theta *= sn;

  const nx = Math.floor(ra * Math.sin(theta) + XO + 0.5);
  const ny = Math.floor(ro - ra * Math.cos(theta) + YO + 0.5);

  return { nx, ny };
}

/**
 * 현재 날짜/시간을 API 형식으로 변환
 */
export function getCurrentBaseDateTime(): { baseDate: string; baseTime: string } {
  const now = new Date();
  const year = now.getFullYear();
  const month = String(now.getMonth() + 1).padStart(2, '0');
  const day = String(now.getDate()).padStart(2, '0');
  const hour = now.getHours();

  // 기상청 API는 매시 30분에 발표
  // 현재 시각이 30분 이전이면 이전 시간 데이터 사용
  const minutes = now.getMinutes();
  let baseHour = hour;
  if (minutes < 30) {
    baseHour = hour - 1;
    if (baseHour < 0) baseHour = 23;
  }

  const baseDate = `${year}${month}${day}`;
  const baseTime = String(baseHour).padStart(2, '0') + '00';

  return { baseDate, baseTime };
}

/**
 * 해역 구역 ID 매핑
 * 주요 해역별 ID
 */
export const MARINE_REGIONS = {
  서해중부: '1100000000',
  서해남부: '1200000000',
  제주도해상: '1300000000',
  남해서부: '2100000000',
  남해동부: '2200000000',
  동해중부: '3100000000',
  동해남부: '3200000000',
};

/**
 * 좌표에 가장 가까운 해역 구역 찾기
 */
export function findNearestMarineRegion(lat: number, lon: number): string {
  // 간단한 매핑 (실제로는 더 정교한 로직 필요)
  if (lat >= 37 && lon <= 127) return MARINE_REGIONS.서해중부;
  if (lat < 37 && lat >= 35 && lon <= 126.5) return MARINE_REGIONS.서해남부;
  if (lat < 35 && lon >= 126 && lon <= 127) return MARINE_REGIONS.제주도해상;
  if (lat >= 34 && lat < 36 && lon >= 127 && lon <= 128.5) return MARINE_REGIONS.남해서부;
  if (lat >= 34 && lat < 36 && lon > 128.5) return MARINE_REGIONS.남해동부;
  if (lat >= 36 && lon >= 129) return MARINE_REGIONS.동해중부;
  if (lat < 36 && lon >= 129) return MARINE_REGIONS.동해남부;

  return MARINE_REGIONS.서해중부; // 기본값
}
