import React, { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
import axios from "axios";

const MaintenanceContext = createContext(null);

const INITIAL_STATE = {
  maintenance: null,
  update: null,
  script: null,
  ssh: null,
  loading: true,
  error: "",
  lastUpdated: null
};

export default function MaintenanceProvider({ children }) {
  const [state, setState] = useState(INITIAL_STATE);
  const pollingRef = useRef(null);
  const wasRunningRef = useRef(false);

  const applyState = useCallback((partial) => {
    setState((prev) => ({
      ...prev,
      ...partial
    }));
  }, []);

  const fetchConfig = useCallback(async () => {
    applyState({ loading: true, error: "" });
    try {
      const response = await axios.get("/api/maintenance/config");
      const data = response.data ?? {};
      applyState({
        maintenance: data.maintenance ?? null,
        update: data.update ?? null,
        script: data.script ?? null,
        ssh: data.ssh ?? null,
        loading: false,
        error: "",
        lastUpdated: new Date()
      });
    } catch (err) {
      const message = err.response?.data?.error || err.message || "Fehler beim Laden der Wartungsdaten";
      applyState({ loading: false, error: message });
    }
  }, [applyState]);

  const refreshUpdateStatus = useCallback(async () => {
    try {
      const response = await axios.get("/api/maintenance/update-status");
      const data = response.data ?? {};
      setState((prev) => ({
        ...prev,
        maintenance: data.maintenance ?? prev.maintenance,
        update: data.update ?? prev.update,
        error: ""
      }));
    } catch (err) {
      const message = err.response?.data?.error || err.message || "Fehler beim Aktualisieren des Wartungsstatus";
      setState((prev) => ({ ...prev, error: message }));
    }
  }, []);

  useEffect(() => {
    fetchConfig();
  }, [fetchConfig]);

  useEffect(() => {
    if (state.update?.running) {
      refreshUpdateStatus();
      const intervalId = setInterval(() => {
        refreshUpdateStatus();
      }, 5000);
      pollingRef.current = intervalId;
      return () => clearInterval(intervalId);
    }
    if (pollingRef.current) {
      clearInterval(pollingRef.current);
      pollingRef.current = null;
    }
    return undefined;
  }, [state.update?.running, refreshUpdateStatus]);

  useEffect(() => {
    const currentlyRunning = Boolean(state.update?.running);
    if (!currentlyRunning && wasRunningRef.current) {
      fetchConfig();
    }
    wasRunningRef.current = currentlyRunning;
  }, [state.update?.running, fetchConfig]);

  const triggerUpdate = useCallback(async (payload = {}) => {
    await axios.post("/api/maintenance/portainer-update", payload);
    await refreshUpdateStatus();
  }, [refreshUpdateStatus]);

  const saveScript = useCallback(async (script) => {
    await axios.put("/api/maintenance/update-script", { script });
    await fetchConfig();
  }, [fetchConfig]);

  const resetScript = useCallback(async () => {
    await axios.delete("/api/maintenance/update-script");
    await fetchConfig();
  }, [fetchConfig]);

  const saveSshConfig = useCallback(async (config) => {
    await axios.put("/api/maintenance/ssh-config", config);
    await fetchConfig();
  }, [fetchConfig]);

  const deleteSshConfig = useCallback(async () => {
    await axios.delete("/api/maintenance/ssh-config");
    await fetchConfig();
  }, [fetchConfig]);

  const testSshConnection = useCallback(async (config) => {
    const response = await axios.post("/api/maintenance/test-ssh", config ?? {});
    return response.data;
  }, []);

  const value = useMemo(() => ({
    maintenance: state.maintenance,
    update: state.update,
    script: state.script,
    ssh: state.ssh,
    loading: state.loading,
    error: state.error,
    lastUpdated: state.lastUpdated,
    refreshConfig: fetchConfig,
    refreshUpdateStatus,
    triggerUpdate,
    saveScript,
    resetScript,
    saveSshConfig,
    deleteSshConfig,
    testSshConnection
  }), [state, fetchConfig, refreshUpdateStatus, triggerUpdate, saveScript, resetScript, saveSshConfig, deleteSshConfig, testSshConnection]);

  return (
    <MaintenanceContext.Provider value={value}>
      {children}
    </MaintenanceContext.Provider>
  );
}

export function useMaintenance() {
  const context = useContext(MaintenanceContext);
  if (!context) {
    throw new Error('useMaintenance must be used within a MaintenanceProvider');
  }
  return context;
}
