// This program has been developed by students from the bachelor Computer Science at Utrecht
// University within the Software Project course.
// © Copyright Utrecht University (Department of Information and Computing Sciences)
import React, { useEffect } from 'react';
import { API_BASE_URL } from '../../config/api.ts';

/**
 * HELPER: Unified sender function
 */
export const sendAPICall = async (type: string, context: string, endpoint?: string) => {
  try {
    const response = await fetch(`${API_BASE_URL}/button_pressed${endpoint ?? ""}`, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ type, context }),
    });
    if (!response.ok) throw new Error("Backend response error");
    console.log(`API Call send - Type: ${type}, Context: ${context} ${endpoint ? `, Endpoint: ${endpoint}` : ""}`);
  } catch (err) {
    console.error(`Failed to send api call:`, err);
  }
};


/**
 * Sends an API call to the CB for going to the next phase. 
 * In case we can't go to the next phase, the function will throw an error.
 */
export async function nextPhase(): Promise<void> {
  const type = "next_phase"
  const context = ""
  sendAPICall(type, context)
}

export async function stopExperiment(): Promise<void> {
  const type = "stop"
  const context = ""
  sendAPICall(type, context)
}


/**
 * Sends an API call to the CB for going to pause experiment
*/
export async function pauseExperiment(): Promise<void> {
  const type = "pause"
  const context = "true"
  sendAPICall(type, context)
}

/**
 * Sends an API call to the CB for going to resume experiment
*/
export async function playExperiment(): Promise<void> {
  const type = "pause"
  const context = "false"
  sendAPICall(type, context)
}


/**
 * Types for the experiment stream messages
 */
export type PhaseUpdate = { type: 'phase_update'; id: string };
export type GoalUpdate = { type: 'goal_update'; id: string };
export type TriggerUpdate = { type: 'trigger_update'; id: string; achieved: boolean };
export type CondNormsStateUpdate = { type: 'cond_norms_state_update'; norms: { id: string; active: boolean }[] };
export type ExperimentStreamData = PhaseUpdate | GoalUpdate | TriggerUpdate | CondNormsStateUpdate | Record<string, unknown>;

/**
 * A hook that listens to the experiment stream that updates current state of the program
 * via updates sent from the backend
 */
export function useExperimentLogger(onUpdate?: (data: ExperimentStreamData) => void) {
  const callbackRef = React.useRef(onUpdate);
  // Ref is updated every time with on update
  React.useEffect(() => {
    callbackRef.current = onUpdate;
  }, [onUpdate]);

  useEffect(() => {
    console.log("Connecting to Experiment Stream...");
    const eventSource = new EventSource(`${API_BASE_URL}/experiment_stream`);

    eventSource.onmessage = (event) => {
      try {
        const parsedData = JSON.parse(event.data) as ExperimentStreamData;
        //call function using the ref
        callbackRef.current?.(parsedData);
      } catch (err) {
        console.warn("Stream parse error:", err);
      }
    };

    eventSource.onerror = (err) => {
      console.error("SSE Connection Error:", err);
      eventSource.close();
    };

    return () => {
      console.log("Closing Experiment Stream...");
      eventSource.close();
    };
  }, []);
}

/**
 * A hook that listens to the status stream that updates active conditional norms
 * via updates sent from the backend
 */
export function useStatusLogger(onUpdate?: (data: ExperimentStreamData) => void) {
  const callbackRef = React.useRef(onUpdate);

  React.useEffect(() => {
    callbackRef.current = onUpdate;
  }, [onUpdate]);

  useEffect(() => {
    const eventSource = new EventSource(`${API_BASE_URL}/status_stream`);
    eventSource.onmessage = (event) => {
      try {
        const parsedData = JSON.parse(event.data);
        callbackRef.current?.(parsedData);
      } catch (err) { console.warn("Status stream error:", err); }
    };
    return () => eventSource.close();
  }, []);
}
