import React, {
  createContext,
  useCallback,
  useContext,
  useEffect,
  useReducer,
} from "react";
import AsyncStorage from "@react-native-async-storage/async-storage";
import {
  Reading,
  UserProfile,
  AgpThresholds,
  DEFAULT_AGP_THRESHOLDS,
  computeAlert,
  generateId,
  kgToLb,
  fToC,
} from "./health-data";

// ─── Keys ─────────────────────────────────────────────────────────────────────

const KEY_PROFILE    = "vhm_profile";
const KEY_READINGS   = "vhm_readings";
const KEY_THRESHOLDS = "vhm_agp_thresholds";

// ─── State ────────────────────────────────────────────────────────────────────

interface StoreState {
  profile: UserProfile | null;
  readings: Reading[];
  agpThresholds: AgpThresholds;
  loaded: boolean;
}

type Action =
  | { type: "LOAD"; payload: Partial<StoreState> }
  | { type: "SET_PROFILE"; payload: UserProfile }
  | { type: "ADD_READING"; payload: Reading }
  | { type: "UPDATE_READING"; payload: Reading }
  | { type: "DELETE_READING"; payload: string }
  | { type: "CLEAR_READINGS" }
  | { type: "SET_THRESHOLDS"; payload: AgpThresholds };

function reducer(state: StoreState, action: Action): StoreState {
  switch (action.type) {
    case "LOAD":
      return { ...state, ...action.payload, loaded: true };
    case "SET_PROFILE":
      return { ...state, profile: action.payload };
    case "ADD_READING":
      return { ...state, readings: [...state.readings, action.payload] };
    case "UPDATE_READING":
      return {
        ...state,
        readings: state.readings.map((r) =>
          r.id === action.payload.id ? action.payload : r,
        ),
      };
    case "DELETE_READING":
      return {
        ...state,
        readings: state.readings.filter((r) => r.id !== action.payload),
      };
    case "CLEAR_READINGS":
      return { ...state, readings: [] };
    case "SET_THRESHOLDS":
      return { ...state, agpThresholds: action.payload };
    default:
      return state;
  }
}

const initialState: StoreState = {
  profile: null,
  readings: [],
  agpThresholds: DEFAULT_AGP_THRESHOLDS,
  loaded: false,
};

// ─── Context ──────────────────────────────────────────────────────────────────

interface StoreContextValue extends StoreState {
  saveProfile: (profile: UserProfile) => Promise<void>;
  saveReading: (data: Partial<Reading> & { readingType: Reading["readingType"] }) => Promise<Reading>;
  updateReading: (reading: Reading) => Promise<void>;
  deleteReading: (id: string) => Promise<void>;
  clearAllReadings: () => Promise<void>;
  saveThresholds: (t: AgpThresholds) => Promise<void>;
  getLatestHeartRateReading: () => Reading | null;
  getAgpSummaryFromReadings: () => { avg?: string; gmi?: string; tir?: string; var?: string; date?: string } | null;
}

const StoreContext = createContext<StoreContextValue | null>(null);

export function StoreProvider({ children }: { children: React.ReactNode }) {
  const [state, dispatch] = useReducer(reducer, initialState);

  // Load from AsyncStorage on mount
  useEffect(() => {
    (async () => {
      try {
        const [profileRaw, readingsRaw, thresholdsRaw] = await Promise.all([
          AsyncStorage.getItem(KEY_PROFILE),
          AsyncStorage.getItem(KEY_READINGS),
          AsyncStorage.getItem(KEY_THRESHOLDS),
        ]);
        dispatch({
          type: "LOAD",
          payload: {
            profile:       profileRaw    ? JSON.parse(profileRaw)    : null,
            readings:      readingsRaw   ? JSON.parse(readingsRaw)   : [],
            agpThresholds: thresholdsRaw ? JSON.parse(thresholdsRaw) : DEFAULT_AGP_THRESHOLDS,
          },
        });
      } catch {
        dispatch({ type: "LOAD", payload: {} });
      }
    })();
  }, []);

  const saveProfile = useCallback(async (profile: UserProfile) => {
    await AsyncStorage.setItem(KEY_PROFILE, JSON.stringify(profile));
    dispatch({ type: "SET_PROFILE", payload: profile });
  }, []);

  const persistReadings = useCallback(async (readings: Reading[]) => {
    await AsyncStorage.setItem(KEY_READINGS, JSON.stringify(readings));
  }, []);

  const saveReading = useCallback(
    async (data: Partial<Reading> & { readingType: Reading["readingType"] }): Promise<Reading> => {
      const now = new Date();
      const date = data.date ?? now.toISOString().slice(0, 10);
      const time = data.time ?? now.toTimeString().slice(0, 5);

      // Auto-calc derived fields
      let weightLb = data.weightLb ?? null;
      if (data.weightKg != null && weightLb == null) {
        weightLb = kgToLb(data.weightKg);
      }
      let temperatureC = data.temperatureC ?? null;
      if (data.temperatureF != null && temperatureC == null) {
        temperatureC = fToC(data.temperatureF);
      }

      const reading: Reading = {
        id:           data.id ?? generateId(),
        date,
        time,
        patientName:  data.patientName ?? state.profile?.name ?? "",
        readingType:  data.readingType,
        context:      data.context ?? "",
        deviceMethod: data.deviceMethod ?? "Manual",
        systolicBP:   data.systolicBP ?? null,
        diastolicBP:  data.diastolicBP ?? null,
        heartRate:    data.heartRate ?? null,
        spo2:         data.spo2 ?? null,
        bloodGlucose: data.bloodGlucose ?? null,
        weightKg:     data.weightKg ?? null,
        weightLb,
        temperatureF: data.temperatureF ?? null,
        temperatureC,
        hrv:          data.hrv ?? null,
        sleepHours:   data.sleepHours ?? null,
        notes:        data.notes ?? "",
        alertStatus:  computeAlert(data),
      };

      const updated = [...state.readings, reading];
      await persistReadings(updated);
      dispatch({ type: "ADD_READING", payload: reading });
      return reading;
    },
    [state.readings, state.profile, persistReadings],
  );

  const updateReading = useCallback(
    async (reading: Reading) => {
      // Re-compute derived fields
      let weightLb = reading.weightLb;
      if (reading.weightKg != null) weightLb = kgToLb(reading.weightKg);
      let temperatureC = reading.temperatureC;
      if (reading.temperatureF != null) temperatureC = fToC(reading.temperatureF);

      const updated: Reading = {
        ...reading,
        weightLb: weightLb ?? null,
        temperatureC: temperatureC ?? null,
        alertStatus: computeAlert(reading),
      };
      const updatedList = state.readings.map((r) =>
        r.id === updated.id ? updated : r,
      );
      await persistReadings(updatedList);
      dispatch({ type: "UPDATE_READING", payload: updated });
    },
    [state.readings, persistReadings],
  );

  const deleteReading = useCallback(
    async (id: string) => {
      const updatedList = state.readings.filter((r) => r.id !== id);
      await persistReadings(updatedList);
      dispatch({ type: "DELETE_READING", payload: id });
    },
    [state.readings, persistReadings],
  );

  const clearAllReadings = useCallback(async () => {
    await AsyncStorage.setItem(KEY_READINGS, JSON.stringify([]));
    dispatch({ type: "CLEAR_READINGS" });
  }, []);

  const saveThresholds = useCallback(async (t: AgpThresholds) => {
    await AsyncStorage.setItem(KEY_THRESHOLDS, JSON.stringify(t));
    dispatch({ type: "SET_THRESHOLDS", payload: t });
  }, []);

  const getLatestHeartRateReading = useCallback((): Reading | null => {
    const hrReadings = state.readings.filter(
      (r) => r.readingType === "Heart Rate" || (r.readingType === "SpO2" && r.heartRate != null),
    );
    return hrReadings.length > 0 ? hrReadings[hrReadings.length - 1] : null;
  }, [state.readings]);

  const getAgpSummaryFromReadings = useCallback(() => {
    const cgmRows = state.readings.filter(
      (r) => r.context === "CGM Import" || (r.notes && r.notes.includes("GMI")),
    );
    if (cgmRows.length === 0) return null;
    const row = cgmRows[cgmRows.length - 1];
    const notes = row.notes ?? "";
    const find = (pattern: RegExp) => {
      const m = notes.match(pattern);
      return m ? m[1] : undefined;
    };
    return {
      avg:  find(/Report Avg\s+(\d{2,3})\s*mg\/dL/),
      gmi:  find(/GMI\s+([\d.]+)%/),
      tir:  find(/Time in Range\s+(\d{1,3})%/),
      var:  find(/Variability\s+([\d.]+)%/),
      date: row.date,
    };
  }, [state.readings]);

  return (
    <StoreContext.Provider
      value={{
        ...state,
        saveProfile,
        saveReading,
        updateReading,
        deleteReading,
        clearAllReadings,
        saveThresholds,
        getLatestHeartRateReading,
        getAgpSummaryFromReadings,
      }}
    >
      {children}
    </StoreContext.Provider>
  );
}

export function useStore() {
  const ctx = useContext(StoreContext);
  if (!ctx) throw new Error("useStore must be used within StoreProvider");
  return ctx;
}
