/**
 * Tests for energy/format.ts — formatMetricValue helper.
 *
 * Coverage:
 * 1. energy device_class → 3 decimal places.
 * 2. non-energy device_class → 2 decimal places.
 * 3. null value → "—" placeholder.
 * 4. undefined value → "—" placeholder.
 * 5. NaN value → "—" placeholder.
 * 6. Missing / null metric metadata → default 2 decimal places.
 * 7. Integer value still rendered with correct decimal places.
 * 8. String numeric value is coerced and formatted.
 */

import { describe, it, expect } from 'vitest'
import { formatMetricValue, VALUE_PLACEHOLDER } from './format'
import type { MetricInfo } from './hooks'

// ---------------------------------------------------------------------------
// Fixtures
// ---------------------------------------------------------------------------

function makeMetric(overrides: Partial<MetricInfo> = {}): MetricInfo {
  return {
    key: 'voltage',
    label: 'Voltage',
    unit: 'V',
    device_class: 'voltage',
    ...overrides,
  }
}

const energyMetric = makeMetric({ key: 'import_energy', label: 'Import Energy', unit: 'kWh', device_class: 'energy' })
const voltageMetric = makeMetric()
const powerMetric = makeMetric({ key: 'active_power', label: 'Active Power', unit: 'W', device_class: 'power' })
const powerFactorMetric = makeMetric({ key: 'power_factor', label: 'Power Factor', unit: '', device_class: 'power_factor' })

// ---------------------------------------------------------------------------
// Tests
// ---------------------------------------------------------------------------

describe('formatMetricValue — energy device_class → 3 decimal places', () => {
  it('formats kWh energy value to 3 decimal places', () => {
    expect(formatMetricValue(123.4567, energyMetric)).toBe('123.457')
  })

  it('formats a whole-number energy value to 3 decimal places', () => {
    expect(formatMetricValue(123, energyMetric)).toBe('123.000')
  })

  it('formats zero energy value to 3 decimal places', () => {
    expect(formatMetricValue(0, energyMetric)).toBe('0.000')
  })
})

describe('formatMetricValue — non-energy device_class → 2 decimal places', () => {
  it('formats voltage to 2 decimal places', () => {
    expect(formatMetricValue(230.2567, voltageMetric)).toBe('230.26')
  })

  it('formats power to 2 decimal places', () => {
    expect(formatMetricValue(295.0, powerMetric)).toBe('295.00')
  })

  it('formats power factor to 2 decimal places', () => {
    expect(formatMetricValue(0.98, powerFactorMetric)).toBe('0.98')
  })

  it('formats current to 2 decimal places', () => {
    const currentMetric = makeMetric({ key: 'current', label: 'Current', unit: 'A', device_class: 'current' })
    expect(formatMetricValue(1.3456, currentMetric)).toBe('1.35')
  })
})

describe('formatMetricValue — null/undefined/NaN → placeholder', () => {
  it('returns placeholder for null', () => {
    expect(formatMetricValue(null, voltageMetric)).toBe(VALUE_PLACEHOLDER)
  })

  it('returns placeholder for undefined', () => {
    expect(formatMetricValue(undefined, voltageMetric)).toBe(VALUE_PLACEHOLDER)
  })

  it('returns placeholder for NaN', () => {
    expect(formatMetricValue(NaN, voltageMetric)).toBe(VALUE_PLACEHOLDER)
  })

  it('returns placeholder for non-numeric string', () => {
    expect(formatMetricValue('not-a-number', voltageMetric)).toBe(VALUE_PLACEHOLDER)
  })

  it('returns placeholder for Infinity', () => {
    expect(formatMetricValue(Infinity, voltageMetric)).toBe(VALUE_PLACEHOLDER)
  })
})

describe('formatMetricValue — missing metric metadata → default 2 decimal places', () => {
  it('falls back to 2 decimal places when metric is undefined', () => {
    expect(formatMetricValue(230.2567)).toBe('230.26')
  })

  it('falls back to 2 decimal places when metric is null', () => {
    expect(formatMetricValue(230.2567, null)).toBe('230.26')
  })

  it('returns placeholder for null value even without metric', () => {
    expect(formatMetricValue(null)).toBe(VALUE_PLACEHOLDER)
  })
})

describe('formatMetricValue — numeric string coercion', () => {
  it('coerces a numeric string to number and formats it', () => {
    // API could theoretically return strings; we handle them gracefully.
    expect(formatMetricValue('230.2567', voltageMetric)).toBe('230.26')
  })

  it('coerces a numeric string for energy metric → 3 decimals', () => {
    expect(formatMetricValue('123.4567', energyMetric)).toBe('123.457')
  })
})
