<script>
    import { useDictionaryForm } from "$lib/components/composable/use-dictionary-form.svelte";
    import FormPageContainer from "$lib/components/reusable/form/form-page-container.svelte";
    import DictionaryFormRenderer from "$lib/components/reusable/form/dictionary-form-renderer.svelte";
    import { toast } from "svelte-sonner";
    import ReusableAlertDialog from "$lib/components/reusable/reusable-alert-dialog.svelte";
    import * as Tabs from "$lib/components/ui/tabs/index.js";
    import { useForm } from "$lib/components/composable/use-form.svelte";
    import { buildTestPayload, 
            testCalSchema, testCalInitialForm, testCalDefaultErrors, testCalFormFields, 
            refNumSchema, refNumDefaultErrors, refNumInitialForm, refNumFormFields, 
            refTxtSchema, refTxtDefaultErrors, refTxtInitialForm, refTxtFormFields,
            testMapSchema, testMapInitialForm, testMapDefaultErrors, testMapFormFields
        } from "$lib/components/dictionary/test/config/test-form-config";
    import ReusableEmpty from "$lib/components/reusable/reusable-empty.svelte";
    import RefNum from "./tabs/ref-num.svelte";
    import RefTxt from "./tabs/ref-txt.svelte";
    import Calculation from "./tabs/calculation.svelte";
    import Map from "./tabs/map.svelte";
    import { API } from "$lib/config/api";
    import { untrack } from "svelte";

    let props = $props();

    let resetRefNum = $state();
    let resetRefTxt = $state();
    let resetMap = $state();

    const { masterDetail, formFields, formActions, schema, initialForm } = props.context;

    const { formState } = masterDetail;

    const calFormState = useForm({
        schema: testCalSchema,
        initialForm: testCalInitialForm,
        defaultErrors: testCalDefaultErrors,
    });

    const refNumState = useForm({
        schema: refNumSchema,
        initialForm: refNumInitialForm,
        defaultErrors: refNumDefaultErrors,
    });

    const refTxtState = useForm({
        schema: refTxtSchema,
        initialForm: refTxtInitialForm,
        defaultErrors: refTxtDefaultErrors,
    });

    const mapFormState = useForm({
        schema: testMapSchema,
        initialForm: testMapInitialForm,
        defaultErrors: testMapDefaultErrors,
        modeOpt: 'cascade'
    })

    const activeFormStates = $derived.by(() => {
        switch (formState.form.TestType) {
            case "TEST":
            case "PARAM":
                return [refNumState, refTxtState, mapFormState];
            case "CALC":
                return [calFormState, refNumState, refTxtState, mapFormState];
            case "GROUP":
                return [];
            case "TITLE":
                return [];
            default:
                return [];
        }
    });

    // const helpers = useDictionaryForm(formState);
    const helpers = useDictionaryForm(formState, () => activeFormStates);

    const handlers = {
        clearForm: () => {
            formState.reset();
        }
    };

    const actions = formActions(handlers);

    const allColumns = formFields.flatMap(
        (section) => section.rows.flatMap(
            (row) => row.columns ?? []
        )
    );

    let showConfirm = $state(false);

    async function handleSave() {
        const mainForm = masterDetail.formState.form;
        const calForm = calFormState.form;
        const refForm = refNumState.form;

        const payload = buildTestPayload({
            mainForm,
            calForm,
            refForm,
            testType: mainForm.TestType
        });
        console.log(payload);
        // const result = await formState.save(masterDetail.mode);

        // toast('Test Created!');
        // masterDetail?.exitForm(true);
    }

    const primaryAction = $derived({
        label: 'Save',
        onClick: handleSave,
        disabled: helpers.hasErrors || formState.isSaving.current,
        loading: formState.isSaving.current
    });

    const secondaryActions = [];

    // ==================================================================
    
    let availableTabs = $derived.by(() => {
        const testType = formState?.form?.TestType;
        
        switch(testType) {
            case 'TEST':
            case 'PARAM':
                return ['definition', 'map', 'reference'];
            case 'CALC':
                return ['definition', 'calculation', 'map', 'reference'];
            case 'GROUP':
                return ['definition', 'group'];
            default:
                return ['definition'];
        }
    });

    let disabledResultTypes = $derived.by(() => {
        const testType = formState?.form?.TestType;
        
        switch(testType) {
            case 'TEST':
            case 'PARAM':
                return [];
            case 'CALC':
                return ['RANGE', 'TEXT', 'VSET', 'NORES'];
            case 'GROUP':
                return ['NMRIC', 'RANGE', 'TEXT', 'VSET', 'NORES'];
            case 'TITLE':
                return ['NMRIC', 'RANGE', 'TEXT', 'VSET', 'NORES'];
            default:
                return [];
        }
    });

    let disabledReferenceTypes = $derived.by(() => {
        const resultType = formState?.form?.ResultType;
        
        switch(resultType) {
            case 'NMRIC':
                return ['TEXT', 'VSET', 'NOREF'];
            case 'RANGE':
                return ['TEXT', 'VSET', 'NOREF'];
            case 'TEXT':
                return ['RANGE', 'THOLD', 'VSET', 'NOREF'];
            case 'VSET':
                return ['RANGE', 'THOLD', 'TEXT', 'NOREF'];
            case 'NORES':
                return ['RANGE', 'THOLD', 'TEXT', 'VSET'];
            default:
                return ['RANGE', 'THOLD', 'TEXT', 'VSET', 'NOREF'];
        }
    });

    let hiddenFields = $derived.by(() => {
        const resultType = formState?.form?.ResultType;
        return resultType !== "VSET" ? ["VSet"] : [];
    });

    let refComponent = $derived.by(() => {
        const refType = formState.form.RefType;
        if (refType === 'RANGE' || refType === 'THOLD') return 'numeric';
        if (refType === 'TEXT' || refType === 'VSET') return 'text';
        return null;
    });

    const refTxtFormFieldsTransformed = $derived.by(() => {
        return refTxtFormFields.map(group => ({
            ...group,
            rows: group.rows.map(row => ({
                ...row,
                columns: row.columns.map(col => {
                    if (col.key !== "RefTxt") return col;

                    if (formState.form.ResultType !== "VSET" || !formState.form.VSet) {
                        return {
                            ...col,
                            type: "textarea",
                            optionsEndpoint: undefined
                        };
                    }

                    return {
                        ...col,
                        type: "select",
                        optionsEndpoint: `${API.BASE_URL}${API.VALUESET}/${formState.form.VSet}`,
                        fullWidth: false
                    };
                })
            }))
        }));
    });

    const testMapFormFieldsTransformed = $derived.by(() => {
        return testMapFormFields.map(group => ({
            ...group,
            rows: group.rows.map(row => ({
                ...row,
                columns: row.columns.map(col => {
                    
                    if (col.key === "HostID") {
                        if (mapFormState.form.HostType === "SITE") {
                            return {
                                ...col,
                                type: "select",
                                optionsEndpoint: `${API.BASE_URL}${API.SITE}`,
                                valueKey: "SiteID",
                                labelKey: (item) => `${item.SiteCode} - ${item.SiteName}`,
                            };
                        }
                        return col;
                    }

                    if (col.key === "ClientID") {
                        if (mapFormState.form.ClientType === "SITE") {
                            return {
                                ...col,
                                type: "select",
                                optionsEndpoint: `${API.BASE_URL}${API.SITE}`,
                                valueKey: "SiteID",
                                labelKey: (item) => `${item.SiteCode} - ${item.SiteName}`,
                            };
                        }
                        return col;
                    }

                    if (col.key === "HostTestCode" || col.key === "HostTestName") {
                        if (mapFormState.form.HostType === "SITE" && mapFormState.form.HostID) {
                            return {
                                ...col,
                                type: "select",
                                optionsEndpoint: `${API.BASE_URL}${API.TEST}?SiteID=${mapFormState.form.HostID}`,
                                valueKey: "TestSiteID",
                                labelKey: (item) => `${item.TestSiteCode} - ${item.TestSiteName}`,
                            };
                        }
                        // kalau belum pilih HostID, kembalikan default (misal input biasa)
                        return {
                            ...col,
                            type: "text",
                            optionsEndpoint: undefined
                        };
                    }

                    if (col.key === "ClientTestCode" || col.key === "ClientTestName") {
                        if (mapFormState.form.ClientType === "SITE" && mapFormState.form.ClientID) {
                            return {
                                ...col,
                                type: "select",
                                optionsEndpoint: `${API.BASE_URL}${API.TEST}?SiteID=${mapFormState.form.ClientID}`,
                                valueKey: "TestSiteID",
                                labelKey: (item) => `${item.TestSiteCode} - ${item.TestSiteName}`,
                            };
                        }
                        // kalau belum pilih HostID, kembalikan default (misal input biasa)
                        return {
                            ...col,
                            type: "text",
                            optionsEndpoint: undefined
                        };
                    }

                    return col;
                })
            }))
        }));
    });

// $inspect(activeFormState.errors)
    let activeTab = $state('definition');

    $effect(() => {
        if (!availableTabs.includes(activeTab)) {
            activeTab = availableTabs[0];
        }
    });

    $effect(() => {
        for (const key of hiddenFields) {
            formState.form[key] = "";
        }
    });

    $effect(() => {
        if (formState.form.Factor && !formState.form.Unit2) {
            formState.errors.Unit2 = "Required";
        } else {
            formState.errors.Unit2 = null;
        }
    });

    $effect(() => {
        const allColumns = formFields.flatMap(
            (section) => section.rows.flatMap(
                (row) => row.columns ?? []
            )
        );
        
        untrack(() => {
            for (const col of allColumns) {
                if (!col.optionsEndpoint) continue;
                if (!col.optionsEndpoint || col.autoFetch === false) continue;
    
                formState.fetchOptions?.(
                    {
                        key: col.key,
                        optionsEndpoint: col.optionsEndpoint,
                        valueKey: col.valueKey,
                        labelKey: col.labelKey,
                    },
                    formState.form
                );
            }
        })
    });

    function handleTestTypeChange(value) {
        formState.form.TestType = value;

        formState.form.ResultType = "";
        formState.errors.ResultType = null;
        formState.form.RefType = "";
        formState.errors.RefType = null;

        calFormState.reset();
        refNumState.reset();
        refTxtState.reset();

        resetRefNum?.();
        resetRefTxt?.();
    }

    function handleResultTypeChange(value) {
        formState.form.ResultType = value;

        formState.form.RefType = "";
        formState.errors.RefType = null;

        calFormState.reset();
        refNumState.reset();
        refTxtState.reset();

        resetRefNum?.();
        resetRefTxt?.();

        let newRefType = "";
        if (value === 'TEXT') {
            newRefType = 'TEXT';
        }
        if (value === 'VSET') {
            newRefType = 'VSET';
        }
        if (value === 'NORES') {
            newRefType = 'NOREF';
        }
        
        if (newRefType) {
            formState.form.RefType = newRefType;
            handleRefTypeChange(newRefType);
        }
    }

    function handleRefTypeChange(value) {
        formState.form.RefType = value;

        refNumState.reset();
        refTxtState.reset();

        resetRefNum?.();
        resetRefTxt?.();

        if (value === 'RANGE' || value === 'THOLD') {
            refNumState.form.NumRefType = value;
        }
        if (value === 'TEXT' || value === 'VSET') {
            refTxtState.form.TxtRefType = value;
        }
    }

    // $inspect({
    //     definition: formState.errors,
    //     active: activeFormStates.map(fs => fs.errors)
    // });
</script>

<FormPageContainer title="Create Test" {primaryAction} {secondaryActions} {actions}>
    <Tabs.Root bind:value={activeTab} class="w-full h-full">
        <Tabs.List>
            {#if availableTabs.includes('definition')}
                <Tabs.Trigger value="definition">Definition</Tabs.Trigger>
            {/if}
            {#if availableTabs.includes('calculation')}
                <Tabs.Trigger value="calculation">Calculation</Tabs.Trigger>
            {/if}
            {#if availableTabs.includes('group')}
                <Tabs.Trigger value="group">Group</Tabs.Trigger>
            {/if}
            {#if availableTabs.includes('reference')}
                <Tabs.Trigger value="reference">Reference</Tabs.Trigger>
            {/if}
            {#if availableTabs.includes('map')}
                <Tabs.Trigger value="map">Map</Tabs.Trigger>
            {/if}
        </Tabs.List>
        <Tabs.Content value="definition">
            <DictionaryFormRenderer 
                {formState}
                formFields={formFields}
                mode="create"
                {disabledResultTypes}
                {disabledReferenceTypes}
                {hiddenFields}
                {handleTestTypeChange}
                {handleResultTypeChange}
                {handleRefTypeChange}
            />
        </Tabs.Content>
        <Tabs.Content value="calculation">
            <Calculation {calFormState} {testCalFormFields} />
        </Tabs.Content>
        <Tabs.Content value="group">
            group
        </Tabs.Content>
        <Tabs.Content value="map">
            <Map {mapFormState} testMapFormFields={testMapFormFieldsTransformed} bind:resetMap={resetMap}/>
        </Tabs.Content>
        <Tabs.Content value="reference">
            <div class="w-full h-full flex items-start">
                {#if refComponent === 'numeric'}
                    <RefNum {refNumState} {refNumFormFields} bind:resetRefNum={resetRefNum}/>
                {:else if refComponent === 'text'}
                    <RefTxt {refTxtState} refTxtFormFields={refTxtFormFieldsTransformed} bind:resetRefTxt={resetRefTxt} />
                {:else}
                    <div class="h-full w-full flex items-center">
                        <ReusableEmpty desc="Select a Reference Type" />
                    </div>
                {/if}
            </div>
        </Tabs.Content>
    </Tabs.Root>
    
</FormPageContainer>

<ReusableAlertDialog
    bind:open={masterDetail.showExitConfirm}
    onConfirm={masterDetail.confirmExit}
/>