import { api } from '@common/services/api';

export interface PredictionAnalysis {
  acdntSn: number;
  acdntNm: string;
  occurredAt: string;
  analysisDate: string;
  requestor: string;
  duration: string;
  oilType: string;
  volume: number | null;
  location: string;
  lat: number | null;
  lon: number | null;
  kospsStatus: string;
  poseidonStatus: string;
  opendriftStatus: string;
  backtrackStatus: string;
  analyst: string;
  officeName: string;
  acdntSttsCd: string;
  predRunSn: number | null;
  runDtm: string | null;
}

export interface PredictionDetail {
  acdnt: {
    acdntSn: number;
    acdntNm: string;
    occurredAt: string;
    lat: number | null;
    lon: number | null;
    location: string;
    analyst: string;
    officeName: string;
  };
  spill: {
    oilType: string;
    volume: number | null;
    unit: string;
    fcstHr: number | null;
  } | null;
  vessels: Array<{
    vesselInfoSn: number;
    imoNo: string;
    vesselNm: string;
    vesselTp: string;
    loaM: number | null;
    breadthM: number | null;
    draftM: number | null;
    gt: number | null;
    dwt: number | null;
    builtYr: number | null;
    flagCd: string;
    callsign: string;
    engineDc: string;
    insuranceData: unknown;
  }>;
  weather: Array<{
    obsDtm: string;
    locNm: string;
    temp: string;
    weatherDc: string;
    wind: string;
    wave: string;
    humid: string;
    vis: string;
    sst: string;
  }>;
}

export interface BacktrackResult {
  backtrackSn: number;
  acdntSn: number;
  estSpilDtm: string | null;
  anlysRange: string | null;
  lon: number | null;
  lat: number | null;
  srchRadiusNm: number | null;
  totalVessels: number | null;
  execSttsCd: string;
  rsltData: Record<string, unknown> | null;
}

export const fetchPredictionAnalyses = async (params?: {
  search?: string;
  acdntSn?: number;
}): Promise<PredictionAnalysis[]> => {
  const response = await api.get<PredictionAnalysis[]>('/prediction/analyses', { params });
  return response.data;
};

export const fetchPredictionDetail = async (acdntSn: number): Promise<PredictionDetail> => {
  const response = await api.get<PredictionDetail>(`/prediction/analyses/${acdntSn}`);
  return response.data;
};

export const fetchBacktrack = async (sn: number): Promise<BacktrackResult> => {
  const response = await api.get<BacktrackResult>(`/prediction/backtrack/${sn}`);
  return response.data;
};

export const fetchBacktrackByAcdnt = async (acdntSn: number): Promise<BacktrackResult | null> => {
  const response = await api.get<BacktrackResult[]>('/prediction/backtrack', {
    params: { acdntSn },
  });
  return response.data.length > 0 ? response.data[0] : null;
};

export const createBacktrack = async (input: {
  acdntSn: number;
  lon: number;
  lat: number;
  srchRadiusNm?: number;
  anlysRange?: string;
  estSpilDtm?: string;
}): Promise<BacktrackResult> => {
  const response = await api.post<BacktrackResult>('/prediction/backtrack', input);
  return response.data;
};

// ============================================================
// 확산 예측 시뮬레이션 (OpenDrift 연동)
// ============================================================

export interface SimulationRunResponse {
  success: boolean;
  execSn: number; // 하위 호환 유지 (첫 번째 모델의 execSn)
  execSns: Array<{ model: string; execSn: number }>;
  acdntSn: number | null;
  status: 'RUNNING';
}

export interface WindPoint {
  lat: number;
  lon: number;
  wind_speed: number;
  wind_direction: number;
}

export interface HydrGrid {
  lonInterval: number[];
  boundLonLat: { top: number; bottom: number; left: number; right: number };
  rows: number;
  cols: number;
  latInterval: number[];
}

export interface HydrDataStep {
  value: [number[][], number[][]]; // [u_2d, v_2d]
  grid: HydrGrid;
}

export interface CenterPoint {
  lat: number;
  lon: number;
  time: number;
  model?: string;
}

export interface OilParticle {
  lat: number;
  lon: number;
  time: number;
  particle?: number;
  stranded?: 0 | 1;
  model?: string;
}

export interface SimulationSummary {
  remainingVolume: number;
  weatheredVolume: number;
  evaporationVolume: number;
  dispersionVolume: number;
  pollutionArea: number;
  beachedVolume: number;
  pollutionCoastLength: number;
}

export interface SimulationStatusResponse {
  status: 'PENDING' | 'RUNNING' | 'DONE' | 'ERROR';
  progress?: number;
  trajectory?: OilParticle[];
  summary?: SimulationSummary;
  centerPoints?: CenterPoint[];
  windData?: WindPoint[][];
  hydrData?: (HydrDataStep | null)[];
  error?: string;
}

export interface RunModelSyncResult {
  model: string;
  execSn: number;
  status: 'DONE' | 'ERROR';
  trajectory?: OilParticle[];
  summary?: SimulationSummary;
  stepSummaries?: SimulationSummary[];
  centerPoints?: CenterPoint[];
  windData?: WindPoint[][];
  hydrData?: (HydrDataStep | null)[];
  error?: string;
}

export interface RunModelSyncResponse {
  success: boolean;
  acdntSn: number | null;
  execSns: Array<{ model: string; execSn: number }>;
  results: RunModelSyncResult[];
}

export interface TrajectoryResponse {
  trajectory: OilParticle[] | null;
  summary: SimulationSummary | null;
  centerPoints?: CenterPoint[];
  windDataByModel?: Record<string, WindPoint[][]>;
  hydrDataByModel?: Record<string, (HydrDataStep | null)[]>;
  summaryByModel?: Record<string, SimulationSummary>;
  stepSummariesByModel?: Record<string, SimulationSummary[]>;
}

export const fetchAnalysisTrajectory = async (
  acdntSn: number,
  predRunSn?: number,
): Promise<TrajectoryResponse> => {
  const response = await api.get<TrajectoryResponse>(
    `/prediction/analyses/${acdntSn}/trajectory`,
    predRunSn != null ? { params: { predRunSn } } : undefined,
  );
  return response.data;
};

export interface SensitiveResourceCategory {
  category: string;
  count: number;
  totalArea: number | null;
}

export const fetchSensitiveResources = async (
  acdntSn: number,
): Promise<SensitiveResourceCategory[]> => {
  const response = await api.get<SensitiveResourceCategory[]>(
    `/prediction/analyses/${acdntSn}/sensitive-resources`,
  );
  return response.data;
};

export interface SensitiveResourceFeature {
  type: 'Feature';
  geometry: { type: string; coordinates: unknown };
  properties: {
    srId: number;
    category: string;
    [key: string]: unknown;
  };
}

export interface SensitiveResourceFeatureCollection {
  type: 'FeatureCollection';
  features: SensitiveResourceFeature[];
}

export const fetchSensitiveResourcesGeojson = async (
  acdntSn: number,
): Promise<SensitiveResourceFeatureCollection> => {
  const response = await api.get<SensitiveResourceFeatureCollection>(
    `/prediction/analyses/${acdntSn}/sensitive-resources/geojson`,
  );
  return response.data;
};

export interface SpreadParticlesGeojson {
  type: 'FeatureCollection';
  features: Array<{
    type: 'Feature';
    geometry: { type: 'Point'; coordinates: [number, number] };
    properties: { model: string; time: number; stranded: 0 | 1; isLastStep: boolean };
  }>;
  maxStep: number;
}

export const fetchPredictionParticlesGeojson = async (
  acdntSn: number,
): Promise<SpreadParticlesGeojson> => {
  const response = await api.get<SpreadParticlesGeojson>(
    `/prediction/analyses/${acdntSn}/spread-particles`,
  );
  return response.data;
};

export const fetchSensitivityEvaluationGeojson = async (
  acdntSn: number,
): Promise<{ type: 'FeatureCollection'; features: unknown[] }> => {
  const response = await api.get<{ type: 'FeatureCollection'; features: unknown[] }>(
    `/prediction/analyses/${acdntSn}/sensitivity-evaluation`,
  );
  return response.data;
};

// ============================================================
// 이미지 업로드 분석
// ============================================================

export interface ImageAnalyzeResult {
  acdntSn: number;
  lat: number;
  lon: number;
  oilType: string;
  area: number;
  volume: number;
  fileId: string;
  occurredAt: string;
}

export const analyzeImage = async (file: File, acdntNm?: string): Promise<ImageAnalyzeResult> => {
  const formData = new FormData();
  formData.append('image', file);
  if (acdntNm?.trim()) formData.append('acdntNm', acdntNm.trim());
  const response = await api.post<ImageAnalyzeResult>('/prediction/image-analyze', formData, {
    headers: { 'Content-Type': 'multipart/form-data' },
    timeout: 330_000,
  });
  return response.data;
};

// ============================================================
// GSC 외부 수집 사고 목록 (확산 예측 입력 셀렉트용)
// ============================================================

export interface GscAccidentListItem {
  acdntMngNo: string;
  pollNm: string;
  pollDate: string | null;
  lat: number | null;
  lon: number | null;
}

export const fetchGscAccidents = async (): Promise<GscAccidentListItem[]> => {
  const response = await api.get<GscAccidentListItem[]>('/gsc/accidents');
  return response.data;
};
