import React, { createContext, useContext, useEffect, useMemo, useState } from "react";
import { useSocket } from "./socket-provider";

type LiveState = {
  value: number;
  running: boolean;
};

type JobStream = {
  logs: string[];
  status?: string;
  lastRunAt?: string;
  lastMessage?: string;
};

type LiveContextValue = LiveState & {
  startCounter: () => void;
  stopCounter: () => void;
  jobStreams: Record<string, JobStream>;
};

const LiveContext = createContext<LiveContextValue | undefined>(undefined);

export const LiveProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
  const socket = useSocket();
  const [state, setState] = useState<LiveState>({ value: 0, running: false });
  const [jobStreams, setJobStreams] = useState<Record<string, JobStream>>({});

  useEffect(() => {
    if (!socket) return;

    const handleUpdate = (payload: { value: number }) => {
      setState({ value: payload.value, running: true });
    };

    const handleStopped = (payload: { value: number }) => {
      setState({ value: payload.value, running: false });
    };

    socket.on("counter:update", handleUpdate);
    socket.on("counter:stopped", handleStopped);
    const handleJobLog = ({ jobId, line }: { jobId: string; line: string }) => {
      if (!jobId) return;
      setJobStreams((prev) => {
        const current = prev[jobId] || { logs: [] };
        const nextLogs = [...current.logs, line].slice(-200);
        return { ...prev, [jobId]: { ...current, logs: nextLogs } };
      });
    };

    const handleJobStatus = ({
      jobId,
      status,
      lastRunAt,
      lastMessage
    }: {
      jobId: string;
      status?: string;
      lastRunAt?: string;
      lastMessage?: string;
    }) => {
      if (!jobId) return;
      setJobStreams((prev) => {
        const current = prev[jobId] || { logs: [] };
        return { ...prev, [jobId]: { ...current, status, lastRunAt, lastMessage } };
      });
    };

    socket.emit("counter:status", (payload: { value: number; running: boolean }) => {
      setState({ value: payload.value, running: payload.running });
    });

    socket.on("job:log", handleJobLog);
    socket.on("job:status", handleJobStatus);

    return () => {
      socket.off("counter:update", handleUpdate);
      socket.off("counter:stopped", handleStopped);
      socket.off("job:log", handleJobLog);
      socket.off("job:status", handleJobStatus);
    };
  }, [socket]);

  const startCounter = useMemo(
    () => () => {
      socket?.emit("counter:start");
    },
    [socket]
  );

  const stopCounter = useMemo(
    () => () => {
      socket?.emit("counter:stop");
    },
    [socket]
  );

  const value = useMemo(
    () => ({
      value: state.value,
      running: state.running,
      startCounter,
      stopCounter,
      jobStreams
    }),
    [state, startCounter, stopCounter, jobStreams]
  );

  return <LiveContext.Provider value={value}>{children}</LiveContext.Provider>;
};

export function useLiveCounter() {
  const ctx = useContext(LiveContext);
  if (!ctx) throw new Error("useLiveCounter LiveProvider içinde kullanılmalı");
  return ctx;
}

export function useJobStream(jobId: string) {
  const ctx = useContext(LiveContext);
  if (!ctx) throw new Error("useJobStream LiveProvider içinde kullanılmalı");
  return useMemo(() => ctx.jobStreams[jobId] || { logs: [], status: "idle" }, [ctx.jobStreams, jobId]);
}
