import { Bytes, PrivateKey } from '@ethersphere/bee-js'
import { FileInfo, FileStatus } from '@solarpunkltd/file-manager-lib'
import React from 'react'

import { LocalStorageKeys } from '../../../utils/localStorage'
import { lifetimeAdjustments } from '../constants/stamps'

export function getDaysLeft(expiryDate: Date): number {
  const now = new Date()

  const diffMs = expiryDate.getTime() - now.getTime()

  return Math.max(0, Math.floor(diffMs / (1000 * 60 * 60 * 24)))
}

export const fromBytesConversion = (size: number, metric: string): number => {
  switch (metric) {
    case 'GB':
      return size / 1000 / 1000 / 1000
    case 'MB':
      return size / 1000 / 1000
    default:
      return 0
  }
}

export function getExpiryDateByLifetime(lifetimeValue: number, actualValidity?: Date): Date {
  const now = actualValidity || new Date()

  const adjustDate = lifetimeAdjustments.get(lifetimeValue)

  if (adjustDate) {
    adjustDate(now)
  }

  return now
}

export const indexStrToBigint = (indexStr?: string): bigint | undefined => {
  if (!indexStr) {
    return undefined
  }

  const isHex = /[a-fA-F]/.test(indexStr) || indexStr.startsWith('0') || indexStr.length > 10

  if (isHex) {
    return BigInt(parseInt(indexStr, 16))
  }

  return BigInt(parseInt(indexStr, 10))
}

export const formatBytes = (v?: string | number): string | undefined => {
  let n: number

  if (typeof v === 'string') n = Number(v)
  else if (typeof v === 'number') n = v
  else n = NaN

  if (!Number.isFinite(n) || n < 0) return undefined

  if (n < 1000) return `${n} B`

  const units = ['KB', 'MB', 'GB', 'TB'] as const
  let val = n / 1000
  let i = 0
  while (val >= 1000 && i < units.length - 1) {
    val /= 1000
    i++
  }

  return `${val.toFixed(1)} ${units[i]}`
}

export const isTrashed = (fi: FileInfo): boolean => fi.status === FileStatus.Trashed

export type Point = { x: number; y: number }
export enum Dir {
  Down = 'down',
  Up = 'up',
}

export function getFileId(fi: FileInfo): string {
  return fi.topic.toString()
}

export function getSigner(input: string): PrivateKey {
  const normalized = input.trim().toLowerCase()
  const inputBytes = Bytes.fromUtf8(normalized)
  const privateKeyHex = Bytes.keccak256(inputBytes).toHex()

  return new PrivateKey(privateKeyHex)
}

export function getSignerPk(): PrivateKey | undefined {
  try {
    const fromLocalPk = localStorage.getItem(LocalStorageKeys.fmPrivateKey)

    if (!fromLocalPk) {
      // eslint-disable-next-line no-console
      console.error('Private key not found, cannot initialize')

      return undefined
    }

    return new PrivateKey(fromLocalPk)
  } catch (err) {
    // eslint-disable-next-line no-console
    console.error(`Private key error in localStorage under key "${LocalStorageKeys.fmPrivateKey}": `, err)

    return undefined
  }
}

export function setSignerPk(pk: string): void {
  localStorage.setItem(LocalStorageKeys.fmPrivateKey, pk)
}

export function removeSignerPk(): void {
  localStorage.removeItem(LocalStorageKeys.fmPrivateKey)
}

export const capitalizeFirstLetter = (str: string): string => str.charAt(0).toUpperCase() + str.slice(1)

export const safeSetState =
  <T>(ref: React.RefObject<boolean>, setter: React.Dispatch<React.SetStateAction<T>>) =>
  (value: React.SetStateAction<T>) => {
    if (ref.current) setter(value)
  }

export const truncateNameMiddle = (s: string, max = 40, start?: number, end?: number): string => {
  if (s.length <= max) return s

  if (start && end && start + end < s.length) {
    return `${s.slice(0, start)}…${s.slice(-end)}`
  }

  const half = Math.floor((max - 1) / 2)

  return `${s.slice(0, half)}…${s.slice(-half)}`
}
