/*
    Предрейсовые осмотры - мобильное приложение
    Модуль для работы с SQLite базой данных
*/

//---------------------
//Подключение библиотек
//---------------------

const { open } = require('react-native-quick-sqlite');

//Импорт утилиты для загрузки SQL файлов
const SQLFileLoader = require('./sql/SQLFileLoader');
const { DB_NAME } = require('../config/database'); //Имя базы данных

//-----------
//Тело модуля
//-----------

class SQLiteDatabase {
    constructor() {
        this.db = null;
        this.isInitialized = false;
        this.sqlQueries = null;
    }

    //Инициализация базы данных
    async initialize() {
        if (this.isInitialized) {
            return this.db;
        }

        try {
            //Загружаем SQL файлы (синхронно)
            this.sqlQueries = SQLFileLoader.loadAllSQLFiles();

            //Открываем базу данных
            this.db = open({
                name: DB_NAME,
                location: 'default'
            });

            console.log('База данных успешно открыта');

            //Настраиваем базу данных
            await this.setupDatabase();

            this.isInitialized = true;
            return this.db;
        } catch (error) {
            console.error('Ошибка инициализации базы данных:', error);
            throw error;
        }
    }

    //Настройка базы данных (создание таблиц и индексов)
    async setupDatabase() {
        if (!this.db || !this.sqlQueries) {
            throw new Error('База данных или SQL запросы не инициализированы');
        }

        try {
            //Выполняем SQL запросы последовательно
            await this.executeQuery(this.sqlQueries.CREATE_TABLE_APP_SETTINGS);
            console.log('Таблица app_settings создана/проверена');

            await this.executeQuery(this.sqlQueries.CREATE_TABLE_INSPECTIONS);
            console.log('Таблица inspections создана/проверена');

            await this.executeQuery(this.sqlQueries.CREATE_TABLE_AUTH_SESSION);
            console.log('Таблица auth_session создана/проверена');

            await this.executeQuery(this.sqlQueries.CREATE_INDEX_INSPECTIONS_STATUS);
            console.log('Индекс idx_inspections_status создан/проверен');

            await this.executeQuery(this.sqlQueries.CREATE_INDEX_INSPECTIONS_CREATED);
            console.log('Индекс idx_inspections_created создан/проверен');

            console.log('Все таблицы и индексы созданы/проверены');
        } catch (error) {
            console.error('Ошибка настройки базы данных:', error);
            throw error;
        }
    }

    //Выполнение SQL запроса
    async executeQuery(sql, params = []) {
        if (!this.db) {
            throw new Error('База данных не инициализирована');
        }

        try {
            const result = await this.db.executeAsync(sql, params);
            return result;
        } catch (error) {
            console.error('Ошибка выполнения SQL запроса:', error, 'SQL:', sql, 'Params:', params);
            throw error;
        }
    }

    //Получение настройки
    async getSetting(key) {
        try {
            const result = await this.executeQuery(this.sqlQueries.SETTINGS_GET, [key]);

            if (result.rows && result.rows.length > 0) {
                return result.rows.item(0).value;
            }
            return null;
        } catch (error) {
            console.error('Ошибка получения настройки:', error);
            throw error;
        }
    }

    //Сохранение настройки
    async setSetting(key, value) {
        try {
            const stringValue = typeof value === 'object' ? JSON.stringify(value) : String(value);
            await this.executeQuery(this.sqlQueries.SETTINGS_SET, [key, stringValue]);
            return true;
        } catch (error) {
            console.error('Ошибка сохранения настройки:', error);
            throw error;
        }
    }

    //Удаление настройки
    async deleteSetting(key) {
        try {
            await this.executeQuery(this.sqlQueries.SETTINGS_DELETE, [key]);
            return true;
        } catch (error) {
            console.error('Ошибка удаления настройки:', error);
            throw error;
        }
    }

    //Получение всех настроек
    async getAllSettings() {
        try {
            const result = await this.executeQuery(this.sqlQueries.SETTINGS_GET_ALL, []);
            const settings = {};

            if (result.rows && result.rows.length > 0) {
                for (let i = 0; i < result.rows.length; i++) {
                    const row = result.rows.item(i);
                    try {
                        settings[row.key] = JSON.parse(row.value);
                    } catch {
                        settings[row.key] = row.value;
                    }
                }
            }

            return settings;
        } catch (error) {
            console.error('Ошибка получения всех настроек:', error);
            throw error;
        }
    }

    //Очистка всех настроек
    async clearSettings() {
        try {
            await this.executeQuery(this.sqlQueries.SETTINGS_CLEAR_ALL, []);
            return true;
        } catch (error) {
            console.error('Ошибка очистки настроек:', error);
            throw error;
        }
    }

    //Сохранение осмотра
    async saveInspection(inspection) {
        try {
            const { id, title, status, data } = inspection;
            const dataString = data ? JSON.stringify(data) : null;

            await this.executeQuery(this.sqlQueries.INSPECTIONS_UPSERT, [id, title, status, id, dataString]);
            return true;
        } catch (error) {
            console.error('Ошибка сохранения осмотра:', error);
            throw error;
        }
    }

    //Получение всех осмотров
    async getInspections() {
        try {
            const result = await this.executeQuery(this.sqlQueries.INSPECTIONS_GET_ALL, []);
            const inspections = [];

            if (result.rows && result.rows.length > 0) {
                for (let i = 0; i < result.rows.length; i++) {
                    const row = result.rows.item(i);
                    const inspection = {
                        id: row.id,
                        title: row.title,
                        status: row.status,
                        createdAt: row.created_at,
                        updatedAt: row.updated_at
                    };

                    if (row.data) {
                        try {
                            inspection.data = JSON.parse(row.data);
                        } catch {
                            inspection.data = row.data;
                        }
                    }

                    inspections.push(inspection);
                }
            }

            return inspections;
        } catch (error) {
            console.error('Ошибка получения осмотров:', error);
            throw error;
        }
    }

    //Получение осмотра по ID
    async getInspectionById(id) {
        try {
            const result = await this.executeQuery(this.sqlQueries.INSPECTIONS_GET_BY_ID, [id]);

            if (result.rows && result.rows.length > 0) {
                const row = result.rows.item(0);
                const inspection = {
                    id: row.id,
                    title: row.title,
                    status: row.status,
                    createdAt: row.created_at,
                    updatedAt: row.updated_at
                };

                if (row.data) {
                    try {
                        inspection.data = JSON.parse(row.data);
                    } catch {
                        inspection.data = row.data;
                    }
                }

                return inspection;
            }
            return null;
        } catch (error) {
            console.error('Ошибка получения осмотра по ID:', error);
            throw error;
        }
    }

    //Удаление осмотра
    async deleteInspection(id) {
        try {
            await this.executeQuery(this.sqlQueries.INSPECTIONS_DELETE, [id]);
            return true;
        } catch (error) {
            console.error('Ошибка удаления осмотра:', error);
            throw error;
        }
    }

    //Удаление всех осмотров
    async clearInspections() {
        try {
            await this.executeQuery(this.sqlQueries.INSPECTIONS_DELETE_ALL, []);
            return true;
        } catch (error) {
            console.error('Ошибка очистки осмотров:', error);
            throw error;
        }
    }

    //Получение количества осмотров
    async getInspectionsCount() {
        try {
            const result = await this.executeQuery(this.sqlQueries.INSPECTIONS_COUNT, []);

            if (result.rows && result.rows.length > 0) {
                return result.rows.item(0).count;
            }
            return 0;
        } catch (error) {
            console.error('Ошибка получения количества осмотров:', error);
            throw error;
        }
    }

    //Оптимизация базы данных
    async vacuum() {
        try {
            await this.executeQuery(this.sqlQueries.UTILITY_VACUUM, []);
            return true;
        } catch (error) {
            console.error('Ошибка оптимизации базы данных:', error);
            throw error;
        }
    }

    //Сохранение сессии авторизации
    async setAuthSession(session) {
        try {
            const {
                sessionId,
                serverUrl,
                userRn = null,
                userCode = null,
                userName = null,
                companyRn = null,
                companyName = null,
                savePassword = false
            } = session;

            await this.executeQuery(this.sqlQueries.AUTH_SESSION_SET, [
                sessionId,
                serverUrl,
                userRn,
                userCode,
                userName,
                companyRn,
                companyName,
                savePassword ? 1 : 0
            ]);
            return true;
        } catch (error) {
            console.error('Ошибка сохранения сессии авторизации:', error);
            throw error;
        }
    }

    //Получение сессии авторизации
    async getAuthSession() {
        try {
            const result = await this.executeQuery(this.sqlQueries.AUTH_SESSION_GET, []);

            if (result.rows && result.rows.length > 0) {
                const row = result.rows.item(0);
                return {
                    sessionId: row.session_id,
                    serverUrl: row.server_url,
                    userRn: row.user_rn,
                    userCode: row.user_code,
                    userName: row.user_name,
                    companyRn: row.company_rn,
                    companyName: row.company_name,
                    savePassword: row.save_password === 1,
                    createdAt: row.created_at,
                    updatedAt: row.updated_at
                };
            }
            return null;
        } catch (error) {
            console.error('Ошибка получения сессии авторизации:', error);
            throw error;
        }
    }

    //Очистка сессии авторизации
    async clearAuthSession() {
        try {
            await this.executeQuery(this.sqlQueries.AUTH_SESSION_CLEAR, []);
            return true;
        } catch (error) {
            console.error('Ошибка очистки сессии авторизации:', error);
            throw error;
        }
    }

    //Проверка существования таблицы
    async checkTableExists(tableName) {
        try {
            const result = await this.executeQuery(this.sqlQueries.UTILITY_CHECK_TABLE, [tableName]);
            return result.rows && result.rows.length > 0 && result.rows.item(0).exists === 1;
        } catch (error) {
            console.error('Ошибка проверки существования таблицы:', error);
            throw error;
        }
    }

    //Удаление таблицы
    async dropTable(tableName) {
        try {
            await this.executeQuery(this.sqlQueries.UTILITY_DROP_TABLE, [tableName]);
            return true;
        } catch (error) {
            console.error('Ошибка удаления таблицы:', error);
            throw error;
        }
    }

    //Закрытие базы данных
    async close() {
        try {
            if (this.db) {
                // В react-native-quick-sqlite нет явного метода close
                // База данных закрывается автоматически при уничтожении объекта
                this.db = null;
                this.isInitialized = false;
                console.log('База данных закрыта');
            }
        } catch (error) {
            console.error('Ошибка закрытия базы данных:', error);
            this.db = null;
            this.isInitialized = false;
            throw error;
        }
    }
}

//-----------------
//Интерфейс модуля
//-----------------

module.exports = new SQLiteDatabase();
