import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
import { wirePasswordReveal, wirePasswordStrength } from '../password-tools';

describe('wirePasswordReveal', () => {
  let form: HTMLElement;

  beforeEach(() => {
    form = document.createElement('div');
    form.innerHTML = `
      <input id="f-password" type="password" value="secret" />
      <button id="reveal-password-btn" class="glyph-btn" type="button" title="reveal">⊙</button>
    `;
    document.body.appendChild(form);
  });

  afterEach(() => {
    document.body.removeChild(form);
  });

  it('flips input.type and glyph on click', () => {
    wirePasswordReveal(form);
    const btn = form.querySelector('#reveal-password-btn') as HTMLButtonElement;
    const input = form.querySelector('#f-password') as HTMLInputElement;
    expect(input.type).toBe('password');
    expect(btn.textContent).toBe('⊙');

    btn.click();
    expect(input.type).toBe('text');
    expect(btn.textContent).toBe('⊘');
    expect(btn.title).toBe('hide');

    btn.click();
    expect(input.type).toBe('password');
    expect(btn.textContent).toBe('⊙');
    expect(btn.title).toBe('reveal');
  });

  it('teardown returned by wirePasswordReveal resets to password', () => {
    const teardown = wirePasswordReveal(form);
    const btn = form.querySelector('#reveal-password-btn') as HTMLButtonElement;
    const input = form.querySelector('#f-password') as HTMLInputElement;
    btn.click(); // now revealed
    expect(input.type).toBe('text');
    teardown();
    expect(input.type).toBe('password');
    expect(btn.textContent).toBe('⊙');
    expect(btn.title).toBe('reveal');
  });
});

describe('wirePasswordStrength', () => {
  let form: HTMLElement;
  let scheduleRate: ReturnType<typeof vi.fn>;

  beforeEach(() => {
    form = document.createElement('div');
    form.innerHTML = `
      <input id="f-password" type="password" value="" />
      <div id="strength-bar-row" class="strength-bar-row" hidden>
        <div class="strength-bar"><span></span><span></span><span></span><span></span><span></span></div>
        <div class="strength-label"></div>
      </div>
    `;
    document.body.appendChild(form);
    scheduleRate = vi.fn();
  });

  afterEach(() => {
    document.body.removeChild(form);
  });

  it('shows bar with score class on input', () => {
    scheduleRate.mockImplementation((_pw, cb) => cb({ score: 3, guessesLog10: 11.4 }));
    wirePasswordStrength(form, { scheduleRate });
    const input = form.querySelector('#f-password') as HTMLInputElement;
    input.value = 'CorrectHorseBatteryStaple';
    input.dispatchEvent(new Event('input'));
    const row = form.querySelector('#strength-bar-row') as HTMLElement;
    expect(row.hidden).toBe(false);
    expect(row.querySelector('.strength-bar')?.className).toContain('s-good');
    expect(row.querySelector('.strength-label')?.textContent).toContain('good');
    expect(row.querySelector('.strength-label')?.textContent).toContain('10^11');
  });

  it('hides bar when input is empty', () => {
    scheduleRate.mockImplementation((_pw, cb) => cb({ score: -1, guessesLog10: -1 }));
    wirePasswordStrength(form, { scheduleRate });
    const input = form.querySelector('#f-password') as HTMLInputElement;
    input.value = '';
    input.dispatchEvent(new Event('input'));
    const row = form.querySelector('#strength-bar-row') as HTMLElement;
    expect(row.hidden).toBe(true);
  });
});
