import React, {useCallback, useEffect, useRef, useState} from 'react';

import '@xyflow/react/dist/style.css';
import MonacoEditor from '@/components/shared/MonacoEditor';
import ScenarioMenuBar from '@/components/api-tester/ScenarioMenuBar.jsx';
import DiagramArea from '@/components/api-tester/DiagramArea.jsx';
import {useLoadTest} from '@/providers/LoadTestProvider.jsx';
import {useScenarioExecutor} from '@/services/ScenarioExecutor';
import APIClient from '@/services/APIClient.js';
import {Button} from '@/components/ui/button.jsx';

const apiClient = new APIClient();

// ConsoleArea Component
const ConsoleArea = ({value, isVisible}) => (
    <div className={`${isVisible ? 'h-full' : 'hidden'}`}>
      <MonacoEditor
          id="scenario-console"
          value={value}
          language="plaintext"
          readOnly={true}
          height="full"
      />
    </div>
);

// Main ScenarioEditor Component
const ScenarioEditor = () => {
  const diagramRef = useRef(null);
  const {currentScenario, currentFlowData, updateScenario} = useLoadTest();
  const [isExecuting, setIsExecuting] = useState(false);
  const [isConsoleVisible, setIsConsoleVisible] = useState(true);

  const {
    logs,
    clearLogs,
    executeScenario,
    executeStep,
    resetExecutor,
    pauseExecution,
    isRunning
  } = useScenarioExecutor(
      currentFlowData?.nodes || [],
      currentFlowData?.edges || [],
      apiClient
  );

  useEffect(() => {
    resetExecutor();
    clearLogs();
  }, [currentFlowData]);

  const handleSave = async () => {
    try {
      console.log(currentScenario);
      const flowData = diagramRef.current?.getFlowData();
      await updateScenario({
        ...currentScenario,
        scenario: JSON.stringify(flowData)
      });
    } catch (error) {
      console.error('Failed to save scenario:', error);
    }
  };

  const handleStepRun = useCallback(async () => {
    setIsExecuting(true);
    try {
      await executeStep();
    } finally {
      setIsExecuting(false);
    }
  }, [executeStep]);

  const handleFullRun = useCallback(async () => {
    setIsExecuting(true);
    try {
      await executeScenario();
    } finally {
      setIsExecuting(false);
    }
  }, [executeScenario]);

  const handlePause = useCallback(() => {
    pauseExecution();
  }, [pauseExecution]);

  const handleReset = useCallback(() => {
    resetExecutor();
    clearLogs();
  }, [resetExecutor, clearLogs]);

  const toggleConsole = useCallback((visibility) => {
    setIsConsoleVisible(visibility);
  }, []);

  if (!currentFlowData) {
    return <div className="flex items-center justify-center h-full">Select a scenario to edit</div>;
  }

  return (
      <div className="flex flex-col h-full">
        <ScenarioMenuBar
            onSave={handleSave}
            onStepRun={handleStepRun}
            onFullRun={handleFullRun}
            onPause={handlePause}
            onReset={handleReset}
            disabled={isExecuting}
            isRunning={isRunning}
        />
        <div className="flex-1 min-h-0 flex flex-col">
          <div className={`${isConsoleVisible ? 'h-1/2' : 'h-full'} min-h-0 border-b`}>
            <DiagramArea
                ref={diagramRef}
                initialNodes={currentFlowData?.nodes || []}
                initialEdges={currentFlowData?.edges || []}
                isExecuting={isExecuting}
            />
          </div>
          <div className={isConsoleVisible ? 'h-1/2' : 'h-auto'}>
            <div className="flex items-center gap-2 p-1 border-b">
              <div>Output:</div>
              <Button
                  variant="outline"
                  size="sm"
                  onClick={() => toggleConsole(!isConsoleVisible)}
              >
                {isConsoleVisible ? '숨기기' : '보이기'}
              </Button>
            </div>
            <div className="h-[calc(100%-32px)]">
              <ConsoleArea value={logs} isVisible={isConsoleVisible}/>
            </div>
          </div>
        </div>
      </div>
  );
};

export default ScenarioEditor;
