import OrderedObject from "./OrderedObject.js"
const argon2 = require("argon2")
const { z } = require("zod")

export default class Members extends OrderedObject {
    addressSchema = z.object({
        address1: z.string(),
        address2: z.string().optional(),
        zip: z.string().regex(/^\d{5}(-\d{4})?$/),
        state: z.string(),
        city: z.string()
    })
    schema = z.object({
        id: z.number(),
        email: z.string().email(),
        firstName: z.string(),
        lastName: z.string(),
        password: z.string(),
        tokenUsed: z.string().regex(
            /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i,
            "Invalid UUID"
        ),
        joined: z.string(),
        address: this.addressSchema,
    })

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

    save(member) {
        let id = `MEMBER-${member.id}`
        let result = this.schema.safeParse(member)
        if(result.success) {
            try {
                super.add(id, member)
            } catch(e) {
                console.error(e)
                throw e
            }
        } else {
            console.error("Failed parsing member: ", result.error)
            throw new global.ServerError(400, "Invalid Member Data!: ");
        }
    }

    async add(newMember, tokenID) {
        newMember.tokenUsed = tokenID
        const hash = await argon2.hash(newMember.password);
        newMember.password = hash
        newMember.joined = global.currentTime()
        newMember.id = this.entries.length+1
        this.save(newMember)
    }

    get(id) {
        return this.entries[this.ids[id]]
    }

    getByEmail(email) {
        for(let i=0; i<this.entries.length; i++) {
            if(this.entries[i].email === email) {
                return this.entries[i]
            }
        }
        return null
    }

    getIDFromEmail(email) {
        let index = 0
        for(let i=0; i<this.entries.length; i++) {
            if(this.entries[i].email === email) {
                index = i
                break
            }
        }
        return Object.entries(this.ids)[index][0]
    }
}