import path from 'path';
import fs from 'fs';
import argon2 from 'argon2';
import { z } from 'zod';

export default class Member {
    prefix = "MEMBER"
    indices = null

    constructor(indices) {
        this.indices = indices
    }

    schema = z.object({
        id: z.number(),
        email: z.string().email(),
        firstName: z.string(),
        lastName: z.string(),
        password: z.string(),
        apps: z.array(z.string()),
        created: z.string()
    })

    isHashed = (s) => {return s.startsWith("$argon2")}

    async add(newMember, network = null) {
        const hash = await argon2.hash(newMember.password);
        newMember.password = hash
        newMember.apps = ["Dashboard"]

        try {
            global.db.addNode(this.prefix, newMember)
            if(network) {
                global.db.edge.add({
                    type: "IN",
                    from: `${this.prefix}-${global.db.getCurrentIndex(this)}`,
                    to: "NETWORK-1"
                })
            }
        } catch(e) {
            console.error(e)
            throw new global.ServerError(400, "Failed to add member!");
        }
    }

    async getPersonalData(id) {
        const filePath = path.join(global.db.PERSONAL_DATA_PATH,  id, "db.json");

        const [raw] = await Promise.all([
            fs.promises.readFile(filePath, "utf8"),
        ]);

        const result = raw.trim() ? JSON.parse(raw) : [];
        return result
    }

    getByNetwork(id) {
        let connections = db.MEMBER_IN_NETWORK.getByNetwork(id)
        let members = []
        connections.forEach((conn) => {
            members.push(this.getByID(conn.from))
        })
        return members
    }

    getByID(id) {
        if(typeof id === 'string') {
            id = id.split("-")[1]
        }
        return global.db.nodes[this.indices[0] + id - 1]
    }

    getByEmail(email) {
        for(let i=this.indices[0]; i<this.indices[1]; i++) {
            if(global.db.nodes[i].email === email) {
                return global.db.nodes[i]
            }
        }
        return null
    }
}