// providers/LoadTestProvider.jsx
import React, { createContext, useState, useContext, useCallback } from 'react';
import { loadTestService } from '@/services/loadTestService';
import { scenarioService } from '@/services/scenarioService';

const LoadTestContext = createContext();

export const LoadTestProvider = ({ children, contextPath = '/' }) => {
  const [tests, setTests] = useState([]);
  const [scenarios, setScenarios] = useState([]);
  const [currentTest, setCurrentTest] = useState(null);
  const [currentScenario, setCurrentScenario] = useState(null);
  const [currentFlowData, setCurrentFlowData] = useState(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);

  // Initialize services
  const loadTests$ = loadTestService(contextPath);
  const scenarios$ = scenarioService(contextPath);

  const loadScenarioList = useCallback(async () => {
    setLoading(true);
    setError(null);
    try {
      const data = await scenarios$.loadScenarios();
      setScenarios(data);
      return data;
    } catch (err) {
      setError(err.message);
      return [];
    } finally {
      setLoading(false);
    }
  }, []);

  const selectScenario = useCallback((scenarioId) => {
    const scenario = scenarios.find(s => s.id === scenarioId);
    if (!scenario) {
      setError('Scenario not found');
      return null;
    }

    let flowData = { nodes: [], edges: [] };
    if (scenario.scenario) {
      try {
        flowData = JSON.parse(scenario.scenario);
      } catch (e) {
        console.warn('Failed to parse scenario data:', e);
      }
    }
    console.log(scenario);
    console.log(flowData);
    setCurrentScenario(scenario);
    setCurrentFlowData(flowData);
    return flowData;
  }, [scenarios]);

  const createScenario = useCallback(async (name) => {
    setLoading(true);
    setError(null);
    try {
      const newScenario = await scenarios$.createScenario(name);
      await loadScenarioList();
      return newScenario;
    } catch (err) {
      setError(err.message);
      return null;
    } finally {
      setLoading(false);
    }
  }, [loadScenarioList]);

  const updateScenario = useCallback(async (scenario) => {
    setLoading(true);
    setError(null);
    try {
      const updated = await scenarios$.updateScenario(scenario);
      await loadScenarioList();
      return updated;
    } catch (err) {
      setError(err.message);
      return null;
    } finally {
      setLoading(false);
    }
  }, [loadScenarioList]);

  const deleteScenario = useCallback(async (scenario) => {
    setLoading(true);
    setError(null);
    try {
      const newScenario = await scenarios$.deleteScenario(scenario);
      await loadScenarioList();
      return newScenario;
    } catch (err) {
      setError(err.message);
      return null;
    } finally {
      setLoading(false);
    }
  }, [loadScenarioList]);

  const loadTestList = useCallback(async () => {
    setLoading(true);
    setError(null);
    try {
      const data = await loadTests$.loadTests();
      setTests(data);
      return data;
    } catch (err) {
      setError(err.message);
      return [];
    } finally {
      setLoading(false);
    }
  }, []);

  const createTest = useCallback(async (testName) => {
    setLoading(true);
    setError(null);
    try {
      const newTest = await loadTests$.createTest(testName);
      await loadTestList();
      return newTest;
    } catch (err) {
      setError(err.message);
      return null;
    } finally {
      setLoading(false);
    }
  }, [loadTestList]);

  const updateTest = useCallback(async (test) => {
    setLoading(true);
    setError(null);
    try {
      const updatedTest = await loadTests$.updateTest(test);
      setTests(prev => prev.map(t => t.id === test.id ? updatedTest : t));
      return updatedTest;
    } catch (err) {
      setError(err.message);
      return null;
    } finally {
      setLoading(false);
    }
  }, []);

  const deleteTest = useCallback(async (testId) => {
    setLoading(true);
    setError(null);
    try {
      await loadTests$.deleteTest(testId);
      setTests(prev => prev.filter(t => t.id !== testId));
      if (currentTest?.id === testId) {
        setCurrentTest(null);
      }
      return true;
    } catch (err) {
      setError(err.message);
      return false;
    } finally {
      setLoading(false);
    }
  }, [currentTest?.id]);

  const startTest = useCallback(async (test) => {
    setLoading(true);
    setError(null);
    try {
      return await loadTests$.startTest(test);
    } catch (err) {
      setError(err.message);
      return false;
    } finally {
      setLoading(false);
    }
  }, []);

  const stopTest = useCallback(async (test) => {
    setLoading(true);
    setError(null);
    try {
      return await loadTests$.stopTest(test);
    } catch (err) {
      setError(err.message);
      return false;
    } finally {
      setLoading(false);
    }
  }, []);

  const contextValue = {
    tests,
    scenarios,
    currentScenario,
    currentFlowData,
    createScenario,
    updateScenario,
    deleteScenario,
    selectScenario,
    currentTest,
    loading,
    error,
    setCurrentTest,
    loadScenarioList,
    loadTestList,
    createTest,
    updateTest,
    deleteTest,
    startTest,
    stopTest,
    setError
  };

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

export const useLoadTest = () => {
  const context = useContext(LoadTestContext);
  if (!context) {
    throw new Error('useLoadTest must be used within a LoadTestProvider');
  }
  return context;
};

export default LoadTestProvider;
