import { describe, it, expect, vi } from 'vitest'
import { mount, flushPromises } from '@vue/test-utils'

// The forecast identifies a cartridge by its NAME - '414X Black' - and keeps the
// part number on the hover. A part number alone ('W2020X') only identifies the
// toner to someone who already knows it, and the two places that name a supply
// (the order list and the Part column) had shown nothing else.
//
// The number has to survive somewhere: it is what an order is placed against.
// It stays in the title attribute and, verbatim and unlabelled, in the text that
// 'Copy list' writes to the clipboard. These specs pin both halves.
//
// marketingname is nullable, so every display falls back to the number.

vi.mock('@/api', () => ({
  printersApi: { supplyForecast: vi.fn() },
}))
vi.mock('@/utils/apiError', () => ({ apiError: (e) => String(e) }))

import { printersApi } from '@/api'
import TonerForecast from './TonerForecast.vue'

function payload({ marketingname = '414X Black', partnumber = 'W2020X' } = {}) {
  const part = { partnumber, marketingname, capacitytier: 'high', pageyield: 7500 }
  return {
    data: {
      data: {
        available: true,
        days: 90,
        horizondays: 14,
        summary: { bands: { empty: 1 }, replacements: 3, toorder: 1 },
        cartridges: [{
          printerid: 1, printername: 'GageLab-Xerox-C415', assetnumber: 'P-1',
          ipaddress: '10.49.215.12', name: 'Black toner', color: 'black',
          currentlevel: 4, band: 'empty', daysleft: 0, burnrateperday: 1.8,
          rateunstable: false, replacements: 3, basisdays: 12,
          partnumbers: [part],
        }],
        unestimated: [],
        orderlist: [{
          partnumber, marketingname, color: 'black', supplytype: 'toner',
          model: 'Versalink C415', alternates: [], quantity: 2,
          printers: [{ printerid: 1, printername: 'GageLab-Xerox-C415', daysleft: 0 }],
        }],
      },
    },
  }
}

async function render(overrides) {
  printersApi.supplyForecast.mockResolvedValue(payload(overrides))
  const wrapper = mount(TonerForecast, {
    global: { stubs: { 'router-link': { template: '<a><slot /></a>' } } },
  })
  await flushPromises()
  return wrapper
}

describe('the supply is named, not numbered', () => {
  it('shows the name in the order list', async () => {
    const wrapper = await render()
    const name = wrapper.find('.order-list .supplyname')
    expect(name.text()).toBe('414X Black')
  })

  it('shows the name in the Part column', async () => {
    const wrapper = await render()
    const cells = wrapper.findAll('tbody .supplyname')
    expect(cells.length).toBeGreaterThan(0)
    expect(cells[0].text()).toBe('414X Black')
  })

  it('keeps the part number on the hover, both places', async () => {
    const wrapper = await render()
    for (const el of wrapper.findAll('.supplyname')) {
      expect(el.attributes('title')).toBe('W2020X')
    }
  })

  it('never renders the part number as the visible label', async () => {
    const wrapper = await render()
    for (const el of wrapper.findAll('.supplyname')) {
      expect(el.text()).not.toBe('W2020X')
    }
  })
})

describe('a supply with no name on file', () => {
  it('falls back to the part number rather than showing nothing', async () => {
    const wrapper = await render({ marketingname: null })
    for (const el of wrapper.findAll('.supplyname')) {
      expect(el.text()).toBe('W2020X')
    }
  })
})

describe('what purchasing receives is unchanged', () => {
  it('copies the part number, not the name', async () => {
    const written = []
    Object.assign(navigator, {
      clipboard: { writeText: (text) => { written.push(text); return Promise.resolve() } },
    })
    const wrapper = await render()
    await wrapper.find('.order-head button').trigger('click')
    await flushPromises()
    expect(written).toHaveLength(1)
    expect(written[0]).toContain('W2020X')
    expect(written[0]).not.toContain('414X Black')
  })
})
