import { Database } from 'sqlite3';
import { IUser } from './interfaces/IUser';
import { Logger, LogLevel } from '../logging/Logging';

export class UserStorage {
    private database: Database;
    constructor() {
        Logger.logMessage("Establishing connection to UserStorage database", "Database", LogLevel.INFO);
        this.database = new Database('../storage/UserStorage.sqlite3');
        this.runMigrations();
        Logger.logMessage("Connection established", "Database", LogLevel.INFO);
    }

    /**
     * Run the database migrations
     */
    private runMigrations(): void {
        this.database.serialize(() => {
            Logger.logMessage("Run database migration", "Database", LogLevel.INFO);
            this.database.run('CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, credits INTEGER)');
        });
    }

    /**
     * Update the credits for a user in the database
     * @param userId {string}
     * @param credits {number}
     * @returns 
     */
    public async updateUserCredits(userId: string, credits: number): Promise<void> {
        return new Promise((resolve, reject) => {
            this.database.run('UPDATE users SET credits = ? WHERE id = ?', [credits, userId], (err) => {
                if (err) {
                    reject(err);
                } else {
                    resolve();
                }
            });
        });
    }

    /**
     * Get a user from the database, if the user does not exist, it will return undefined
     * @param userId {string}
     * @returns {Promise<IUser>}
     */
    public async getUser(userId: string): Promise<IUser> {
        return new Promise((resolve, reject) => {
            this.database.get('SELECT * FROM users WHERE id = ?', [userId], (err, row: IUser) => {
                if (err) {
                    reject(err);
                } else {
                    resolve(row);
                }
            });
        });
    }

    /**
     * Create a new user in the database
     * @param userId {number}
     * @param credits {number}
     * @returns 
     */
    public async createUser(userId: number, credits: number): Promise<void> {
        return new Promise((resolve, reject) => {
            this.database.run('INSERT INTO users (id, credits) VALUES (?, ?)', [userId, credits], (err) => {
                if (err) {
                    reject(err);
                } else {
                    resolve();
                }
            });
        });
    }
}