
import * as SQLite from "expo-sqlite";
import uuid from "react-native-uuid";

import { Query } from "expo-sqlite";
import { SimpleDate } from "../util/SimpleDate";

let db: SQLite.SQLiteDatabase;

export const initDatabase = async () => {
    db = SQLite.openDatabase("interactive_systeme.db");
    try {
        await db.transactionAsync(async (tx: SQLite.SQLTransactionAsync) => {
            await tx.executeSqlAsync(
                "CREATE TABLE IF NOT EXISTS category (guid VARCHAR(36) PRIMARY KEY, name TEXT, color TEXT, type TEXT, allocated_amount DOUBLE);"
            );
            await tx.executeSqlAsync(
                "CREATE TABLE IF NOT EXISTS expense (guid VARCHAR(36) PRIMARY KEY, name TEXT, category_guid VARCHAR(36), datetime DATETIME, amount DOUBLE, FOREIGN KEY (category_guid) REFERENCES category(guid));"
            );
        });
    } catch (error) {
        console.log("Error initializing the Database!");
        throw (error);
    }
};

export const addCategory = async (name: string, color: string, type: string) => {

    //needs user input validation for type and color (should be validated by this function)

    const UUID = uuid.v4();

    try {
        await db.transactionAsync(async (tx) => {
            await tx.executeSqlAsync("INSERT INTO category (guid, name, color, type) VALUES (?, ?, ?, ?);",
                [UUID.toString(), name, color, type]
            );
        });
    } catch (error) {
        console.log("Error adding category: ", error);
        throw error;
    }
}

export const addExpense = async (name: string, category_guid: string,datetime: string, amount: number) => {

    //needs user input validation for type and color (should be validated by this function)

    const expenseUUID = uuid.v4();

    try {
        await db.transactionAsync(async (tx) => {
            await tx.executeSqlAsync("INSERT INTO expense (guid, name, category_guid, datetime, amount) VALUES (?, ?, ?, ?, ?);", [expenseUUID.toString(), name, category_guid, datetime, amount]
            );
        });
    } catch (error) {
        console.log("Error adding expense: ", error);
        throw error;
    }
};

export const deleteCategory = async (guid: string) => {
    try {
        await db.transactionAsync(async (tx: SQLite.SQLTransactionAsync) => {
            await tx.executeSqlAsync("DELETE FROM category WHERE guid = ?;", [guid]);
        }); 
    } catch(error) {
        console.log("Error deleting category: ", error);
        throw error;
    }
}

export const deleteExpense = async (guid: string) => {
    try {
        await db.transactionAsync(async (tx: SQLite.SQLTransactionAsync) => {
            await tx.executeSqlAsync("DELETE FROM expense WHERE guid = ?;", [guid]);
        }); 
    } catch(error) {
        console.log("Error deleting expense: ", error);
        throw error;
    }
}

export const executeQuery = async (query: Query) => {   
        const result = await db.execAsync([query], true);
    if("error" in result[0]){
        throw result[0].error
    }
    return result; 
}


export const deleteExpenses = async () => {
    try {
        await db.transactionAsync(async (tx: SQLite.SQLTransactionAsync) => {
            await tx.executeSqlAsync("DELETE FROM expense;");
        }); 
    } catch(error) {
        console.log("Error deleting expense: ", error);
        throw error;
    }
}

export const deleteCategories = async () => {
    try {
        await db.transactionAsync(async (tx: SQLite.SQLTransactionAsync) => {
            await tx.executeSqlAsync("DELETE FROM category;");
        }); 
        console.log("deleteCategories")
    } catch(error) {
        console.log("Error deleting category: ", error);
        throw error;
    }
}

export const deleteDatabase = () => {
    closeDatabase().then(() => {
        try {
            db.deleteAsync()
        } catch (error) {
            console.log("Error deleting the Database: ", error);
            throw error;
        }
    });
}

const closeDatabase = async () => {
    try {
        db.closeAsync();
    } catch (error) {
        console.log("Error, cant close database: ", error);
        throw error;
    }
}


export const DEV_populateDatabase = async () => {
    try {
        await deleteCategories();
        await deleteExpenses()

        const colors = ["red", "blue", "green", "purple", "yellow"]

        for(let i=0; i < 5; i++){
            let random = Math.floor(Math.random() * colors.length);
            await addCategory(`Category ${i}`, colors[random], "budget")
        }
        const result = await executeQuery({sql:"SELECT * from category", args:[]})
        let categories: {[column: string]: any}[];
        if("rows" in result[0]){
            categories = result[0]["rows"]
        }else{
            throw new Error("WHATHEFUCK")
        }
        console.log(categories)

        let date = new Date()
        for(let i = 0; i < 15; i++){
            let random = Math.floor(Math.random() * categories.length);
            let randomDay = Math.floor(Math.random() * 20)
            date.setDate(randomDay)
            let string = new SimpleDate(date).toISOString()
            await addExpense(`Expense ${i}`, categories[random].guid, string, 15)
        }
    } catch(e){
        console.error(e)
    }
}
