// SPDX-FileCopyrightText: © 2026 LEDGER SAS
// SPDX-License-Identifier: Apache-2.0

import type { TezosCoinConfig } from '../config'
import type { Baker } from '../types'
import { makeLRUCache } from '@ledgerhq/live-network/cache'
import network from '@ledgerhq/live-network/network'
import { log } from '@ledgerhq/logs'
import { ledgerValidatorAddress } from './bakers.whitelist-default'

export type TezosApiBaker = {
  address: string
  name: string
  status: string
  balance: number
  features: TezosBakerFeature[]
  delegation: {
    enabled: boolean
    minBalance: number
    fee: number
    capacity: number
    freeSpace: number
    estimatedApy: number
    features: TezosBakerFeature[]
  }
  staking: {
    enabled: boolean
    minBalance: number
    fee: number
    capacity: number
    freeSpace: number
    estimatedApy: number
    features: TezosBakerFeature[]
  }
}

export type TezosBakerFeature = {
  title: string
  content: string | unknown
}

export const cache = makeLRUCache(
  async (config: TezosCoinConfig): Promise<Baker[]> => {
    const bakers: Baker[] = []
    const TEZOS_API_BASE_URL = config.baker.url
    const { data } = await network<TezosApiBaker[]>({
      url: `${TEZOS_API_BASE_URL}/v3/bakers`,
    })

    if (data && Array.isArray(data)) {
      log('tezos/bakers', 'found ' + data.length + ' bakers')
      data
        .filter((raw) => raw.status === 'active' && raw.delegation.enabled)
        .forEach((raw) => {
          const baker = asBaker(raw)

          if (baker) {
            bakers.push(baker)
          }
        })
      bakers.sort((a, b) => (a.name > b.name ? 1 : -1))
    }

    const ledgerBakerIndex = bakers.findIndex((baker) => baker.address === ledgerValidatorAddress)
    const [ledgerBaker] = bakers.splice(ledgerBakerIndex, 1)

    log('tezos/bakers', 'loaded ' + bakers.length + ' bakers')
    return [ledgerBaker, ...bakers]
  },
  (config: TezosCoinConfig) => config.baker.url
)

let _lastBakers: Baker[] = []

export const fetchAllBakers = async (config: TezosCoinConfig): Promise<Baker[]> => {
  const allBakers = await cache.force(config)
  _lastBakers = allBakers
  return allBakers
}

function whitelist(all: Baker[], addresses: string[]) {
  return all.filter((baker) => addresses.includes(baker.address))
}
export const listBakersWithDefault = (whitelistAddresses: string[]): Baker[] => {
  return whitelist(_lastBakers, whitelistAddresses)
}

export const listBakers = async (
  config: TezosCoinConfig,
  whitelistAddresses: string[]
): Promise<Baker[]> => {
  _lastBakers = await cache(config)
  return whitelist(_lastBakers, whitelistAddresses)
}

export function getBakerSync(addr: string): Baker | undefined {
  return _lastBakers.find((baker) => baker.address === addr)
}

export async function loadBaker(config: TezosCoinConfig, addr: string): Promise<Baker | undefined> {
  const cacheBaker = getBakerSync(addr)
  if (cacheBaker) return cacheBaker
  const bakers = await cache(config)
  const baker = bakers.find((baker) => baker.address === addr)
  return baker
}

export const asBaker = (data: TezosApiBaker): Baker | undefined => {
  const { address, name, delegation } = data

  if (
    typeof name === 'string' &&
    typeof address === 'string' &&
    typeof delegation.freeSpace === 'number' &&
    typeof delegation.estimatedApy === 'number' &&
    delegation.estimatedApy >= 0 &&
    delegation.estimatedApy <= 1
  ) {
    return {
      name,
      address,
      logoURL: `https://services.tzkt.io/v1/avatars/${address}`,
      nominalYield: `${Math.floor(10000 * delegation.estimatedApy) / 100} %`,
      capacityStatus: delegation.freeSpace <= 0 ? 'full' : 'normal',
    }
  }
}
