import { mockFleetReportSchedules } from '../mock/mockFleetReportSchedules'
import type {
  FleetReportFormat,
  FleetReportPeriod,
  FleetReportSchedule,
} from '../model/types'

const FLEET_REPORT_SCHEDULES_STORAGE_KEY = 'fleet-ble-monitor.fleetReportSchedules'
const defaultTimezone = 'Asia/Novosibirsk'
const defaultPeriod: FleetReportPeriod = 'PREVIOUS_DAY'

export type CreateFleetReportSchedulePayload = {
  recipientUserIds: number[]
  reportFormat: FleetReportFormat
  sendTime: string
  enabled: boolean
}

function cloneSchedule(schedule: FleetReportSchedule): FleetReportSchedule {
  return {
    ...schedule,
    recipientUserIds: [...schedule.recipientUserIds],
  }
}

function readSchedules(): FleetReportSchedule[] {
  if (typeof window === 'undefined') {
    return mockFleetReportSchedules.map(cloneSchedule)
  }

  const storedSchedules = window.localStorage.getItem(
    FLEET_REPORT_SCHEDULES_STORAGE_KEY,
  )

  if (!storedSchedules) {
    const initialSchedules = mockFleetReportSchedules.map(cloneSchedule)
    window.localStorage.setItem(
      FLEET_REPORT_SCHEDULES_STORAGE_KEY,
      JSON.stringify(initialSchedules),
    )

    return initialSchedules
  }

  try {
    const parsedSchedules = JSON.parse(storedSchedules) as FleetReportSchedule[]

    return parsedSchedules.map(cloneSchedule)
  } catch {
    const initialSchedules = mockFleetReportSchedules.map(cloneSchedule)
    window.localStorage.setItem(
      FLEET_REPORT_SCHEDULES_STORAGE_KEY,
      JSON.stringify(initialSchedules),
    )

    return initialSchedules
  }
}

function writeSchedules(schedules: FleetReportSchedule[]) {
  if (typeof window === 'undefined') return

  window.localStorage.setItem(
    FLEET_REPORT_SCHEDULES_STORAGE_KEY,
    JSON.stringify(schedules),
  )
  window.dispatchEvent(new Event('fleet-report-schedules:change'))
}

function assertValidSendTime(sendTime: string) {
  if (!/^\d{2}:\d{2}$/.test(sendTime)) {
    throw new Error('Укажите время отправки')
  }

  const [hours, minutes] = sendTime.split(':').map(Number)

  if (hours > 23 || minutes > 59) {
    throw new Error('Укажите корректное время отправки')
  }
}

export const fleetReportSchedulesService = {
  async getSchedules(): Promise<FleetReportSchedule[]> {
    return readSchedules().map(cloneSchedule)
  },

  async createSchedule(
    payload: CreateFleetReportSchedulePayload,
  ): Promise<FleetReportSchedule> {
    const recipientUserIds = Array.from(new Set(payload.recipientUserIds))
      .filter((userId) => Number.isFinite(userId))

    if (recipientUserIds.length === 0) {
      throw new Error('Выберите хотя бы одного получателя')
    }

    assertValidSendTime(payload.sendTime)

    const schedules = readSchedules()
    const now = new Date().toISOString()
    const nextId = Math.max(0, ...schedules.map((schedule) => schedule.id)) + 1
    const schedule: FleetReportSchedule = {
      id: nextId,
      name: 'Ежедневный отчет по парку АТТ',
      recipientUserIds,
      reportFormat: payload.reportFormat,
      sendTime: payload.sendTime,
      period: defaultPeriod,
      timezone: defaultTimezone,
      enabled: payload.enabled,
      createdAt: now,
      updatedAt: now,
    }

    writeSchedules([...schedules, schedule])

    return cloneSchedule(schedule)
  },

  async updateSchedule(
    id: number | string,
    payload: Partial<CreateFleetReportSchedulePayload>,
  ): Promise<FleetReportSchedule> {
    const numericId = Number(id)
    const schedules = readSchedules()
    const scheduleIndex = schedules.findIndex((schedule) => schedule.id === numericId)

    if (scheduleIndex === -1) {
      throw new Error('Рассылка отчета не найдена')
    }

    if (payload.sendTime) {
      assertValidSendTime(payload.sendTime)
    }

    const currentSchedule = schedules[scheduleIndex]
    const recipientUserIds = payload.recipientUserIds
      ? Array.from(new Set(payload.recipientUserIds))
          .filter((userId) => Number.isFinite(userId))
      : currentSchedule.recipientUserIds

    if (recipientUserIds.length === 0) {
      throw new Error('Выберите хотя бы одного получателя')
    }

    const nextSchedule: FleetReportSchedule = {
      ...currentSchedule,
      ...payload,
      id: currentSchedule.id,
      name: currentSchedule.name,
      recipientUserIds,
      period: currentSchedule.period,
      timezone: currentSchedule.timezone,
      createdAt: currentSchedule.createdAt,
      updatedAt: new Date().toISOString(),
    }
    const nextSchedules = [...schedules]
    nextSchedules[scheduleIndex] = nextSchedule
    writeSchedules(nextSchedules)

    return cloneSchedule(nextSchedule)
  },

  async deleteSchedule(id: number | string): Promise<boolean> {
    const numericId = Number(id)
    const schedules = readSchedules()
    const nextSchedules = schedules.filter((schedule) => schedule.id !== numericId)

    if (nextSchedules.length === schedules.length) {
      throw new Error('Рассылка отчета не найдена')
    }

    writeSchedules(nextSchedules)

    return true
  },
}

