import { mount } from '@vue/test-utils';
import { nextTick } from 'vue';
import {
    afterEach,
    beforeEach,
    describe,
    expect,
    it,
    vi,
} from 'vitest';
import RecordDeleteAction from '@/components/records/RecordDeleteAction.vue';
import RecordDetailLayout from '@/components/records/RecordDetailLayout.vue';
import RecordFieldGrid from '@/components/records/RecordFieldGrid.vue';
import RecordSummaryCard from '@/components/records/RecordSummaryCard.vue';

beforeEach(() => {
    const meta = document.createElement('meta');

    meta.name = 'csrf-token';
    meta.content = 'record-test-token';
    document.head.append(meta);
});

afterEach(() => {
    document.head.querySelector('meta[name="csrf-token"]')?.remove();
    document.body.innerHTML = '';
    vi.restoreAllMocks();
});

describe('Phase 6 record components', () => {
    it('keeps the summary and main region in a responsive semantic layout', () => {
        const wrapper = mount(RecordDetailLayout, {
            slots: {
                sidebar: '<p>Summary</p>',
                default: '<section>Related records</section>',
            },
        });

        expect(wrapper.get('aside').classes()).toContain('record-detail-sidebar');
        expect(wrapper.get('aside').text()).toBe('Summary');
        expect(wrapper.get('.record-detail-main').text()).toBe('Related records');
    });

    it('renders preformatted summary values and preserves native link boundaries', () => {
        const wrapper = mount(RecordSummaryCard, {
            props: {
                eyebrow: 'Fund',
                title: 'Demo Alpha Growth IV',
                subtitle: 'Luxembourg SCSp',
                icon: 'folder',
                metrics: [
                    { id: 'nav', label: 'NAV', value: '38.2M €' },
                    { id: 'investors', label: 'Investors', value: '8' },
                ],
                details: [
                    {
                        id: 'gp',
                        label: 'General Partner',
                        value: 'Arcadia Ventures',
                        link: { href: '/gps/gp-1', inertia: false },
                    },
                    { id: 'currency', label: 'Currency', value: 'EUR' },
                ],
            },
            slots: {
                fields: '<p>Dynamic fields</p>',
            },
        });

        expect(wrapper.get('h2').text()).toBe('Demo Alpha Growth IV');
        expect(wrapper.get('.record-summary-eyebrow').text()).toBe('Fund');
        expect(wrapper.findAll('.record-summary-metric')).toHaveLength(2);
        expect(wrapper.get('a').attributes('href')).toBe('/gps/gp-1');
        expect(wrapper.get('.record-summary-fields').text()).toBe('Dynamic fields');
        expect(wrapper.html()).not.toContain('data-ui-');
    });

    it('renders server-formatted fields as text without accepting server HTML', () => {
        const wrapper = mount(RecordFieldGrid, {
            props: {
                fields: [
                    { id: 'identity', label: 'Identity', separator: true },
                    { id: 'name', label: 'Name', value: '<strong>Northstar</strong>' },
                    {
                        id: 'gp',
                        label: 'GP',
                        value: 'Arcadia',
                        description: 'Related General Partner',
                        link: { href: '/gps/gp-1', inertia: false },
                    },
                    { id: 'notes', label: 'Notes', value: null, wide: true },
                    {
                        id: 'logo',
                        label: 'Fund logo',
                        value: null,
                        imageUrl: '/storage/funds/alpha.png',
                        wide: true,
                    },
                ],
            },
        });

        expect(wrapper.get('.entity-summary-separator').text()).toBe('Identity');
        expect(wrapper.text()).toContain('<strong>Northstar</strong>');
        expect(wrapper.find('strong').exists()).toBe(false);
        expect(wrapper.get('a').attributes('href')).toBe('/gps/gp-1');
        expect(wrapper.get('[title="Related General Partner"]').attributes('title')).toBe('Related General Partner');
        expect(wrapper.get('.entity-summary-item--wide').text()).toContain('—');
        expect(wrapper.get<HTMLImageElement>('.entity-summary-image').attributes()).toMatchObject({
            src: '/storage/funds/alpha.png',
            alt: 'Fund logo',
        });
    });

    it('confirms once before submitting the native Laravel form', async () => {
        const requestSubmit = vi
            .spyOn(HTMLFormElement.prototype, 'requestSubmit')
            .mockImplementation(() => undefined);
        const wrapper = mount(RecordDeleteAction, {
            attachTo: document.body,
            props: {
                id: 'delete-fund-dialog',
                action: '/funds/fund-1',
                triggerLabel: 'Delete fund',
                confirmation: {
                    title: 'Delete fund?',
                    message: 'This fund will be permanently removed.',
                    label: 'Delete fund',
                },
            },
        });
        const trigger = wrapper.get<HTMLButtonElement>('.btn-danger');

        trigger.element.focus();
        await trigger.trigger('click');
        await nextTick();

        expect(document.body.querySelector('[role="alertdialog"]')?.textContent).toContain('Delete fund?');
        expect(document.activeElement).toBe(document.body.querySelector('.ui-confirm-dialog__cancel'));

        document.body.querySelector<HTMLButtonElement>('.ui-confirm-dialog__accept')?.click();
        await nextTick();

        expect(requestSubmit).toHaveBeenCalledTimes(1);
        expect(wrapper.get('form').attributes('action')).toBe('/funds/fund-1');
        expect(wrapper.get('input[name="_token"]').attributes('value')).toBe('record-test-token');
        expect(wrapper.get('input[name="_method"]').attributes('value')).toBe('DELETE');

        document.body.querySelector<HTMLButtonElement>('.ui-confirm-dialog__accept')?.click();
        expect(requestSubmit).toHaveBeenCalledTimes(1);
    });
});
