// ─── Types ────────────────────────────────────────────────────────────────────

export type ReadingType =
  | "BP"
  | "Heart Rate"
  | "SpO2"
  | "Glucose"
  | "Weight"
  | "Temperature"
  | "HRV"
  | "Sleep";

export interface Reading {
  id: string;
  date: string;           // YYYY-MM-DD
  time: string;           // HH:MM
  patientName: string;
  readingType: ReadingType;
  context: string;
  deviceMethod: string;
  systolicBP?: number | null;
  diastolicBP?: number | null;
  heartRate?: number | null;
  spo2?: number | null;
  bloodGlucose?: number | null;
  weightKg?: number | null;
  weightLb?: number | null;
  temperatureF?: number | null;
  temperatureC?: number | null;
  hrv?: number | null;
  sleepHours?: number | null;
  notes: string;
  alertStatus: string;
}

export interface AgpSummary {
  avg?: string | null;
  gmi?: string | null;
  tir?: string | null;
  var?: string | null;
  date?: string;
  status?: string;
}

export interface AgpThresholds {
  tir_green_min: number;
  tir_yellow_min: number;
  gmi_green_max: number;
  gmi_yellow_max: number;
  var_green_max: number;
  var_yellow_max: number;
}

export interface UserProfile {
  name: string;
  pin: string;
}

// ─── Constants ────────────────────────────────────────────────────────────────

export const CATEGORY_DISPLAY: Record<string, string> = {
  BP:          "Blood Pressure",
  "Heart Rate": "Heart Rate",
  SpO2:        "Blood Oxygen",
  Glucose:     "Blood Glucose",
  Weight:      "Body Weight",
  Temperature: "Temperature",
  HRV:         "Heart Rate Variability",
  Sleep:       "Sleep",
  AGP:         "AGP Report",
};

export const CATEGORY_ICONS: Record<string, string> = {
  BP:          "🫀",
  "Heart Rate": "💓",
  SpO2:        "🫁",
  Glucose:     "🩸",
  Weight:      "⚖️",
  Temperature: "🌡️",
  HRV:         "📊",
  Sleep:       "😴",
  AGP:         "📈",
};

export const CATEGORY_UNIT: Record<string, string> = {
  BP:          "mmHg",
  "Heart Rate": "BPM",
  SpO2:        "%",
  Glucose:     "mg/dL",
  Weight:      "kg / lb",
  Temperature: "°F",
  HRV:         "ms",
  Sleep:       "hrs",
  AGP:         "CGM summary",
};

export const CATEGORY_ORDER: ReadingType[] = [
  "BP", "Heart Rate", "SpO2", "Glucose", "Weight", "Temperature", "HRV", "Sleep",
];

export const DASHBOARD_ORDER = [
  "BP", "Heart Rate", "SpO2", "Glucose", "Weight", "Temperature", "AGP", "Sleep",
] as const;

export const CONTEXTS = [
  "", "Fasting", "Post-Meal", "Resting", "Active",
  "Before Sleep", "After Exercise", "CGM Import",
];

export const METHODS = [
  "", "Manual", "Bluetooth Device", "Imported Device", "Scale",
  "Oximeter", "BP Cuff", "Glucose Meter", "Smart Ring", "Wearable",
];

export const REQUIRED_MAP: Record<ReadingType, string[]> = {
  BP:          ["systolicBP", "diastolicBP"],
  "Heart Rate": ["heartRate"],
  SpO2:        ["spo2"],
  Glucose:     ["bloodGlucose"],
  Weight:      ["weightKg"],
  Temperature: ["temperatureF"],
  HRV:         ["hrv"],
  Sleep:       ["sleepHours"],
};

export const GUIDANCE: Record<ReadingType, string> = {
  BP:          "Enter systolic and diastolic pressure in mmHg.",
  "Heart Rate": "Enter heart rate in BPM. Add context such as Resting or After Exercise.",
  SpO2:        "Enter blood oxygen percentage. Heart Rate is optional if your oximeter provides both.",
  Glucose:     "Enter blood glucose in mg/dL. Always note context — Fasting vs Post-Meal matters.",
  Weight:      "Enter weight in kg — pounds are calculated automatically.",
  Temperature: "Enter temperature in °F — Celsius is calculated automatically.",
  HRV:         "Enter Heart Rate Variability in milliseconds.",
  Sleep:       "Enter total sleep duration in hours.",
};

export const DEFAULT_AGP_THRESHOLDS: AgpThresholds = {
  tir_green_min: 70,
  tir_yellow_min: 55,
  gmi_green_max: 7.0,
  gmi_yellow_max: 8.0,
  var_green_max: 36.0,
  var_yellow_max: 42.0,
};

// ─── Alert computation ────────────────────────────────────────────────────────

export function computeAlert(r: Partial<Reading>): string {
  const alerts: string[] = [];
  const sys = r.systolicBP;
  const dia = r.diastolicBP;
  const hr  = r.heartRate;
  const spo2 = r.spo2;
  const glucose = r.bloodGlucose;
  const tempF = r.temperatureF;

  if ((sys != null && sys >= 180) || (dia != null && dia >= 120)) alerts.push("Critical BP");
  else if ((sys != null && sys >= 140) || (dia != null && dia >= 90)) alerts.push("High BP");
  if (hr != null && (hr < 50 || hr > 120)) alerts.push("Heart Rate");
  if (spo2 != null && spo2 < 92) alerts.push("Low Blood Oxygen");
  if (glucose != null && (glucose < 70 || glucose > 180)) alerts.push("Glucose");
  if (tempF != null && tempF >= 100.4) alerts.push("Temp");
  return alerts.length === 0 ? "OK" : alerts.join(", ");
}

export type AlertSeverity = "Normal" | "Warning" | "Critical";

export function alertStyle(alertText: string): { severity: AlertSeverity; color: string; bg: string } {
  const txt = (alertText || "").toLowerCase();
  if (txt.includes("critical")) return { severity: "Critical", color: "#f87171", bg: "#fee2e2" };
  if (txt !== "ok" && txt.trim()) return { severity: "Warning", color: "#fbbf24", bg: "#fef3c7" };
  return { severity: "Normal", color: "#4ade80", bg: "#dcfce7" };
}

// ─── Reading value summary ────────────────────────────────────────────────────

export function readingValueSummary(r: Reading): string {
  switch (r.readingType) {
    case "BP":
      return `${r.systolicBP ?? ""}/${r.diastolicBP ?? ""} mmHg`;
    case "Heart Rate":
      return r.heartRate != null ? `${r.heartRate} BPM` : "";
    case "SpO2": {
      const spo2 = r.spo2 != null ? `${r.spo2}%` : "";
      const hr   = r.heartRate != null ? `  HR ${r.heartRate} BPM` : "";
      return spo2 + hr;
    }
    case "Glucose":
      return r.bloodGlucose != null ? `${r.bloodGlucose} mg/dL` : "";
    case "Weight": {
      const kg = r.weightKg != null ? `${r.weightKg} kg` : "";
      const lb = r.weightLb != null ? ` / ${r.weightLb} lb` : "";
      return kg + lb;
    }
    case "Temperature":
      return r.temperatureF != null ? `${r.temperatureF} °F` : "";
    case "HRV":
      return r.hrv != null ? `${r.hrv} ms` : "";
    case "Sleep":
      return r.sleepHours != null ? `${r.sleepHours} hrs` : "";
    default:
      return "";
  }
}

// ─── Trend direction ──────────────────────────────────────────────────────────

export function metricForTrend(r: Reading): number | null {
  switch (r.readingType) {
    case "BP": {
      const vals = [r.systolicBP, r.diastolicBP].filter((v): v is number => v != null);
      return vals.length ? vals.reduce((a, b) => a + b, 0) / vals.length : null;
    }
    case "Heart Rate":  return r.heartRate ?? null;
    case "SpO2":        return r.spo2 ?? null;
    case "Glucose":     return r.bloodGlucose ?? null;
    case "Weight":      return r.weightKg ?? null;
    case "Temperature": return r.temperatureF ?? null;
    case "HRV":         return r.hrv ?? null;
    case "Sleep":       return r.sleepHours ?? null;
    default: return null;
  }
}

export function trendDirection(
  cat: string,
  current: number | null,
  previous: number | null,
): { arrow: string; word: string } {
  if (current == null || previous == null) return { arrow: "→", word: "Stable" };
  const diff = current - previous;
  if (Math.abs(diff) < 0.01) return { arrow: "→", word: "Stable" };
  const improvingUp = ["SpO2", "HRV", "Sleep"].includes(cat);
  if (improvingUp) return diff > 0 ? { arrow: "↑", word: "Improving" } : { arrow: "↓", word: "Worsening" };
  return diff < 0 ? { arrow: "↓", word: "Improving" } : { arrow: "↑", word: "Worsening" };
}

// ─── AGP status ───────────────────────────────────────────────────────────────

export function agpStatusAndSummary(
  agp: AgpSummary | null,
  thresholds: AgpThresholds = DEFAULT_AGP_THRESHOLDS,
) {
  const toFloat = (v: string | null | undefined) => {
    if (v == null || v === "") return null;
    const n = parseFloat(v);
    return isNaN(n) ? null : n;
  };

  const avg = toFloat(agp?.avg);
  const gmi = toFloat(agp?.gmi);
  const tir = toFloat(agp?.tir);
  const varVal = toFloat(agp?.var);

  if (tir == null && gmi == null && varVal == null && avg == null) {
    return {
      label: "Not Imported",
      short: "No AGP summary available",
      color: "muted" as const,
      detail: "Import a LibreView AGP/CGM PDF to calculate a plain-language summary.",
    };
  }

  const redReasons: string[] = [];
  const yellowChecks: string[] = [];
  const greenChecks: string[] = [];

  if (tir != null) {
    if (tir >= thresholds.tir_green_min) greenChecks.push("time in range is at or above target");
    else if (tir >= thresholds.tir_yellow_min) yellowChecks.push("time in range is below target");
    else redReasons.push("time in range is low");
  }
  if (gmi != null) {
    if (gmi <= thresholds.gmi_green_max) greenChecks.push("GMI is in a favorable range");
    else if (gmi <= thresholds.gmi_yellow_max) yellowChecks.push("GMI is elevated");
    else redReasons.push("GMI is high");
  }
  if (varVal != null) {
    if (varVal <= thresholds.var_green_max) greenChecks.push("glucose variability is controlled");
    else if (varVal <= thresholds.var_yellow_max) yellowChecks.push("glucose variability is moderately elevated");
    else redReasons.push("glucose variability is high");
  }

  if (redReasons.length > 0) {
    return {
      label: "Red / Review",
      short: "Review AGP pattern",
      color: "crit" as const,
      detail: redReasons.map(r => r.charAt(0).toUpperCase() + r.slice(1)).join("; ") + ".",
    };
  }
  if (yellowChecks.length > 0) {
    return {
      label: "Yellow / Watch",
      short: "Watch AGP trend",
      color: "warn" as const,
      detail: yellowChecks.map(r => r.charAt(0).toUpperCase() + r.slice(1)).join("; ") + ".",
    };
  }
  return {
    label: "Green / Stable",
    short: "Stable AGP pattern",
    color: "ok" as const,
    detail: "Available AGP markers are within the preferred tracking range.",
  };
}

// ─── Auto-calc helpers ────────────────────────────────────────────────────────

export function kgToLb(kg: number): number {
  return Math.round(kg * 2.20462 * 10) / 10;
}

export function fToC(f: number): number {
  return Math.round(((f - 32) * 5) / 9 * 10) / 10;
}

// ─── UUID ─────────────────────────────────────────────────────────────────────

export function generateId(): string {
  return Date.now().toString(36) + Math.random().toString(36).slice(2);
}
