import { mount } from '@vue/test-utils';
import {
    KviewDatePicker,
    KviewDropdown,
    KviewMoneyInput,
    KviewPercentInput,
    KviewTextInput,
    KviewTextarea,
} from '@kview/ui-core/vue';
import { describe, expect, it } from 'vitest';
import DynamicRecordFields from '@/components/forms/DynamicRecordFields.vue';
import RecordAutocomplete from '@/components/forms/RecordAutocomplete.vue';
import type { DynamicRecordField } from '@/types/records';

const fields: DynamicRecordField[] = [
    { name: 'identity', type: 'separator', label: 'Identity' },
    { name: 'name', type: 'text', label: 'Name', required: true },
    { name: 'notes', type: 'textarea', label: 'Notes', wide: true },
    { name: 'event_date', type: 'date', label: 'Event date' },
    { name: 'commitment', type: 'money', label: 'Commitment', currency: 'EUR' },
    { name: 'ownership', type: 'percent', label: 'Ownership' },
    { name: 'vintage_year', type: 'number', label: 'Vintage year', inputmode: 'numeric' },
    {
        name: 'status',
        type: 'dropdown',
        label: 'Status',
        options: [
            { value: 'active', label: 'Active' },
            { value: 'closed', label: 'Closed' },
        ],
    },
    {
        name: 'country',
        type: 'country',
        label: 'Country',
        options: [{ value: 'FR', label: 'France (FR)' }],
    },
    { name: 'verified', type: 'boolean', label: 'Verified' },
    {
        name: 'fund_id',
        type: 'lookup',
        label: 'Fund',
        lookup: {
            url: '/lookups/funds',
            initialOption: { value: 'fund-1', label: 'Demo Alpha Growth IV' },
        },
    },
];

describe('DynamicRecordFields', () => {
    it('maps typed server schema to shared Vue form primitives', () => {
        const wrapper = mount(DynamicRecordFields, {
            props: {
                fields,
                modelValue: {
                    name: 'Atlas Pension Trust',
                    event_date: '2026-07-19',
                    commitment: '1250000',
                    ownership: '42.5',
                    status: 'active',
                    country: 'FR',
                    verified: true,
                    fund_id: 'fund-1',
                },
                errors: { name: 'The name has already been taken.' },
            },
        });

        expect(wrapper.get('.record-form-separator').text()).toContain('Identity');
        expect(wrapper.findAllComponents(KviewTextInput)).toHaveLength(4);
        expect(wrapper.findAllComponents(KviewTextarea)).toHaveLength(1);
        expect(wrapper.findAllComponents(KviewDatePicker)).toHaveLength(1);
        expect(wrapper.findAllComponents(KviewMoneyInput)).toHaveLength(1);
        expect(wrapper.findAllComponents(KviewPercentInput)).toHaveLength(1);
        expect(wrapper.findAllComponents(KviewDropdown)).toHaveLength(3);
        expect(wrapper.findAllComponents(RecordAutocomplete)).toHaveLength(1);
        expect(wrapper.getComponent(KviewMoneyInput).props()).toMatchObject({
            modelValue: '1250000',
            currency: 'EUR',
        });
        expect(wrapper.findAllComponents(KviewDropdown)[2]?.props('modelValue')).toBe('1');
        expect(wrapper.getComponent(RecordAutocomplete).props()).toMatchObject({
            lookupUrl: '/lookups/funds',
            modelValue: 'fund-1',
        });
        expect(wrapper.text()).toContain('The name has already been taken.');
        expect(wrapper.html()).not.toContain('data-ui-');
    });

    it('emits immutable form updates and selected lookup metadata', () => {
        const source = { name: 'Initial', fund_id: '' };
        const wrapper = mount(DynamicRecordFields, {
            props: {
                fields,
                modelValue: source,
            },
        });

        wrapper.findAllComponents(KviewTextInput)[0]?.vm.$emit('update:modelValue', 'Updated');

        expect(source.name).toBe('Initial');
        expect(wrapper.emitted('update:modelValue')?.[0]?.[0]).toMatchObject({
            name: 'Updated',
            fund_id: '',
        });
        expect(wrapper.emitted('change')?.[0]).toEqual(['name', 'Updated']);

        const option = {
            value: 'fund-2',
            label: 'Demo Beta Credit Opportunities',
            data: { currency: 'USD' },
        };

        wrapper.getComponent(RecordAutocomplete).vm.$emit('selected', option);
        expect(wrapper.emitted('selected')?.at(-1)).toEqual(['fund_id', option]);
    });

    it('renders every label and error as text rather than server-owned HTML', () => {
        const wrapper = mount(DynamicRecordFields, {
            props: {
                fields: [{
                    name: 'name',
                    type: 'text',
                    label: '<strong>Name</strong>',
                }],
                errors: { name: '<img src=x onerror=alert(1)>' },
            },
        });

        expect(wrapper.text()).toContain('<strong>Name</strong>');
        expect(wrapper.text()).toContain('<img src=x onerror=alert(1)>');
        expect(wrapper.find('strong').exists()).toBe(false);
        expect(wrapper.find('img').exists()).toBe(false);
    });

    it('keeps native datetime constraints and previews an existing dynamic image', () => {
        const wrapper = mount(DynamicRecordFields, {
            props: {
                fields: [
                    {
                        name: 'kyc_validated_at',
                        type: 'datetime-local',
                        label: 'KYC validated at',
                        min: '2026-01-01T00:00',
                        max: '2026-12-31T23:59',
                    },
                    {
                        name: 'logo',
                        type: 'file',
                        label: 'Logo',
                        accept: 'image/*',
                        previewUrl: '/media/img/demo-logo.jpg',
                    },
                    {
                        name: 'currency',
                        type: 'text',
                        label: 'Currency',
                        maxlength: 3,
                    },
                ],
                modelValue: {
                    kyc_validated_at: '2026-07-19T14:00',
                    logo: '',
                    currency: 'EUR',
                },
            },
        });

        const dateTime = wrapper.get<HTMLInputElement>('input[name="kyc_validated_at"]');
        const currency = wrapper.get<HTMLInputElement>('input[name="currency"]');
        const preview = wrapper.get<HTMLImageElement>('.record-form-image-preview img');

        expect(dateTime.attributes()).toMatchObject({
            type: 'datetime-local',
            min: '2026-01-01T00:00',
            max: '2026-12-31T23:59',
        });
        expect(currency.attributes('maxlength')).toBe('3');
        expect(preview.attributes('src')).toBe('/media/img/demo-logo.jpg');
        expect(preview.attributes('alt')).toBe('Logo preview');
    });
});
