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

vi.mock('../checkbox/MCheckbox.vue', () => ({
  default: {
    name: 'MCheckbox',
    props: ['modelValue', 'id', 'name'],
    emits: ['update:modelValue'],
    template: `
      <input
        type="checkbox"
        :id="id"
        :checked="modelValue"
        @change="$emit('update:modelValue', !$props.modelValue)"
      />
    `,
  },
}));

vi.mock('../radio/MRadio.vue', () => ({
  default: {
    name: 'MRadio',
    props: ['modelValue', 'id', 'name'],
    emits: ['update:modelValue'],
    template: `
      <input
        type="radio"
        :id="id"
        :checked="modelValue"
        @change="$emit('update:modelValue', true)"
      />
    `,
  },
}));

describe('MTileSelectable', () => {
  it('applies bordered class when bordered is true', () => {
    const wrapper = mount(MTileSelectable, {
      props: {
        modelValue: false,
        bordered: true,
      },
    });

    expect(wrapper.classes()).toContain('mc-tile--bordered');
  });

  it('does not apply bordered class when bordered is false', () => {
    const wrapper = mount(MTileSelectable, {
      props: {
        modelValue: false,
        bordered: false,
      },
    });

    expect(wrapper.classes()).not.toContain('mc-tile--bordered');
  });

  it('applies selected class when modelValue is true', () => {
    const wrapper = mount(MTileSelectable, {
      props: {
        modelValue: true,
      },
    });

    expect(wrapper.classes()).toContain('mc-tile--selected');
  });

  it('does not apply selected class when modelValue is false', () => {
    const wrapper = mount(MTileSelectable, {
      props: {
        modelValue: false,
      },
    });

    expect(wrapper.classes()).not.toContain('mc-tile--selected');
  });

  it('applies input left class when inputPosition is left', () => {
    const wrapper = mount(MTileSelectable, {
      props: {
        modelValue: false,
        inputPosition: 'left',
      },
    });

    expect(wrapper.classes()).toContain('mc-tile--input-left');
  });

  it('applies input center class when centered is true', () => {
    const wrapper = mount(MTileSelectable, {
      props: {
        modelValue: false,
        centered: true,
      },
    });

    expect(wrapper.classes()).toContain('mc-tile--input-center');
  });

  it('renders checkbox by default', () => {
    const wrapper = mount(MTileSelectable, {
      props: {
        modelValue: false,
      },
    });

    expect(wrapper.find('input[type="checkbox"]').exists()).toBe(true);
    expect(wrapper.find('input[type="radio"]').exists()).toBe(false);
  });

  it('renders radio when inputType is radio', () => {
    const wrapper = mount(MTileSelectable, {
      props: {
        modelValue: false,
        inputType: 'radio',
      },
    });

    expect(wrapper.find('input[type="radio"]').exists()).toBe(true);
    expect(wrapper.find('input[type="checkbox"]').exists()).toBe(false);
  });

  it('emits update:modelValue when checkbox value changes', async () => {
    const wrapper = mount(MTileSelectable, {
      props: {
        modelValue: false,
      },
    });

    await wrapper.find('input[type="checkbox"]').trigger('change');

    expect(wrapper.emitted('update:modelValue')).toBeTruthy();
    expect(wrapper.emitted('update:modelValue')![0]).toEqual([true]);
  });

  it('emits update:modelValue when radio button value changes', async () => {
    const wrapper = mount(MTileSelectable, {
      props: {
        inputType: 'radio',
        modelValue: false,
      },
    });

    await wrapper.find('input[type="radio"]').trigger('change');

    expect(wrapper.emitted('update:modelValue')).toBeTruthy();
    expect(wrapper.emitted('update:modelValue')![0]).toEqual([true]);
  });

  it('renders header and content when details slot is provided', () => {
    const wrapper = mount(MTileSelectable, {
      props: {
        modelValue: false,
      },
      slots: {
        default: 'Main content',
        details: 'Details content',
      },
    });

    expect(wrapper.find('.mc-tile__header').exists()).toBe(true);
    expect(wrapper.find('.mc-tile__content').exists()).toBe(true);
    expect(wrapper.text()).toContain('Details content');
  });

  it('does not render content container when details slot is missing', () => {
    const wrapper = mount(MTileSelectable, {
      props: {
        modelValue: false,
      },
    });

    expect(wrapper.find('.mc-tile__content').exists()).toBe(false);
  });

  it('emits update:modelValue when card is clicked and clickable is true', async () => {
    const wrapper = mount(MTileSelectable, {
      props: {
        modelValue: false,
        trigger: 'container',
      },
    });

    await wrapper.find('.mc-tile').trigger('click');

    expect(wrapper.emitted('update:modelValue')).toBeTruthy();
    expect(wrapper.emitted('update:modelValue')![0]).toEqual([true]);
  });

  it('does not emit update:modelValue when card is clicked but clickable is false', async () => {
    const wrapper = mount(MTileSelectable, {
      props: {
        modelValue: false,
      },
    });

    await wrapper.find('.mc-tile').trigger('click');

    expect(wrapper.emitted('update:modelValue')).toBeFalsy();
  });

  it('toggles off when card is clicked and already selected with clickable and checkbox', async () => {
    const wrapper = mount(MTileSelectable, {
      props: {
        modelValue: true,
        trigger: 'container',
        inputType: 'checkbox',
      },
    });

    await wrapper.find('.mc-tile').trigger('click');

    expect(wrapper.emitted('update:modelValue')![0]).toEqual([false]);
  });

  it('always sets true when card is clicked with clickable and radio', async () => {
    const wrapper = mount(MTileSelectable, {
      props: {
        modelValue: false,
        trigger: 'container',
        inputType: 'radio',
      },
    });

    await wrapper.find('.mc-tile').trigger('click');

    expect(wrapper.emitted('update:modelValue')![0]).toEqual([true]);
  });

  it('does not double-toggle when the input itself is clicked with clickable enabled', async () => {
    const wrapper = mount(MTileSelectable, {
      props: {
        modelValue: false,
        trigger: 'container',
        inputType: 'checkbox',
      },
    });

    const input = wrapper.find('input[type="checkbox"]');
    await input.trigger('click');
    // Clicking the input itself should not invoke the card click handler
    expect(wrapper.emitted('update:modelValue')).toBeFalsy();
  });
});
