import { parentPort } from 'node:worker_threads'
import { PeerInfo, Question, QuestionDb } from '../../types/basicTypes'
import { files, paths, readAndValidateFile } from '../../utils/files'
import utils from '../../utils/utils'
import { RecievedData } from '../../utils/actions'
import { removeCacheFromQuestion } from '../../utils/qdbUtils'
import { QuestionAddResponse } from '../../modules/api/submodules/qminingapi'
import logger from '../../utils/logger'
import { post } from '../../utils/networkUtils'
import {
    loginAndPostDataToAllPeers,
    peerToString,
} from '../../modules/api/p2p/p2putils'

export type QuestionsToPeersTaskObject = {
    type: 'sendQuestionsToPeers'
    data: {
        newQuestions: Question[]
        location: string
        subj: string
    }
}

export const handleQuestionsToPeers = async (
    _qdbs: QuestionDb[],
    msg: QuestionsToPeersTaskObject,
    workerIndex: number
): Promise<void> => {
    const { newQuestions, location, subj } = msg.data

    const domain = utils.ReadFile(paths.domainFile).trim()
    const peers = readAndValidateFile<PeerInfo[]>(files.peersFile)

    if (!peers || peers.length === 0 || newQuestions.length === 0) {
        parentPort.postMessage({
            msg: `From thread #${workerIndex}: sendQuestionsToPeers done`,
            workerIndex: workerIndex,
        })
        return
    }

    const dataToSend: RecievedData = {
        fromPeer: true,
        subj: subj,
        location: location,
        id: domain, // client ID
        version: 'P2P',
        quiz: newQuestions.map((question) => {
            return removeCacheFromQuestion({
                ...question,
                data: {
                    ...question.data,
                    source: domain,
                },
            })
        }),
    }

    const postData = (peer: PeerInfo, sessionCookie: string) => {
        return post<QuestionAddResponse>({
            hostname: peer.host,
            port: peer.port,
            http: peer.http,
            path: '/api/isAdding',
            bodyObject: dataToSend,
            cookie: `sessionID=${sessionCookie}`,
        })
    }

    const hadNewQuestions: string[] = []
    loginAndPostDataToAllPeers<QuestionAddResponse & { success: boolean }>(
        peers,
        postData,
        (peer, res) => {
            if (res.data?.totalNewQuestions > 0) {
                hadNewQuestions.push(peerToString(peer))
            }
        }
    )
    if (hadNewQuestions.length > 0) {
        logger.Log(
            `\t Peers that added new questions: ${hadNewQuestions.join(', ')}`
        )
    }

    parentPort.postMessage({
        msg: `From thread #${workerIndex}: sendQuestionsToPeers done`,
        workerIndex: workerIndex,
    })
}
