import { expect, fixture, html } from '@open-wc/testing';
import './nile-qr-code';
import NileQrCode from './nile-qr-code';

describe('NileQrCode', () => {
  // === RENDERING ===

  it('1. should render without errors', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code></nile-qr-code>`);
    expect(el).to.exist;
  });

  it('2. should have a shadow root', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code></nile-qr-code>`);
    expect(el.shadowRoot).to.not.be.null;
  });

  it('3. should render a canvas element', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code></nile-qr-code>`);
    const canvas = el.shadowRoot!.querySelector('canvas');
    expect(canvas).to.exist;
  });

  it('4. should have a canvas with correct default size', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code></nile-qr-code>`);
    const canvas = el.shadowRoot!.querySelector('canvas');
    expect(canvas!.getAttribute('width')).to.equal('128');
    expect(canvas!.getAttribute('height')).to.equal('128');
  });

  it('5. shadow root should be open mode', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code></nile-qr-code>`);
    expect(el.shadowRoot!.mode).to.equal('open');
  });

  // === DEFAULT PROPERTY VALUES ===

  it('6. should have default value of empty string', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code></nile-qr-code>`);
    expect(el.value).to.equal('');
  });

  it('7. should have default size of 128', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code></nile-qr-code>`);
    expect(el.size).to.equal(128);
  });

  it('8. should have default fill of black', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code></nile-qr-code>`);
    expect(el.fill).to.equal('black');
  });

  it('9. should have default background of white', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code></nile-qr-code>`);
    expect(el.background).to.equal('white');
  });

  it('10. should have default radius of 0', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code></nile-qr-code>`);
    expect(el.radius).to.equal(0);
  });

  it('11. should have default errorCorrection of H', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code></nile-qr-code>`);
    expect(el.errorCorrection).to.equal('H');
  });

  it('12. should have default label of empty string', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code></nile-qr-code>`);
    expect(el.label).to.equal('');
  });

  // === PROPERTY SETTING ===

  it('13. should accept value property', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code value="https://example.com"></nile-qr-code>`);
    expect(el.value).to.equal('https://example.com');
  });

  it('14. should accept size property', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code size="256"></nile-qr-code>`);
    expect(el.size).to.equal(256);
  });

  it('15. should accept fill property', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code fill="red"></nile-qr-code>`);
    expect(el.fill).to.equal('red');
  });

  it('16. should accept background property', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code background="blue"></nile-qr-code>`);
    expect(el.background).to.equal('blue');
  });

  it('17. should accept radius property', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code radius="0.5"></nile-qr-code>`);
    expect(el.radius).to.equal(0.5);
  });

  it('18. should accept error-correction property', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code error-correction="L"></nile-qr-code>`);
    expect(el.errorCorrection).to.equal('L');
  });

  it('19. should accept label property', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code label="Scan me"></nile-qr-code>`);
    expect(el.label).to.equal('Scan me');
  });

  // === ATTRIBUTE REFLECTION ===

  it('20. should reflect value to attribute', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code value="test"></nile-qr-code>`);
    expect(el.getAttribute('value')).to.equal('test');
  });

  it('21. should reflect size to attribute', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code size="64"></nile-qr-code>`);
    expect(el.getAttribute('size')).to.equal('64');
  });

  it('22. should reflect fill to attribute', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code fill="green"></nile-qr-code>`);
    expect(el.getAttribute('fill')).to.equal('green');
  });

  it('23. should reflect background to attribute', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code background="yellow"></nile-qr-code>`);
    expect(el.getAttribute('background')).to.equal('yellow');
  });

  it('24. should reflect radius to attribute', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code radius="0.3"></nile-qr-code>`);
    expect(el.getAttribute('radius')).to.equal('0.3');
  });

  it('25. should reflect error-correction to attribute', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code error-correction="M"></nile-qr-code>`);
    expect(el.getAttribute('error-correction')).to.equal('M');
  });

  it('26. should reflect label to attribute', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code label="My QR"></nile-qr-code>`);
    expect(el.getAttribute('label')).to.equal('My QR');
  });

  // === ACCESSIBILITY ===

  it('27. should have role=img on canvas', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code></nile-qr-code>`);
    const canvas = el.shadowRoot!.querySelector('canvas');
    expect(canvas!.getAttribute('role')).to.equal('img');
  });

  it('28. should use label for aria-label when provided', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code value="https://test.com" label="Scan this code"></nile-qr-code>`);
    const canvas = el.shadowRoot!.querySelector('canvas');
    expect(canvas!.getAttribute('aria-label')).to.equal('Scan this code');
  });

  it('29. should fallback to value for aria-label when no label', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code value="https://test.com"></nile-qr-code>`);
    const canvas = el.shadowRoot!.querySelector('canvas');
    expect(canvas!.getAttribute('aria-label')).to.equal('https://test.com');
  });

  it('30. should fallback to "QR Code" for aria-label when no label and no value', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code></nile-qr-code>`);
    const canvas = el.shadowRoot!.querySelector('canvas');
    expect(canvas!.getAttribute('aria-label')).to.equal('QR Code');
  });

  // === CSS PARTS ===

  it('31. should have base part on canvas', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code></nile-qr-code>`);
    const canvas = el.shadowRoot!.querySelector('[part="base"]');
    expect(canvas).to.exist;
  });

  it('32. base part should be the canvas element', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code></nile-qr-code>`);
    const canvas = el.shadowRoot!.querySelector('[part="base"]');
    expect(canvas!.tagName.toLowerCase()).to.equal('canvas');
  });

  // === SIZE CHANGES ===

  it('33. should update canvas width when size changes', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code size="64"></nile-qr-code>`);
    const canvas = el.shadowRoot!.querySelector('canvas');
    expect(canvas!.getAttribute('width')).to.equal('64');
  });

  it('34. should update canvas height when size changes', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code size="256"></nile-qr-code>`);
    const canvas = el.shadowRoot!.querySelector('canvas');
    expect(canvas!.getAttribute('height')).to.equal('256');
  });

  it('35. should redraw when size property is changed programmatically', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code value="test" size="128"></nile-qr-code>`);
    el.size = 64;
    await el.updateComplete;
    const canvas = el.shadowRoot!.querySelector('canvas');
    expect(canvas!.getAttribute('width')).to.equal('64');
  });

  // === VALUE CHANGES ===

  it('36. should render QR code when value is set', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code value="Hello"></nile-qr-code>`);
    const canvas = el.shadowRoot!.querySelector('canvas');
    expect(canvas).to.exist;
    // Canvas should have some drawn content
    const ctx = canvas!.getContext('2d');
    expect(ctx).to.exist;
  });

  it('37. should redraw when value changes programmatically', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code value="First"></nile-qr-code>`);
    el.value = 'Second';
    await el.updateComplete;
    expect(el.value).to.equal('Second');
  });

  it('38. should handle empty value gracefully', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code value=""></nile-qr-code>`);
    expect(el).to.exist;
    expect(el.shadowRoot!.querySelector('canvas')).to.exist;
  });

  it('39. should handle long URLs', async () => {
    const longUrl = 'https://example.com/' + 'a'.repeat(200);
    const el = await fixture<NileQrCode>(html`<nile-qr-code value=${longUrl}></nile-qr-code>`);
    expect(el).to.exist;
    expect(el.value).to.equal(longUrl);
  });

  // === ERROR CORRECTION LEVELS ===

  it('40. should accept error-correction L', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code value="test" error-correction="L"></nile-qr-code>`);
    expect(el.errorCorrection).to.equal('L');
  });

  it('41. should accept error-correction M', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code value="test" error-correction="M"></nile-qr-code>`);
    expect(el.errorCorrection).to.equal('M');
  });

  it('42. should accept error-correction Q', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code value="test" error-correction="Q"></nile-qr-code>`);
    expect(el.errorCorrection).to.equal('Q');
  });

  it('43. should accept error-correction H', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code value="test" error-correction="H"></nile-qr-code>`);
    expect(el.errorCorrection).to.equal('H');
  });

  // === RADIUS ===

  it('44. should accept radius 0', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code radius="0"></nile-qr-code>`);
    expect(el.radius).to.equal(0);
  });

  it('45. should accept radius 0.5', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code radius="0.5"></nile-qr-code>`);
    expect(el.radius).to.equal(0.5);
  });

  it('46. should accept fractional radius values', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code radius="0.25"></nile-qr-code>`);
    expect(el.radius).to.equal(0.25);
  });

  // === COLOR PROPERTIES ===

  it('47. should accept hex fill color', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code fill="#FF0000"></nile-qr-code>`);
    expect(el.fill).to.equal('#FF0000');
  });

  it('48. should accept rgb fill color', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code fill="rgb(255,0,0)"></nile-qr-code>`);
    expect(el.fill).to.equal('rgb(255,0,0)');
  });

  it('49. should accept transparent background', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code background="transparent"></nile-qr-code>`);
    expect(el.background).to.equal('transparent');
  });

  it('50. should accept hex background color', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code background="#0000FF"></nile-qr-code>`);
    expect(el.background).to.equal('#0000FF');
  });

  // === INSTANCE ===

  it('51. should be instance of NileQrCode', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code></nile-qr-code>`);
    expect(el).to.be.instanceOf(NileQrCode);
  });

  it('52. should have correct tag name', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code></nile-qr-code>`);
    expect(el.tagName.toLowerCase()).to.equal('nile-qr-code');
  });

  it('53. should be a defined custom element', async () => {
    expect(customElements.get('nile-qr-code')).to.exist;
  });

  it('54. should be registered as NileQrCode', async () => {
    expect(customElements.get('nile-qr-code')).to.equal(NileQrCode);
  });

  // === STATIC STYLES ===

  it('55. should have static styles', async () => {
    const styles = NileQrCode.styles;
    expect(styles).to.exist;
    expect(Array.isArray(styles)).to.be.true;
  });

  it('56. styles array should have at least one entry', async () => {
    const styles = NileQrCode.styles;
    expect((styles as any[]).length).to.be.greaterThan(0);
  });

  // === RENDER METHOD ===

  it('57. should have render method', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code></nile-qr-code>`);
    expect(el.render).to.be.a('function');
  });

  it('58. render should return a TemplateResult', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code></nile-qr-code>`);
    const result = el.render();
    expect(result).to.exist;
  });

  it('59. should not throw when render is called', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code></nile-qr-code>`);
    expect(() => el.render()).to.not.throw();
  });

  // === UPDATE LIFECYCLE ===

  it('60. should have updateComplete promise', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code></nile-qr-code>`);
    expect(el.updateComplete).to.be.a('promise');
  });

  it('61. updateComplete should resolve', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code></nile-qr-code>`);
    const result = await el.updateComplete;
    expect(result).to.not.be.undefined;
  });

  it('62. should render consistently after re-render', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code value="test"></nile-qr-code>`);
    await el.requestUpdate();
    await el.updateComplete;
    const canvas = el.shadowRoot!.querySelector('canvas');
    expect(canvas).to.exist;
  });

  it('63. should maintain canvas after multiple updates', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code value="test"></nile-qr-code>`);
    for (let i = 0; i < 5; i++) {
      await el.requestUpdate();
      await el.updateComplete;
    }
    const canvas = el.shadowRoot!.querySelector('canvas');
    expect(canvas).to.exist;
  });

  // === DOM STRUCTURE ===

  it('64. canvas should be the only child in shadow root template', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code></nile-qr-code>`);
    const canvases = el.shadowRoot!.querySelectorAll('canvas');
    expect(canvases.length).to.equal(1);
  });

  it('65. should not have any slot elements', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code></nile-qr-code>`);
    const slots = el.shadowRoot!.querySelectorAll('slot');
    expect(slots.length).to.equal(0);
  });

  it('66. should not have any input elements', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code></nile-qr-code>`);
    const inputs = el.shadowRoot!.querySelectorAll('input');
    expect(inputs.length).to.equal(0);
  });

  it('67. should not have any button elements', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code></nile-qr-code>`);
    const buttons = el.shadowRoot!.querySelectorAll('button');
    expect(buttons.length).to.equal(0);
  });

  it('68. should not have any SVG elements', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code></nile-qr-code>`);
    const svgs = el.shadowRoot!.querySelectorAll('svg');
    expect(svgs.length).to.equal(0);
  });

  it('69. should not have light DOM content', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code></nile-qr-code>`);
    expect(el.childNodes.length).to.equal(0);
  });

  // === DOM MANIPULATION ===

  it('70. should render after being added to DOM programmatically', async () => {
    const container = await fixture(html`<div></div>`);
    const el = document.createElement('nile-qr-code') as NileQrCode;
    container.appendChild(el);
    await el.updateComplete;
    expect(el.shadowRoot!.querySelector('canvas')).to.exist;
  });

  it('71. should handle removal and re-addition', async () => {
    const container = await fixture(html`<div></div>`);
    const el = document.createElement('nile-qr-code') as NileQrCode;
    container.appendChild(el);
    await el.updateComplete;
    container.removeChild(el);
    container.appendChild(el);
    await el.updateComplete;
    expect(el.shadowRoot!.querySelector('canvas')).to.exist;
  });

  it('72. should work when created via new', async () => {
    const el = new NileQrCode();
    document.body.appendChild(el);
    await el.updateComplete;
    expect(el.shadowRoot!.querySelector('canvas')).to.exist;
    document.body.removeChild(el);
  });

  it('73. should be connectedCallback-compatible', async () => {
    const el = document.createElement('nile-qr-code') as NileQrCode;
    document.body.appendChild(el);
    await el.updateComplete;
    expect(el.isConnected).to.be.true;
    document.body.removeChild(el);
  });

  it('74. should handle disconnectedCallback', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code></nile-qr-code>`);
    el.remove();
    expect(el.isConnected).to.be.false;
  });

  // === RENDERING CONTEXTS ===

  it('75. should render correctly inside a flex container', async () => {
    const container = await fixture(html`<div style="display:flex"><nile-qr-code value="test"></nile-qr-code></div>`);
    const qr = container.querySelector('nile-qr-code')!;
    expect((qr as NileQrCode).shadowRoot!.querySelector('canvas')).to.exist;
  });

  it('76. should render correctly inside a grid container', async () => {
    const container = await fixture(html`<div style="display:grid"><nile-qr-code value="test"></nile-qr-code></div>`);
    const qr = container.querySelector('nile-qr-code')!;
    expect((qr as NileQrCode).shadowRoot!.querySelector('canvas')).to.exist;
  });

  it('77. should render correctly with class attribute', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code class="custom-class"></nile-qr-code>`);
    expect(el.classList.contains('custom-class')).to.be.true;
  });

  it('78. should render correctly with id attribute', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code id="my-qr"></nile-qr-code>`);
    expect(el.id).to.equal('my-qr');
  });

  it('79. should render correctly with style attribute', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code style="margin:10px"></nile-qr-code>`);
    expect(el.style.margin).to.equal('10px');
  });

  it('80. should render correctly with hidden attribute', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code hidden></nile-qr-code>`);
    expect(el.hidden).to.be.true;
  });

  // === MULTIPLE INSTANCES ===

  it('81. should render multiple QR codes independently', async () => {
    const container = await fixture(html`
      <div>
        <nile-qr-code value="One"></nile-qr-code>
        <nile-qr-code value="Two"></nile-qr-code>
        <nile-qr-code value="Three"></nile-qr-code>
      </div>
    `);
    const qrCodes = container.querySelectorAll('nile-qr-code');
    expect(qrCodes.length).to.equal(3);
  });

  it('82. each QR code should have its own shadow root', async () => {
    const container = await fixture(html`
      <div>
        <nile-qr-code value="A"></nile-qr-code>
        <nile-qr-code value="B"></nile-qr-code>
      </div>
    `);
    const qrCodes = container.querySelectorAll('nile-qr-code');
    expect(qrCodes[0].shadowRoot).to.not.equal(qrCodes[1].shadowRoot);
  });

  it('83. multiple instances should each have a canvas', async () => {
    const container = await fixture(html`
      <div>
        <nile-qr-code value="X"></nile-qr-code>
        <nile-qr-code value="Y"></nile-qr-code>
      </div>
    `);
    const qrCodes = container.querySelectorAll('nile-qr-code');
    qrCodes.forEach(qr => {
      expect((qr as NileQrCode).shadowRoot!.querySelector('canvas')).to.exist;
    });
  });

  // === PROGRAMMATIC PROPERTY CHANGES ===

  it('84. should redraw when fill changes programmatically', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code value="test" fill="black"></nile-qr-code>`);
    el.fill = 'red';
    await el.updateComplete;
    expect(el.fill).to.equal('red');
  });

  it('85. should redraw when background changes programmatically', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code value="test" background="white"></nile-qr-code>`);
    el.background = 'transparent';
    await el.updateComplete;
    expect(el.background).to.equal('transparent');
  });

  it('86. should redraw when radius changes programmatically', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code value="test" radius="0"></nile-qr-code>`);
    el.radius = 0.3;
    await el.updateComplete;
    expect(el.radius).to.equal(0.3);
  });

  it('87. should redraw when errorCorrection changes programmatically', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code value="test" error-correction="H"></nile-qr-code>`);
    el.errorCorrection = 'L';
    await el.updateComplete;
    expect(el.errorCorrection).to.equal('L');
  });

  // === EDGE CASES ===

  it('88. should handle being moved between containers', async () => {
    const container1 = await fixture(html`<div></div>`) as HTMLElement;
    const container2 = await fixture(html`<div></div>`) as HTMLElement;
    const el = document.createElement('nile-qr-code') as NileQrCode;
    container1.appendChild(el);
    await el.updateComplete;
    container2.appendChild(el);
    await el.updateComplete;
    expect(el.shadowRoot!.querySelector('canvas')).to.exist;
  });

  it('89. should handle rapid add/remove', async () => {
    const container = await fixture(html`<div></div>`) as HTMLElement;
    const el = document.createElement('nile-qr-code') as NileQrCode;
    container.appendChild(el);
    container.removeChild(el);
    container.appendChild(el);
    await el.updateComplete;
    expect(el.shadowRoot!.querySelector('canvas')).to.exist;
  });

  it('90. shadowRoot host should reference the element', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code></nile-qr-code>`);
    expect(el.shadowRoot!.host).to.equal(el);
  });

  it('91. should handle data-* attributes gracefully', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code data-testid="qr1"></nile-qr-code>`);
    expect(el.getAttribute('data-testid')).to.equal('qr1');
  });

  it('92. should handle setting custom aria attributes', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code aria-hidden="true"></nile-qr-code>`);
    expect(el.getAttribute('aria-hidden')).to.equal('true');
  });

  // === CANVAS ATTRIBUTES ===

  it('93. canvas should have width attribute matching size', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code size="200"></nile-qr-code>`);
    const canvas = el.shadowRoot!.querySelector('canvas');
    expect(canvas!.getAttribute('width')).to.equal('200');
  });

  it('94. canvas should have height attribute matching size', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code size="200"></nile-qr-code>`);
    const canvas = el.shadowRoot!.querySelector('canvas');
    expect(canvas!.getAttribute('height')).to.equal('200');
  });

  it('95. canvas should have part attribute', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code></nile-qr-code>`);
    const canvas = el.shadowRoot!.querySelector('canvas');
    expect(canvas!.getAttribute('part')).to.equal('base');
  });

  it('96. canvas should have role attribute', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code></nile-qr-code>`);
    const canvas = el.shadowRoot!.querySelector('canvas');
    expect(canvas!.hasAttribute('role')).to.be.true;
  });

  it('97. canvas should have aria-label attribute', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code></nile-qr-code>`);
    const canvas = el.shadowRoot!.querySelector('canvas');
    expect(canvas!.hasAttribute('aria-label')).to.be.true;
  });

  // === CONNECTED STATE ===

  it('98. should be in connected state after fixture', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code></nile-qr-code>`);
    expect(el.isConnected).to.be.true;
  });

  it('99. should not affect parent container', async () => {
    const container = await fixture(html`<div class="parent"><nile-qr-code></nile-qr-code></div>`) as HTMLElement;
    expect(container.classList.contains('parent')).to.be.true;
    expect(container.children.length).to.equal(1);
  });

  it('100. should handle all properties at once', async () => {
    const el = await fixture<NileQrCode>(html`
      <nile-qr-code
        value="https://example.com"
        size="256"
        fill="#333"
        background="#FFF"
        radius="0.4"
        error-correction="Q"
        label="Scan to visit"
      ></nile-qr-code>
    `);
    expect(el.value).to.equal('https://example.com');
    expect(el.size).to.equal(256);
    expect(el.fill).to.equal('#333');
    expect(el.background).to.equal('#FFF');
    expect(el.radius).to.equal(0.4);
    expect(el.errorCorrection).to.equal('Q');
    expect(el.label).to.equal('Scan to visit');
    const canvas = el.shadowRoot!.querySelector('canvas');
    expect(canvas).to.exist;
    expect(canvas!.getAttribute('aria-label')).to.equal('Scan to visit');
  });

  // === IMAGE OVERLAY DEFAULTS ===

  it('101. should have default image of empty string', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code></nile-qr-code>`);
    expect(el.image).to.equal('');
  });

  it('102. should have default imageSize of 0.25', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code></nile-qr-code>`);
    expect(el.imageSize).to.equal(0.25);
  });

  it('103. should have default imagePadding of 4', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code></nile-qr-code>`);
    expect(el.imagePadding).to.equal(4);
  });

  it('104. should have default imageRadius of 4', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code></nile-qr-code>`);
    expect(el.imageRadius).to.equal(4);
  });

  // === IMAGE OVERLAY PROPERTY SETTING ===

  it('105. should accept image property', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code image="https://example.com/logo.png"></nile-qr-code>`);
    expect(el.image).to.equal('https://example.com/logo.png');
  });

  it('106. should accept image-size property', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code image-size="0.3"></nile-qr-code>`);
    expect(el.imageSize).to.equal(0.3);
  });

  it('107. should accept image-padding property', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code image-padding="8"></nile-qr-code>`);
    expect(el.imagePadding).to.equal(8);
  });

  it('108. should accept image-radius property', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code image-radius="12"></nile-qr-code>`);
    expect(el.imageRadius).to.equal(12);
  });

  // === IMAGE OVERLAY ATTRIBUTE REFLECTION ===

  it('109. should reflect image to attribute', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code image="logo.png"></nile-qr-code>`);
    expect(el.getAttribute('image')).to.equal('logo.png');
  });

  it('110. should reflect image-size to attribute', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code image-size="0.35"></nile-qr-code>`);
    expect(el.getAttribute('image-size')).to.equal('0.35');
  });

  it('111. should reflect image-padding to attribute', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code image-padding="6"></nile-qr-code>`);
    expect(el.getAttribute('image-padding')).to.equal('6');
  });

  it('112. should reflect image-radius to attribute', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code image-radius="10"></nile-qr-code>`);
    expect(el.getAttribute('image-radius')).to.equal('10');
  });

  // === IMAGE OVERLAY RENDERING ===

  it('113. should still render canvas when image is set', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code value="test" image="https://example.com/logo.png"></nile-qr-code>`);
    expect(el.shadowRoot!.querySelector('canvas')).to.exist;
  });

  it('114. should handle invalid image URL gracefully', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code value="test" image="not-a-valid-url"></nile-qr-code>`);
    await el.updateComplete;
    expect(el).to.exist;
    expect(el.shadowRoot!.querySelector('canvas')).to.exist;
  });

  it('115. should handle image property change programmatically', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code value="test"></nile-qr-code>`);
    el.image = 'https://example.com/logo.png';
    await el.updateComplete;
    expect(el.image).to.equal('https://example.com/logo.png');
  });

  it('116. should clear image when set to empty string', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code value="test" image="https://example.com/logo.png"></nile-qr-code>`);
    el.image = '';
    await el.updateComplete;
    expect(el.image).to.equal('');
  });

  // === GRADIENT FILL DEFAULTS ===

  it('117. should have default fillGradient of empty string', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code></nile-qr-code>`);
    expect(el.fillGradient).to.equal('');
  });

  // === GRADIENT FILL PROPERTY SETTING ===

  it('118. should accept fill-gradient property', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code fill-gradient="135, #6366f1, #ec4899"></nile-qr-code>`);
    expect(el.fillGradient).to.equal('135, #6366f1, #ec4899');
  });

  it('119. should reflect fill-gradient to attribute', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code fill-gradient="90, red, blue"></nile-qr-code>`);
    expect(el.getAttribute('fill-gradient')).to.equal('90, red, blue');
  });

  it('120. should render with gradient fill', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code value="test" fill-gradient="45, #000, #fff"></nile-qr-code>`);
    expect(el.shadowRoot!.querySelector('canvas')).to.exist;
  });

  it('121. should fallback to fill when gradient is malformed', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code value="test" fill-gradient="invalid"></nile-qr-code>`);
    await el.updateComplete;
    expect(el).to.exist;
    expect(el.shadowRoot!.querySelector('canvas')).to.exist;
  });

  it('122. should handle gradient with multiple color stops', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code value="test" fill-gradient="180, red, orange, yellow, green"></nile-qr-code>`);
    await el.updateComplete;
    expect(el).to.exist;
  });

  it('123. should handle gradient change programmatically', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code value="test"></nile-qr-code>`);
    el.fillGradient = '90, #333, #999';
    await el.updateComplete;
    expect(el.fillGradient).to.equal('90, #333, #999');
  });

  // === DOWNLOAD METHOD ===

  it('124. should have a download method', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code value="test"></nile-qr-code>`);
    expect(el.download).to.be.a('function');
  });

  it('125. should have a toDataURL method', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code value="test"></nile-qr-code>`);
    expect(el.toDataURL).to.be.a('function');
  });

  it('126. toDataURL should return a data URL string', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code value="test"></nile-qr-code>`);
    const dataUrl = el.toDataURL();
    expect(dataUrl).to.be.a('string');
    expect(dataUrl).to.include('data:image/png');
  });

  it('127. toDataURL should accept a custom MIME type', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code value="test"></nile-qr-code>`);
    const dataUrl = el.toDataURL('image/jpeg');
    expect(dataUrl).to.be.a('string');
  });

  it('128. download should not throw', async () => {
    const el = await fixture<NileQrCode>(html`<nile-qr-code value="test"></nile-qr-code>`);
    expect(() => el.download('test.png')).to.not.throw();
  });

  // === COMBINED FEATURES ===

  it('129. should handle gradient + rounded modules together', async () => {
    const el = await fixture<NileQrCode>(html`
      <nile-qr-code
        value="test"
        radius="0.5"
        fill-gradient="45, #6366f1, #ec4899">
      </nile-qr-code>
    `);
    await el.updateComplete;
    expect(el.shadowRoot!.querySelector('canvas')).to.exist;
  });

  it('130. should handle all new properties at once', async () => {
    const el = await fixture<NileQrCode>(html`
      <nile-qr-code
        value="https://example.com"
        size="256"
        fill="#333"
        background="#FFF"
        radius="0.3"
        error-correction="H"
        label="Full featured"
        image="https://example.com/logo.png"
        image-size="0.25"
        image-padding="6"
        image-radius="8"
        fill-gradient="135, #6366f1, #ec4899">
      </nile-qr-code>
    `);
    expect(el.value).to.equal('https://example.com');
    expect(el.size).to.equal(256);
    expect(el.imageSize).to.equal(0.25);
    expect(el.imagePadding).to.equal(6);
    expect(el.imageRadius).to.equal(8);
    expect(el.fillGradient).to.equal('135, #6366f1, #ec4899');
    expect(el.shadowRoot!.querySelector('canvas')).to.exist;
  });
});
