<script setup>
import { ref, inject, onMounted, computed } from 'vue';
import { useI18n } from 'vue-i18n';

import useNotify from 'src/composables/useNotify.js';
import {
    generateUpdateSqlQuery,
    generateInsertSqlQuery
} from 'src/js/db/sqlService.js';

const props = defineProps({
    title: {
        type: String,
        default: ''
    },
    table: {
        type: String,
        default: ''
    },
    schema: {
        type: String,
        default: ''
    },
    // Objeto que define las pks de la tabla. Usado para generar las queries sql correspondientes.
    // Debe ser definido como un objeto de pares key-value, donde la clave es el nombre de la columna de la pk.
    pks: {
        type: Object,
        default: () => {}
    },
    createModelDefault: {
        type: Object,
        default: () => ({
            field: '',
            value: ''
        })
    },
    // Objeto que contiene la consulta SQL y los parámetros necesarios para obtener los datos iniciales del formulario.
    // `query` debe ser una cadena de texto que representa la consulta SQL.
    // `params` es un objeto que mapea los parámetros de la consulta a sus valores.
    fetchFormDataSql: {
        type: Object,
        default: () => ({
            query: '',
            params: {}
        })
    },
    // Objeto con los datos iniciales del form, si este objeto es definido, no se ejecuta la query fetchFormDataSql
    formInitialData: {
        type: Object,
        default: () => {}
    },
    // Array de columnas que no se deben actualizar
    columnsToIgnoreUpdate: {
        type: Array,
        default: () => []
    },
    autoLoad: {
        type: Boolean,
        default: true
    },
    isEditMode: {
        type: Boolean,
        default: true
    },
    defaultActions: {
        type: Boolean,
        default: true
    }
});

const emit = defineEmits(['onDataSaved']);

const { t } = useI18n();
const jApi = inject('jApi');
const { notify } = useNotify();

const loading = ref(false);
const formData = ref({});
const addressFormRef = ref(null);
const modelInfo = ref(null);
// Array de nombre de columnas de la tabla
const tableColumns = computed(
    () => modelInfo.value?.columns.map(col => col.name) || []
);
// Array de nombre de columnas que fueron actualizadas y no estan en columnsToIgnoreUpdate
const updatedColumns = computed(() => {
    return tableColumns.value.filter(
        colName =>
            modelInfo.value?.data[0][colName] !== formData.value[colName] &&
            !props.columnsToIgnoreUpdate.includes(colName)
    );
});

const fetchFormData = async () => {
    if (!props.fetchFormDataSql.query) return;
    loading.value = true;
    const { results } = await jApi.execQuery(
        props.fetchFormDataSql.query,
        props.fetchFormDataSql.params
    );

    modelInfo.value = results[0];

    if (!modelInfo.value.data[0]) {
        modelInfo.value.data[0] = {};
        // Si no existen datos iniciales, se inicializan con null, en base a las columnas de la tabla
        modelInfo.value.columns.forEach(
            col => (modelInfo.value.data[0][col.name] = null)
        );
    }

    formData.value = { ...modelInfo.value.data[0] };
    loading.value = false;
};

const submit = async () => {
    try {
        const sqlQuery = generateSqlQuery();
        await jApi.execQuery(sqlQuery, props.pks);
        emit('onDataSaved');
        notify(t('dataSaved'), 'positive');
    } catch (error) {
        console.error('Error updating address:', error);
        notify(t('addressNotUpdated'), 'negative');
    }
};

const generateSqlQuery = () => {
    if (props.isEditMode) {
        return generateUpdateSqlQuery(
            props.schema,
            props.table,
            props.pks,
            updatedColumns.value,
            formData.value
        );
    } else {
        return generateInsertSqlQuery(
            props.schema,
            props.table,
            formData.value,
            updatedColumns.value,
            props.createModelDefault
        );
    }
};

onMounted(async () => {
    if (!props.formInitialData && props.autoLoad) {
        fetchFormData();
    }
});

defineExpose({
    formData,
    submit
});
</script>

<template>
    <Teleport :to="$actions">
        <QBtn
            v-if="defaultActions"
            :label="t('save')"
            type="submit"
            icon="check"
            rounded
            no-caps
            :disabled="!updatedColumns.length"
            @click="addressFormRef.submit()"
        />
    </Teleport>
    <QCard class="form-container">
        <QForm
            v-if="!loading"
            ref="addressFormRef"
            class="column full-width q-gutter-y-xs"
            @submit="submit()"
        >
            <span class="text-h6 text-bold">
                {{ title }}
            </span>
            <slot name="form" :data="formData" />
        </QForm>
        <QSpinner v-else color="primary" size="3em" :thickness="2" />
    </QCard>
</template>

<style lang="scss" scoped>
.form-container {
    width: 100%;
    height: max-content;
    max-width: 544px;
    padding: 32px;
    display: flex;
    justify-content: center;
}
</style>
