import { mount } from '@vue/test-utils';
import { nextTick } from 'vue';
import {
    afterEach,
    describe,
    expect,
    it,
} from 'vitest';
import AliasEditor from '@/components/forms/AliasEditor.vue';

afterEach(() => {
    document.body.innerHTML = '';
});

describe('AliasEditor', () => {
    it('keeps Laravel field names and emits edited rows', async () => {
        const wrapper = mount(AliasEditor, {
            props: {
                modelValue: [{ name: 'Northstar', comment: 'Legal name' }],
            },
        });
        const inputs = wrapper.findAll<HTMLInputElement>('input');

        expect(inputs[0]?.attributes('name')).toBe('alias_names[]');
        expect(inputs[1]?.attributes('name')).toBe('alias_comments[]');

        await inputs[0]?.setValue('Northstar Capital');

        expect(wrapper.emitted('update:modelValue')?.at(-1)?.[0]).toEqual([
            { name: 'Northstar Capital', comment: 'Legal name' },
        ]);
    });

    it('adds a focused row and keeps one cleared row after removing the last alias', async () => {
        const wrapper = mount(AliasEditor, {
            attachTo: document.body,
        });

        await wrapper.get('button.btn-secondary').trigger('click');
        await nextTick();

        const names = wrapper.findAll<HTMLInputElement>('input[name="alias_names[]"]');

        expect(names).toHaveLength(2);
        expect(document.activeElement).toBe(names[1]?.element);

        await names[0]?.setValue('First alias');
        const removeButtons = wrapper.findAll<HTMLButtonElement>('[aria-label="Remove alias"]');

        await removeButtons[1]?.trigger('click');
        await removeButtons[0]?.trigger('click');

        expect(wrapper.findAll('input[name="alias_names[]"]')).toHaveLength(1);
        expect(wrapper.get<HTMLInputElement>('input[name="alias_names[]"]').element.value).toBe('');
    });

    it('surfaces duplicate and Laravel errors without duplicating server markup', async () => {
        const wrapper = mount(AliasEditor, {
            props: {
                modelValue: [
                    { name: 'Northstar', comment: '' },
                    { name: ' northstar ', comment: '' },
                ],
                errors: {
                    'alias_comments.1': 'The comment is too long.',
                    alias: 'Please review the aliases.',
                },
            },
        });

        expect(wrapper.findAll('[role="alert"]')).toHaveLength(4);
        expect(wrapper.text()).toContain('This alias is already used.');
        expect(wrapper.text()).toContain('The comment is too long.');
        expect(wrapper.text()).toContain('Please review the aliases.');
        expect(wrapper.emitted('validity-change')?.[0]).toEqual([false]);

        await wrapper.findAll<HTMLInputElement>('input[name="alias_names[]"]')[1]?.setValue('Blue River');

        expect(wrapper.emitted('validity-change')?.at(-1)).toEqual([true]);
        expect(wrapper.html()).not.toContain('data-alias-');
    });

    it('maps associative Laravel alias errors back to the editable alias row', () => {
        const wrapper = mount(AliasEditor, {
            props: {
                modelValue: [{ name: 'Alias One', comment: '' }],
                errors: {
                    'alias.Alias One': 'The alias must not exceed 255 characters.',
                },
            },
        });
        const aliasInput = wrapper.get<HTMLInputElement>('input[name="alias_names[]"]');

        expect(aliasInput.attributes('aria-invalid')).toBe('true');
        expect(wrapper.get('[role="alert"]').text())
            .toBe('The alias must not exceed 255 characters.');
        expect(wrapper.find('.alias-editor > .ui-form-field__error').exists()).toBe(false);
    });

    it('attaches a root alias conflict to the first editable field', () => {
        const wrapper = mount(AliasEditor, {
            props: {
                modelValue: [{ name: 'Existing alias', comment: '' }],
                errors: {
                    alias: 'This alias is already linked to another record.',
                },
            },
        });
        const aliasInput = wrapper.get<HTMLInputElement>('input[name="alias_names[]"]');

        expect(aliasInput.attributes('aria-invalid')).toBe('true');
        expect(wrapper.get('[role="alert"]').text())
            .toBe('This alias is already linked to another record.');
        expect(wrapper.find('.alias-editor > .ui-form-field__error').exists()).toBe(false);
    });
});
