import { apiClient } from '../client' const PREFIX = '/api/soil' export interface SoilSummary { summaryKpis?: Record avg_soil_moisture?: Record anomalyDetectionCard?: Record soilMoistureHeatmap?: Record } interface ApiResponse { code: number msg: string data: T } interface StatusResponse { status: string data: T } type HeatmapPoint = { x: string y: number } type HeatmapSeries = { name: string data: HeatmapPoint[] } function extract(res: ApiResponse | StatusResponse | T): T { return res && typeof res === 'object' && 'data' in res ? (res as ApiResponse).data : (res as T) } function getNumericValue(value: unknown): number { if (typeof value === 'number' && Number.isFinite(value)) return value const parsed = Number(value) return Number.isFinite(parsed) ? parsed : 0 } function normalizeHeatmapSeries(data: Record): HeatmapSeries[] { const legacySeries = Array.isArray(data.series) ? (data.series as HeatmapSeries[]) : [] if (legacySeries.length > 0) return legacySeries const gridCells = Array.isArray(data.grid_cells) ? (data.grid_cells as Array>) : [] if (gridCells.length === 0) return [] const grouped = new Map() gridCells.forEach((cell, index) => { const rowLabel = String( cell.zone_name ?? cell.zone ?? cell.row_label ?? cell.row ?? cell.y_label ?? `ردیف ${index + 1}` ) const columnLabel = String( cell.time_label ?? cell.col_label ?? cell.column_label ?? cell.x_label ?? cell.col ?? cell.x ?? `${index + 1}` ) const rawValue = cell.value ?? cell.moisture ?? cell.moisture_percent ?? cell.intensity ?? cell.y const value = getNumericValue(rawValue) const current = grouped.get(rowLabel) ?? [] current.push({ x: columnLabel, y: value }) grouped.set(rowLabel, current) }) return Array.from(grouped.entries()).map(([name, points]) => ({ name, data: points })) } function buildHealthScoreKpi(summary: Record): Record { const healthScore = getNumericValue(summary.healthScore) const profileSource = String(summary.profileSource ?? 'مرجع خاک') const healthLanguage = summary.healthLanguage && typeof summary.healthLanguage === 'object' ? (summary.healthLanguage as Record) : {} const chipText = String(healthLanguage.short_chip_text ?? summary.avgSoilMoistureStatus ?? '-') let chipColor: 'success' | 'warning' | 'error' = 'success' if (healthScore < 45) chipColor = 'error' else if (healthScore < 70) chipColor = 'warning' return { id: 'soil_health_score', title: 'سلامت خاک', subtitle: profileSource, stats: `${Math.round(healthScore)} / 100`, avatarColor: chipColor === 'error' ? 'error' : chipColor === 'warning' ? 'warning' : 'success', avatarIcon: 'tabler-activity-heartbeat', chipText, chipColor } } export const soilService = { async getSummary(farmUuid: string): Promise { const res = await apiClient.get> | Record>( `${PREFIX}/summary/?farm_uuid=${encodeURIComponent(farmUuid)}` ) const data = extract(res) return { summaryKpis: { kpis: [buildHealthScoreKpi(data)] } } }, async getAvgMoisture(farmUuid: string): Promise> { const res = await apiClient.get> | Record>( `${PREFIX}/avg-moisture/?farm_uuid=${encodeURIComponent(farmUuid)}` ) const data = extract(res) return { kpis: [data] } }, async getAnomalies(farmUuid: string): Promise> { const res = await apiClient.get> | Record>( `${PREFIX}/anomalies/?farm_uuid=${encodeURIComponent(farmUuid)}` ) return extract(res) }, async getMoistureHeatmap(farmUuid: string): Promise> { const res = await apiClient.get> | Record>( `${PREFIX}/moisture-heatmap/?farm_uuid=${encodeURIComponent(farmUuid)}` ) const data = extract(res) return { ...data, series: normalizeHeatmapSeries(data) } }, }