import type { Faisan } from "../../faisan/src/helpers"

interface Env {}

const MAXU32 = 4294967295

export class User {
    env: Env
    state: DurableObjectState

    constructor(state: DurableObjectState, env: Env) {
        this.state = state
        this.env = env
    }

    async fetch(request: Request): Promise<Response> {
        console.log("parsing json")
        let json = <Faisan.Cmd>await request.json()
        console.log(`parsed ${JSON.stringify(json)}`)
        return await this.fetchCmd(json)
    }

    async fetchCmd(json: Faisan.Cmd): Promise<Response> {
        let headers = new Headers();
        headers.set("Content-Type", "application/json");
        // Faisan
        if ("ListProjets" in json) {
            return new Response(JSON.stringify(await this.listprojets()), { headers })
        }

        if ("CreateProjet" in json) {
            let id = crypto.randomUUID()
            let t = ('0000000000' + (MAXU32 - Date.now())).slice(-10)
            await Promise.all([
                this.state.storage.put(
                    `pi.${id}`,
                    {
                        name: json.CreateProjet.name,
                        porteur: json.CreateProjet.porteur,
                        tel: json.CreateProjet.tel,
                        adresse: json.CreateProjet.adresse,
                        simulation: json.CreateProjet.simulation,
                        t,
                    }
                ),
                this.state.storage.put(
                    `pt.${t}`,
                    { id: id, name: json.CreateProjet.name },
                )
            ])
            return new Response(id, { headers })
        }

        if ("SaveProjet" in json) {
            let x: undefined | Faisan.GetProjetResp = await this.state.storage.get(`pi.${json.SaveProjet.id}`)
            if (x) {
                x.name = json.SaveProjet.name || x.name
                x.porteur = json.SaveProjet.porteur || x.porteur
                x.tel = json.SaveProjet.tel || x.tel
                x.adresse = json.SaveProjet.adresse || x.adresse
                x.simulation = json.SaveProjet.simulation || x.simulation
                await this.state.storage.put(`pi${json.SaveProjet.id}`, x)
            }
            return new Response("null", { headers })
        }

        if ("GetProjet" in json) {
            let resp = <Faisan.GetProjetResp> await this.state.storage.get(
                `pi.${json.GetProjet}`
            )
            console.log("resp", JSON.stringify(resp))
            if(resp) {
                resp.id = json.GetProjet
            }
            return new Response(JSON.stringify(resp || null), { headers })
        }

        if ("DelProjet" in json) {
            let t: undefined | { t: string } = await this.state.storage.get(`pi.${json.DelProjet.id}`)
            if(t) {
                await Promise.all([
                    this.state.storage.delete(
                        `pi.${json.DelProjet.id}`
                    ),
                    this.state.storage.delete(
                        `pt.${t.t}`
                    )
                ])
            }
            return new Response("null", { headers })
        }

        const exhaustiveCheck: never = json;
        throw new Error(exhaustiveCheck)
    }

    async listprojets(from?: number): Promise<Faisan.ListProjetsResp> {
        let opts = {
            prefix: 'pt.',
            limit: 100,
            startAfter: from ? `pt.${('0000000000' + (MAXU32 - from)).slice(-10)}` : undefined
        }
        let keys: Map<string, { id: string, name: string }> = await this.state.storage.list(opts)
        console.log(opts, [...keys.entries()])
        let result: Faisan.ListProjetsResp = []
        for (let v of keys.values()) {
            result.push({
                id: v.id,
                name: v.name
            })
        }
        return result
    }
}