const fs = require("node:fs")
const http = require("node:http")
const https = require("node:https")
const crypto = require("node:crypto")
const config = require("../config.json")

async function downloadFile(url, destination, hash) {
    const file = fs.createWriteStream(destination)
    const protocol = url.startsWith("https://") ? http : https
    protocol.get(url, (response) => {
        response.pipe(file)

        file.on("error", (error) => {
            throw error
        })

        file.on("finish", async () => {
            file.close()
            try {
                if (getFileHash(destination) != hash) {
                    fs.unlinkSync(destination)
                    await downloadFile(url, destination, hash)
                }
            } catch (error) {
                reject(error)
            }
        })
    })
}

function getFileHash(filePath) {
    return new Promise((resolve, reject) => {
        const hash = crypto.createHash("sha256")
        const file = fs.createReadStream(filePath)
        file.on("error", (err) => {
            reject(err)
        })
        file.on("data", (chunk) => {
            hash.update(chunk)
        })
        file.on("end", () => {
            resolve(hash.digest("hex"))
        })
    })
}

async function checkFileHash(filePath) {
    try {
        const response = await fetch(`${config.api.base}${config.api.endpoints.fileHash}${filePath}`)
        const json = await response.json()
        if (json.error) {
            return json
        } else {
            if ((await getFileHash(filePath)) !== json.hash) {
                return false
            } else {
                return true
            }
        }
    } catch (error) {
        throw error
    }
}

async function checkFilesHash(root) {
    const files = await fs.promises.readdir(root, { recursive: true })
    for (const file of files) {
        try {
            await checkFileHash(file)
        } catch (error) {
            throw error
        }
    }
}

module.exports = {
    downloadFile,
    checkFileHash,
    checkFilesHash
}