import { createSlice, type PayloadAction } from '@reduxjs/toolkit'

export interface DeviceScreenReaderConfig {
  enabled: boolean
  autoRefresh: boolean
  refreshInterval: number
  showElementBounds: boolean
  highlightClickable: boolean
  showVirtualKeyboard: boolean
  hierarchyData?: any
  loading: boolean
  error?: string
}

export interface Device {
  id: string
  name: string
  model: string
  osVersion: string
  screenWidth: number
  screenHeight: number
  status: 'online' | 'offline' | 'connecting'
  lastSeen: number
  supportedVideoTransports?: string[]
  srtUploadSupported?: boolean
  inputBlocked?: boolean
  screenReader?: DeviceScreenReaderConfig
  publicIP?: string
  systemVersionName?: string
  romType?: string
  romVersion?: string
  osBuildVersion?: string
  appName?: string
  appVersion?: string
  appPackage?: string
  isLocked?: boolean
  connectedAt?: number
  remark?: string
  ownerUserId?: string
  ownerUsername?: string
  ownerGroupId?: string
  ownerGroupName?: string
}

export interface DeviceStatus {
  cpu: number
  memory: number
  battery: number
  networkSpeed: number
}

export interface DeviceFilter {
  model?: string
  osVersion?: string
  appName?: string
  isLocked?: boolean
  status?: 'online' | 'offline' | 'connecting'
  connectedAtRange?: {
    start?: number
    end?: number
  }
}

interface DevicesState {
  connectedDevices: Device[]
  selectedDeviceId: string | null
  deviceStatuses: Record<string, DeviceStatus>
  isLoading: boolean
  error: string | null
  filter: DeviceFilter
}

const initialState: DevicesState = {
  connectedDevices: [],
  selectedDeviceId: null,
  deviceStatuses: {},
  isLoading: false,
  error: null,
  filter: {},
}

const deviceSlice = createSlice({
  name: 'devices',
  initialState,
  reducers: {
    addDevice: (state, action: PayloadAction<Device>) => {
      const existingIndex = state.connectedDevices.findIndex(
        device => device.id === action.payload.id
      )

      if (existingIndex >= 0) {
        state.connectedDevices[existingIndex] = action.payload
      } else {
        state.connectedDevices.push(action.payload)
      }
    },

    removeDevice: (state, action: PayloadAction<string>) => {
      state.connectedDevices = state.connectedDevices.filter(
        device => device.id !== action.payload
      )

      if (state.selectedDeviceId === action.payload) {
        state.selectedDeviceId = null
      }

      delete state.deviceStatuses[action.payload]
    },

    selectDevice: (state, action: PayloadAction<string>) => {
      state.selectedDeviceId = action.payload
    },

    resetDeviceStates: (_state, _action: PayloadAction<string>) => {
      // This action is observed elsewhere for UI reset side effects.
    },

    clearDeviceSelection: (state) => {
      state.selectedDeviceId = null
    },

    updateDeviceStatus: (state, action: PayloadAction<{ deviceId: string; status: DeviceStatus }>) => {
      const { deviceId, status } = action.payload
      state.deviceStatuses[deviceId] = status
    },

    updateDeviceConnectionStatus: (state, action: PayloadAction<{ deviceId: string; status: Device['status'] }>) => {
      const { deviceId, status } = action.payload
      const device = state.connectedDevices.find(d => d.id === deviceId)

      if (device) {
        device.status = status
        device.lastSeen = Date.now()
      }
    },

    updateDeviceInputBlocked: (state, action: PayloadAction<{ deviceId: string; inputBlocked: boolean }>) => {
      const { deviceId, inputBlocked } = action.payload
      const device = state.connectedDevices.find(d => d.id === deviceId)

      if (device) {
        device.inputBlocked = inputBlocked
      }
    },

    enableDeviceScreenReader: (state, action: PayloadAction<string>) => {
      const deviceId = action.payload
      const device = state.connectedDevices.find(d => d.id === deviceId)

      if (device) {
        if (!device.screenReader) {
          device.screenReader = {
            enabled: false,
            autoRefresh: true,
            refreshInterval: 1,
            showElementBounds: true,
            highlightClickable: true,
            showVirtualKeyboard: false,
            loading: false,
          }
        }
        device.screenReader.enabled = true
        device.screenReader.loading = true
        device.screenReader.error = undefined
      }
    },

    disableDeviceScreenReader: (state, action: PayloadAction<string>) => {
      const deviceId = action.payload
      const device = state.connectedDevices.find(d => d.id === deviceId)

      if (device && device.screenReader) {
        device.screenReader.enabled = false
        device.screenReader.loading = false
        device.screenReader.hierarchyData = undefined
        device.screenReader.error = undefined
      }
    },

    updateDeviceScreenReaderConfig: (state, action: PayloadAction<{ deviceId: string; config: Partial<DeviceScreenReaderConfig> }>) => {
      const { deviceId, config } = action.payload
      const device = state.connectedDevices.find(d => d.id === deviceId)

      if (device) {
        if (!device.screenReader) {
          device.screenReader = {
            enabled: false,
            autoRefresh: true,
            refreshInterval: 1,
            showElementBounds: true,
            highlightClickable: true,
            showVirtualKeyboard: false,
            loading: false,
          }
        }
        if (device.screenReader) {
          Object.assign(device.screenReader, config)
        }
      }
    },

    updateDeviceLockStatus: (state, action: PayloadAction<{ deviceId: string; isLocked: boolean }>) => {
      const { deviceId, isLocked } = action.payload
      const device = state.connectedDevices.find(d => d.id === deviceId)

      if (device) {
        device.isLocked = isLocked
      }
    },

    updateDeviceRemark: (state, action: PayloadAction<{ deviceId: string; remark: string }>) => {
      const { deviceId, remark } = action.payload
      const device = state.connectedDevices.find(d => d.id === deviceId)

      if (device) {
        device.remark = remark
      }
    },

    setDeviceScreenReaderHierarchy: (state, action: PayloadAction<{ deviceId: string; hierarchyData: any; error?: string }>) => {
      const { deviceId, hierarchyData, error } = action.payload
      const device = state.connectedDevices.find(d => d.id === deviceId)

      if (device && device.screenReader) {
        device.screenReader.hierarchyData = hierarchyData
        device.screenReader.loading = false
        device.screenReader.error = error
      }
    },

    setLoading: (state, action: PayloadAction<boolean>) => {
      state.isLoading = action.payload
    },

    setError: (state, action: PayloadAction<string | null>) => {
      state.error = action.payload
    },

    setDeviceFilter: (state, action: PayloadAction<DeviceFilter>) => {
      state.filter = action.payload
    },

    clearDeviceFilter: (state) => {
      state.filter = {}
    },

    updateDeviceFilter: (state, action: PayloadAction<Partial<DeviceFilter>>) => {
      const newFilter = { ...state.filter, ...action.payload }
      if (action.payload.status === undefined && 'status' in newFilter) {
        delete newFilter.status
      }
      state.filter = newFilter
    },

    clearDevices: (state) => {
      state.connectedDevices = []
      state.selectedDeviceId = null
      state.deviceStatuses = {}
      state.filter = {}
    },
  },
})

export const {
  addDevice,
  removeDevice,
  selectDevice,
  resetDeviceStates,
  clearDeviceSelection,
  updateDeviceStatus,
  updateDeviceConnectionStatus,
  updateDeviceInputBlocked,
  enableDeviceScreenReader,
  disableDeviceScreenReader,
  updateDeviceScreenReaderConfig,
  updateDeviceLockStatus,
  updateDeviceRemark,
  setDeviceScreenReaderHierarchy,
  setLoading,
  setError,
  setDeviceFilter,
  clearDeviceFilter,
  updateDeviceFilter,
  clearDevices,
} = deviceSlice.actions

export default deviceSlice.reducer

export const selectFilteredDevices = (state: { devices: DevicesState }) => {
  const { connectedDevices, filter } = state.devices
  const filtered = connectedDevices

  return filtered.filter(device => {
    if (filter.model && !device.model?.toLowerCase().includes(filter.model.toLowerCase())) {
      return false
    }

    if (filter.osVersion && !device.osVersion?.toLowerCase().includes(filter.osVersion.toLowerCase())) {
      return false
    }

    if (filter.appName && !device.appName?.toLowerCase().includes(filter.appName.toLowerCase())) {
      return false
    }

    if (filter.isLocked !== undefined && device.isLocked !== filter.isLocked) {
      return false
    }

    if (filter.status && device.status !== filter.status) {
      return false
    }

    if (filter.connectedAtRange) {
      const { start, end } = filter.connectedAtRange
      const connectedAt = device.connectedAt || device.lastSeen

      if (start && connectedAt < start) {
        return false
      }
      if (end && connectedAt > end) {
        return false
      }
    }

    return true
  })
}
