import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
import { sendRpcRequest } from "../../services/apiClient";
import type { IDevice } from "../../types/device.types";

interface IDeviceData {
  bat_level: string;
  location: {
    lat: string;
    lon: string;
    speed: string;
  };
}

interface IAudioList {
  path: string;
  url: string;
  file_exists: boolean;
  file_ext: string;
  file_size: string;
  date: string;
}

interface IDeviceState {
  devices: IDevice[];
  deviceData: IDeviceData | null;
  selectedDevice: IDevice | null;
  audioList: IAudioList[];
  isAudioListLoading: boolean;
  loadingDevices: boolean;
  errorDevices: string;
  isFetched: boolean;
  isDeletingDevice: boolean;
}

const initialState: IDeviceState = {
  devices: [],
  deviceData: null,
  selectedDevice: null,
  audioList: [],
  isAudioListLoading: false,
  loadingDevices: false,
  errorDevices: "",
  isFetched: false,
  isDeletingDevice: false,
};

export const fetchDevices = createAsyncThunk(
  "device/fetchDevices",
  async (_, { rejectWithValue }) => {
    try {
      const response = await sendRpcRequest<{ list: IDevice[] }>(
        "devices.getlist"
      );

      return response.list;
    } catch (error: unknown) {
      if (typeof error === "object" && error !== null && "message" in error) {
        return rejectWithValue(error.message);
      }

      return rejectWithValue("Unknown error occurred");
    }
  }
);

export const fetchDeviceData = createAsyncThunk(
  "device/fetchDeviceData",
  async (deviceId: string, { rejectWithValue }) => {
    try {
      const response = await sendRpcRequest<IDeviceData>(
        "devices.getdevicedata",
        {
          deviceId,
        }
      );

      return response;
    } catch (error: unknown) {
      if (typeof error === "object" && error !== null && "message" in error) {
        return rejectWithValue(error.message);
      }

      return rejectWithValue("Unknown error occurred");
    }
  }
);

export const fetchAudioFiles = createAsyncThunk(
  "device/fetchAudioFiles",
  async (
    {
      deviceId,
      dateFrom,
      dateTo,
      appId,
    }: {
      deviceId: string;
      dateFrom: Date;
      dateTo: Date;
      appId: number;
    },
    { rejectWithValue }
  ) => {
    try {
      const response = await sendRpcRequest<{ list: IAudioList[] }>(
        "data.getMedia",
        {
          deviceId,
          type: appId,
          dateFrom,
          dateTo,
          recStart: 0,
          recLimit: 50,
        }
      );

      return response.list;
    } catch (error: unknown) {
      if (typeof error === "object" && error !== null && "message" in error) {
        return rejectWithValue(error.message);
      }

      return rejectWithValue("Unknown error occurred");
    }
  }
);

export const deleteDevice = createAsyncThunk(
  "device/deleteDevice",
  async (deviceId: string, { rejectWithValue }) => {
    try {
      const response = await sendRpcRequest<{ success: boolean }>(
        "devices.deleteDevice",
        { deviceId }
      );

      if (response.success) {
        fetchDevices();
      }

      return response;
    } catch (error: unknown) {
      if (typeof error === "object" && error !== null && "message" in error) {
        return rejectWithValue(error.message);
      }
      return rejectWithValue("Unknown error occurred");
    }
  }
);

const deviceSlice = createSlice({
  name: "device",
  initialState,
  reducers: {
    setSelectedDevice: (state, action) => {
      const selected = state.devices.find((d) => d.id === action.payload);
      state.selectedDevice = selected ?? null;
    },
  },
  extraReducers: (builder) => {
    builder
      .addCase(fetchDevices.pending, (state) => {
        state.loadingDevices = true;
        state.isFetched = false;
      })
      .addCase(fetchDevices.fulfilled, (state, action) => {
        state.loadingDevices = false;
        state.devices = action.payload;
        state.selectedDevice = action.payload[0] ?? null;
        state.isFetched = true;
      })
      .addCase(fetchDevices.rejected, (state, action) => {
        state.loadingDevices = false;
        state.errorDevices = action.payload as string;
        state.isFetched = false;
      })

      .addCase(fetchDeviceData.fulfilled, (state, action) => {
        state.deviceData = action.payload;
      })

      .addCase(deleteDevice.pending, (state) => {
        state.isDeletingDevice = true;
      })
      .addCase(deleteDevice.fulfilled, (state, action) => {
        state.isDeletingDevice = false;
        if (action.payload.success) {
          state.isFetched = false;
        }
      })
      .addCase(deleteDevice.rejected, (state, action) => {
        state.isDeletingDevice = false;
        console.error("Error deleting device:", action.payload);
      })

      .addCase(fetchAudioFiles.pending, (state) => {
        state.isAudioListLoading = true;
      })
      .addCase(fetchAudioFiles.fulfilled, (state, action) => {
        state.isAudioListLoading = false;
        state.audioList = action.payload;
      })
      .addCase(fetchAudioFiles.rejected, (state, action) => {
        state.isAudioListLoading = false;
        console.error("Error fetching audio files:", action.payload);
      });
  },
});

export const { setSelectedDevice } = deviceSlice.actions;
export default deviceSlice.reducer;
