import { io, Socket } from "socket.io-client";
import { store } from "../store";
import {
  updateTelemetry,
  setTelemetryLoading,
  setTelemetryError,
} from "../store/telemetrySlice";
import { BmsState } from "@/constants/types";
import { BASE_URL, VECTOR_BASE_URL } from "@/constants/config";
import api from "./axiosClient";
import axios from "axios";

type TokenResponse = {
  success: boolean;
  message: string;
  data: {
    email: string;
    token: string;
  };
};

let socket: Socket | null = null;
let token: string | null = null;
let controllingServer: string | null = null;

const fetchToken = async (): Promise<string> => {
  try {
    const response = await api.get<TokenResponse>(
      `${BASE_URL}/api/v1/vec-token`
    );

    return response.data.data.token;
  } catch (error) {
    console.error("Error fetching token:", error);
    throw error;
  }
};

const fetchControllingServer = async (token: string): Promise<string> => {
  const hardwareDeviceId = store.getState().user.data?.batteries[0]?.battery_id;

  try {
    if (!hardwareDeviceId) throw new Error("Missing hardwareDeviceId");

    const response = await axios.get<string>(
      `${VECTOR_BASE_URL}/api/device-management/dashboard/get/hardwareDeviceId/${hardwareDeviceId.substring(
        1
      )}`,
      {
        headers: {
          Authorization: `Bearer ${token}`,
        },
      }
    );

    return response.data.trim();
  } catch (error) {
    console.error("Error fetching controlling server:", error);
    throw error;
  }
};

export const connectSocket = () => {
  const hardwareDeviceId = store.getState().user.data?.batteries[0]?.battery_id;

  if (!token || !controllingServer || !hardwareDeviceId) {
    store.dispatch(setTelemetryError("Missing socket auth info"));
    return;
  }

  store.dispatch(setTelemetryLoading());
  console.log("Initializing socket connection...");

  socket = io(
    `${VECTOR_BASE_URL}/?dashboardId=deviceDashboardSocket&assetId=${hardwareDeviceId}`,
    {
      transports: ["websocket"],
      extraHeaders: {
        Authorization: `Bearer ${token}`,
        controllingServer: controllingServer,
      },
      reconnection: true,
    }
  );

  socket.on("connect", () => {
    console.log("Socket connected:", socket?.id);
  });

  socket.on("connect_error", (error) => {
    console.error("Socket connection error:", error);
    store.dispatch(setTelemetryError("Socket connection failed"));
  });

  socket.on("disconnect", (reason) => {
    console.log("Socket disconnecteddddd", reason);
    store.dispatch(setTelemetryError("Socket disconnected: " + reason));
  });

  socket.on("dataUpdate", handleSocketData);
};

export const initSocket = async () => {
  try {
    token = await fetchToken();
    controllingServer = await fetchControllingServer(token);
    connectSocket();
  } catch (err) {
    console.log(err, "");
    store.dispatch(setTelemetryError("Initialization failed"));
  }
};

export const disconnectSocket = () => {
  if (socket) {
    socket.disconnect();
    console.log("Socket disconnected");
  }
};

const handleSocketData = (data: any) => {
  console.log("...");
  try {
    console.log(data.dataSeries.assetData, "dataSeries.assetData");
    const SoH =
      data?.dataSeries?.assetData[0]?.bms[0]?.bmsSpecific?.ivecSpecific?.soh ??
      null;
    const SoC = data?.dataSeries?.assetData?.[0]?.bms?.[0]?.batterySoc ?? null;
    const currentMode =
      data?.dataSeries?.assetData?.[0]?.bms?.[0]?.bmsSpecific?.ivecSpecific
        ?.ivecStatus?.currentMode ?? null;

    const gps = data?.dataSeries?.locationData?.gps ?? null;

    const totalDistance = data?.dataSeries?.systemData?.odoMeter ?? null;

    const lat = gps?.[1];
    const lon = gps?.[2];
    console.log("GPS Data:", lat, lon);
    let bms_state: BmsState | null = null;

    if (currentMode === 0) {
      bms_state = 0;
    } else if (currentMode === 1) {
      bms_state = -1;
    } else if (currentMode === 2) {
      bms_state = 1;
    }

    store.dispatch(
      updateTelemetry({
        SoH,
        SoC,
        chargingState: bms_state,
        lat,
        lon,
        loading: false,
        error: null,
        totalDistance,
      })
    );
  } catch (err) {
    console.error("Error handling socket data:", err);
    store.dispatch(setTelemetryError("Data parsing failed"));
  }
};
