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; } 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 | null; } export const fetchPredictionAnalyses = async (params?: { search?: string; }): Promise => { const response = await api.get('/prediction/analyses', { params }); return response.data; }; export const fetchPredictionDetail = async (acdntSn: number): Promise => { const response = await api.get(`/prediction/analyses/${acdntSn}`); return response.data; }; export const fetchBacktrack = async (sn: number): Promise => { const response = await api.get(`/prediction/backtrack/${sn}`); return response.data; }; export const fetchBacktrackByAcdnt = async ( acdntSn: number, ): Promise => { const response = await api.get('/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; }): Promise<{ backtrackSn: number }> => { const response = await api.post<{ backtrackSn: number }>('/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; 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; 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; hydrDataByModel?: Record; summaryByModel?: Record; stepSummariesByModel?: Record; } export const fetchAnalysisTrajectory = async (acdntSn: number): Promise => { const response = await api.get(`/prediction/analyses/${acdntSn}/trajectory`); 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): Promise => { const formData = new FormData(); formData.append('image', file); const response = await api.post('/prediction/image-analyze', formData, { headers: { 'Content-Type': 'multipart/form-data' }, timeout: 330_000, }); return response.data; };