import { AxiosError, AxiosResponse } from "axios";
import crypto from "crypto";
import { ProofOfOriginError } from "../types/errors/ProofOfAuthenticityError";
import { readFileSync } from "fs";
import path from "path";

const VERIFICATION_CONSTANT = "verified";

/**
 * @description Scorechain provide a proof of authenticity conducted using JWT and asymetrical encryption of the payload.
 * The following function will help you with veryfying this proof of authenticity.
 */
export function proofOfAuthenticityVerifier(
    data: Record<string, unknown>,
    signature: string,
    publicKey: string,
    headerServerTimestamp: string
) {
    try {
        const payload = JSON.stringify({ data, timestamp: headerServerTimestamp });
        const verification = crypto.createVerify("RSA-SHA256").update(payload).verify(publicKey, signature, "hex");

        if (!verification) {
            throw new ProofOfOriginError();
        }
        return VERIFICATION_CONSTANT;
    } catch (_) {
        throw new ProofOfOriginError();
    }
}

/**
 * @description Scorechain provide a proof of authenticity conducted using JWT and asymetrical encryption of the payload.
 * The following function is an adapter from the last function specificially for query realised with axios.
 */
export function proofOfAuthenticityVerifierAdapterForAxios(axiosCallResponse: AxiosResponse | AxiosError) {
    const publicKey = readFileSync(path.join(__dirname, "../../scorechainPublicKey", "public.pem")).toString("utf-8");
    if (axiosCallResponse instanceof AxiosError) {
        const payload = axiosCallResponse.response?.data as Record<string, unknown>;
        const token: string = axiosCallResponse.response?.headers["x-signature"] as string;
        const headerServerTimestamp: string = axiosCallResponse.response?.headers["x-server-time"] as string;
        proofOfAuthenticityVerifier(payload, token, publicKey, headerServerTimestamp);
    } else {
        const payload = axiosCallResponse.data as Record<string, unknown>;
        const token: string = axiosCallResponse.headers["x-signature"] as string;
        const headerServerTimestamp: string = axiosCallResponse.headers["x-server-time"] as string;
        proofOfAuthenticityVerifier(payload, token, publicKey, headerServerTimestamp);
    }
}
