import NanoDate from 'timestamp-nano'
import { IpnsEntry } from './pb/ipns.ts'
import { unmarshalIPNSRecord } from './utils.ts'

/**
 * Selects the latest valid IPNS record from an array of marshalled IPNS records.
 *
 * Records are sorted by:
 * 1. Sequence number (higher takes precedence)
 * 2. Validity time for EOL records with same sequence number (longer lived record takes precedence)
 *
 * @param key - The routing key for the IPNS record
 * @param data - Array of marshalled IPNS records to select from
 * @returns The index of the most valid record from the input array
 */
export function ipnsSelector (key: Uint8Array, data: Uint8Array[]): number {
  const entries = data.map((buf, index) => ({
    record: unmarshalIPNSRecord(buf),
    index
  }))

  entries.sort((a, b) => {
    // Before we'd sort based on the signature version. Unmarshal now fails if
    // a record does not have SignatureV2, so that is no longer needed. V1-only
    // records haven't been issues in a long time.

    const aSeq = a.record.sequence
    const bSeq = b.record.sequence

    // choose later sequence number
    if (aSeq > bSeq) {
      return -1
    } else if (aSeq < bSeq) {
      return 1
    }

    if (a.record.validityType === IpnsEntry.ValidityType.EOL && b.record.validityType === IpnsEntry.ValidityType.EOL) {
      // choose longer lived record if sequence numbers the same
      const recordAValidityDate = NanoDate.fromString(a.record.validity).toDate()
      const recordBValidityDate = NanoDate.fromString(b.record.validity).toDate()

      if (recordAValidityDate.getTime() > recordBValidityDate.getTime()) {
        return -1
      }

      if (recordAValidityDate.getTime() < recordBValidityDate.getTime()) {
        return 1
      }
    }

    return 0
  })

  return entries[0].index
}
