import { db } from './config.mjs';

export const enum Role {
    none = 'none',
    viewer = 'viewer',
    editor = 'editor',
    owner = 'owner',
}

export class DocUserRoleDb {
    get(userId: string, docId: string): Promise<Role> {
        return new Promise((resolve, reject) => {
            db.get<IDocUserRoleRecord>('SELECT * FROM document_user_role WHERE user_id = ? AND doc_id = ?', [userId, docId], (err, row) => {
                if (err) {
                    console.error(err);
                    return reject(err);
                }

                resolve(row ? row.role : Role.none);
            });
        });
    }

    getByDocId(docId: string): Promise<IDocUserRole[]> {
        return new Promise((resolve, reject) => {
            db.all<IDocUserRoleRecord>('SELECT * FROM document_user_role WHERE doc_id = ?', [docId], (err, row) => {
                if (err) {
                    console.error(err);
                    return reject(err);
                }

                resolve(row.map(convert));
            });
        });
    } 

    getByUserId(userId: string): Promise<IDocUserRole[]> {
        return new Promise((resolve, reject) => {
            db.all<IDocUserRoleRecord>('SELECT * FROM document_user_role WHERE user_id = ?', [userId], (err, row) => {
                if (err) {
                    console.error(err);
                    return reject(err);
                }

                resolve(row.map(convert));
            });
        });
    }

    insert(userId: string, docId: string, role: Role): Promise<IDocUserRole> {
        return new Promise((resolve, reject) => {
            db.run('INSERT INTO document_user_role (user_id, doc_id, role) VALUES (?, ?, ?)', [userId, docId, role], (err) => {
                if (err) {
                    console.error(err);
                    return reject('internal error: insert doc error');
                }

                resolve({ userId, docId, role });
            });
        });
    }

    update(userId: string, docId: string, role: Role): Promise<IDocUserRole> {
        return new Promise((resolve, reject) => {
            db.run('UPDATE document_user_role SET role = ? WHERE user_id = ? AND doc_id = ?', [role, userId, docId], (err) => {
                if (err) {
                    console.error(err);
                    return reject('internal error: insert doc error');
                }

                resolve({ userId, docId, role });
            });
        });
    }

    async set(userId: string, docId: string, role: Role) {
        const r = await this.get(userId, docId);

        if (r === Role.none) {
            await this.insert(userId, docId, role);
        } else {
            await this.update(userId, docId, role);
        }
    }

    delete(userId: string, docId: string): Promise<void> {
        return new Promise((resolve, reject) => {
            db.run('DELETE FROM document_user_role WHERE user_id = ? AND doc_id = ?', [userId, docId], (err: any) => {
                if (err) {
                    console.error(err);
                    return reject(err);
                }

                resolve();
            });
        });
    }

    deleteByDocId(docId: string): Promise<void> {
        return new Promise((resolve, reject) => {
            db.run('DELETE FROM document_user_role WHERE doc_id = ?', [docId], (err: any) => {
                if (err) {
                    console.error(err);
                    return reject(err);
                }

                resolve();
            });
        });
    }
}

export interface IDocUserRole {
    userId: string;
    docId: string;
    role: Role;
}

interface IDocUserRoleRecord {
    user_id: string;
    doc_id: string;
    role: Role;
}

function convert(d: IDocUserRoleRecord): IDocUserRole {
    return { userId: d.user_id, docId: d.doc_id, role: d.role };
}