/**
 * ==========================================================
 * Smart Attendance System
 * AI Test Console
 * ==========================================================
 *
 * Tests the Backend AI Module.
 *
 * This console communicates ONLY with the Backend.
 *
 * Backend
 *      ↓
 * AI Controller
 *      ↓
 * AI Service
 *      ↓
 * Python AI
 *      ↓
 * InsightFace
 *      ↓
 * Database
 *
 * ==========================================================
 */

const axios = require("axios");
const FormData = require("form-data");
const fs = require("fs");
const path = require("path");
const readline = require("readline");

//==========================================================
// Configuration
//==========================================================

const BACKEND_URL =
    process.env.BACKEND_URL ||
    "http://localhost:5000/api/ai";

const IMAGE_FOLDER = path.join(
    __dirname,
    "test_images"
);

//==========================================================
// Readline
//==========================================================

const rl = readline.createInterface({

    input: process.stdin,

    output: process.stdout

});

//==========================================================
// Colors
//==========================================================

const Color = {

    reset: "\x1b[0m",

    bright: "\x1b[1m",

    dim: "\x1b[2m",

    red: "\x1b[31m",

    green: "\x1b[32m",

    yellow: "\x1b[33m",

    blue: "\x1b[34m",

    cyan: "\x1b[36m",

    white: "\x1b[37m"

};

//==========================================================
// Utility Printing
//==========================================================

function line() {

    console.log(
        "============================================================"
    );

}

function title(text) {

    line();

    console.log(

        Color.cyan +

        Color.bright +

        text +

        Color.reset

    );

    line();

}

function success(text) {

    console.log(

        Color.green +

        "✔ " +

        text +

        Color.reset

    );

}

function fail(text) {

    console.log(

        Color.red +

        "✖ " +

        text +

        Color.reset

    );

}

function info(text) {

    console.log(

        Color.blue +

        "ℹ " +

        text +

        Color.reset

    );

}

function warning(text) {

    console.log(

        Color.yellow +

        "⚠ " +

        text +

        Color.reset

    );

}

//==========================================================
// Timer
//==========================================================

function startTimer() {

    return Date.now();

}

function stopTimer(start) {

    return Date.now() - start;

}

//==========================================================
// Pause
//==========================================================

function pause() {

    return new Promise(resolve => {

        rl.question(

            "\nPress ENTER to continue...",

            () => resolve()

        );

    });

}

//==========================================================
// Menu
//==========================================================

async function menu() {

    console.clear();

    title(

        "SMART ATTENDANCE AI TEST CONSOLE"

    );

    console.log(

        Color.white +

        "Backend : " +

        BACKEND_URL +

        Color.reset

    );

    console.log();

    console.log("1. Health Check");

    console.log("2. Face Detection");

    console.log("3. Face Embedding");

    console.log("4. Train Student");

    console.log("5. Recognize Student");

    console.log("6. Run All Tests");

    console.log("0. Exit");

    console.log();

    rl.question(

        "Select Option : ",

        async answer => {

            switch (answer.trim()) {

                case "1":

                    await testHealth();

                    break;

                case "2":

                    await testDetect();

                    break;

                case "3":

                    await testEmbed();

                    break;

                case "4":

                    await testTrain();

                    break;

                case "5":

                    await testRecognize();

                    break;

                case "6":

                    await runAllTests();

                    break;

                case "0":

                    rl.close();

                    process.exit(0);

                    break;

                default:

                    warning(

                        "Invalid option."

                    );

                    await pause();

            }

            menu();

        }

    );

}

//==========================================================
// Placeholder Functions
//==========================================================

//==========================================================
// Health Check
//==========================================================

async function testHealth() {

    console.clear();

    title("AI Health Check");

    const start = startTimer();

    try {

        info("Sending request...");

        const response = await axios.get(

            `${BACKEND_URL}/health`

        );

        const elapsed = stopTimer(start);

        console.log();

        success("Backend responded successfully.");

        console.log();

        console.log("HTTP Status      :", response.status);

        console.log("Success          :", response.data.success);

        console.log("Message          :", response.data.message);

        console.log("Response Time    :", elapsed + " ms");

    }

    catch (error) {

        fail("Health Check Failed");

        console.log();

        if (error.response) {

            console.log(error.response.data);

        }

        else {

            console.log(error.message);

        }

    }

    await pause();

}

//==========================================================
// Face Detection
//==========================================================

async function testDetect() {

    console.clear();

    title("Face Detection Test");

    const imagePath = path.join(

        IMAGE_FOLDER,

        "1.jpeg"

    );

    if (!fs.existsSync(imagePath)) {

        fail("Image not found.");

        console.log(imagePath);

        await pause();

        return;

    }

    const form = new FormData();

    form.append(

        "image",

        fs.createReadStream(imagePath)

    );

    const start = startTimer();

    try {

        info("Uploading image...");

        const response = await axios.post(

            `${BACKEND_URL}/detect`,

            form,

            {

                headers: form.getHeaders(),

                maxBodyLength: Infinity,

                maxContentLength: Infinity,

                timeout: 300000

            }

        );

        const elapsed = stopTimer(start);

        const result = response.data;

        success("Detection completed.");

        console.log();

        console.log("HTTP Status      :", response.status);

        console.log("Success          :", result.success);

        console.log("Message          :", result.message);

        console.log();

        if (result.data) {

            console.log(

                "Faces Detected   :",

                result.data.faces_detected

            );

            console.log(

                "Processing Time  :",

                result.data.processing_time_ms,

                "ms"

            );

        }

        console.log(

            "Backend Time     :",

            elapsed,

            "ms"

        );

    }

    catch (error) {

        fail("Detection Failed");

        console.log();

        if (error.response) {

            console.log(error.response.data);

        }

        else {

            console.log(error.message);

        }

    }

    await pause();

}

//==========================================================
// Face Embedding
//==========================================================

async function testEmbed() {

    console.clear();

    title("Face Embedding Test");

    const imagePath = path.join(

        IMAGE_FOLDER,

        "1.jpeg"

    );

    if (!fs.existsSync(imagePath)) {

        fail("Image not found.");

        console.log(imagePath);

        await pause();

        return;

    }

    const form = new FormData();

    form.append(

        "image",

        fs.createReadStream(imagePath)

    );

    const start = startTimer();

    try {

        info("Generating embedding...");

        const response = await axios.post(

            `${BACKEND_URL}/embed`,

            form,

            {

                headers: form.getHeaders(),

                maxBodyLength: Infinity,

                maxContentLength: Infinity,

                timeout: 300000

            }

        );

        const elapsed = stopTimer(start);

        const result = response.data;

        success("Embedding generated.");

        console.log();

        console.log("HTTP Status      :", response.status);

        console.log("Success          :", result.success);

        console.log("Message          :", result.message);

        console.log();

        if (result.data) {

            console.log(

                "Embeddings       :",

                result.data.embeddings.length

            );

            console.log(

                "Dimension        :",

                result.data.embeddings[0].embedding_dimension

            );

            console.log(

                "Processing Time  :",

                result.data.processing_time_ms,

                "ms"

            );

        }

        console.log(

            "Backend Time     :",

            elapsed,

            "ms"

        );

    }

    catch (error) {

        fail("Embedding Failed");

        console.log();

        if (error.response) {

            console.log(error.response.data);

        }

        else {

            console.log(error.message);

        }

    }

    await pause();

}

//==========================================================
// Train Student
//==========================================================

async function testTrain() {

    console.clear();

    title("Student Training Test");

    const studentId = "BEC001";

    const images = [

        path.join(IMAGE_FOLDER, "1.jpeg"),

        path.join(IMAGE_FOLDER, "2.jpeg"),

        path.join(IMAGE_FOLDER, "3.jpeg")

    ];

    //--------------------------------------------

    for (const image of images) {

        if (!fs.existsSync(image)) {

            fail("Missing image:");

            console.log(image);

            await pause();

            return;

        }

    }

    //--------------------------------------------

    const form = new FormData();

    form.append(

        "student_id",

        studentId

    );

    for (const image of images) {

        form.append(

            "images",

            fs.createReadStream(image)

        );

    }

    //--------------------------------------------

    const start = startTimer();

    try {

        info("Uploading training images...");

        const response = await axios.post(

            `${BACKEND_URL}/train`,

            form,

            {

                headers: form.getHeaders(),

                maxBodyLength: Infinity,

                maxContentLength: Infinity,

                timeout: 300000

            }

        );

        const elapsed = stopTimer(start);

        const result = response.data;

        success("Training completed.");

        console.log();

        console.log("HTTP Status          :", response.status);

        console.log("Student ID           :", result.data.student_id);

        console.log("Images Received      :", result.data.images_received);

        console.log("Images Processed     :", result.data.images_processed);

        console.log("Faces Detected       :", result.data.faces_detected);

        console.log("Embeddings Generated :", result.data.embeddings_generated);

        console.log("Duplicates Removed   :", result.data.duplicates_removed);

        console.log("Embedding Dimension  :", result.data.average_embedding.length);

        console.log("Python Time          :", result.data.processing_time_ms + " ms");

        console.log("Backend Time         :", elapsed + " ms");

    }

    catch (error) {

        fail("Training Failed");

        console.log();

        if (error.response) {

            console.log(error.response.data);

        }

        else {

            console.log(error.message);

        }

    }

    await pause();

}

//==========================================================
// Recognize Student
//==========================================================

async function testRecognize() {

    console.clear();

    title("Student Recognition Test");

    const imagePath = path.join(

        IMAGE_FOLDER,

        "recognize.jpeg"

    );

    //--------------------------------------------

    if (!fs.existsSync(imagePath)) {

        fail("recognize.jpeg not found.");

        await pause();

        return;

    }

    //--------------------------------------------

    const form = new FormData();

    form.append(

        "image",

        fs.createReadStream(imagePath)

    );

    //--------------------------------------------

    const start = startTimer();

    try {

        info("Recognizing student...");

        const response = await axios.post(

            `${BACKEND_URL}/recognize`,

            form,

            {

                headers: form.getHeaders(),

                maxBodyLength: Infinity,

                maxContentLength: Infinity,

                timeout: 300000

            }

        );

        const elapsed = stopTimer(start);

        const result = response.data;

        success("Recognition completed.");

        console.log();

        console.log("HTTP Status :", response.status);

        console.log();

        console.log("Student ID  :", result.data.student_id);

        console.log("Matched     :", result.data.matched);

        console.log("Similarity  :", result.data.similarity);

        console.log("Confidence  :", result.data.confidence);

        console.log("Python Time :", result.data.processing_time_ms + " ms");

        console.log("Backend Time:", elapsed + " ms");

    }

    catch (error) {

        fail("Recognition Failed");

        console.log();

        if (error.response) {

            console.log(error.response.data);

        }

        else {

            console.log(error.message);

        }

    }

    await pause();

}

//==========================================================
// Run All Tests
//==========================================================

async function runAllTests() {

    console.clear();

    title("RUNNING COMPLETE AI TEST SUITE");

    const tests = [

        {

            name: "Health Check",

            fn: testHealth,

            pass: false

        },

        {

            name: "Face Detection",

            fn: testDetect,

            pass: false

        },

        {

            name: "Face Embedding",

            fn: testEmbed,

            pass: false

        },

        {

            name: "Student Training",

            fn: testTrain,

            pass: false

        },

        {

            name: "Student Recognition",

            fn: testRecognize,

            pass: false

        }

    ];

    let passed = 0;

    for (const test of tests) {

        console.clear();

        title(test.name);

        try {

            await test.fn();

            test.pass = true;

            passed++;

        }

        catch (err) {

            test.pass = false;

        }

    }

    console.clear();

    title("FINAL RESULT");

    tests.forEach(test => {

        if (test.pass) {

            success(test.name);

        }

        else {

            fail(test.name);

        }

    });

    console.log();

    console.log(

        "Passed :",

        passed,

        "/",

        tests.length

    );

    console.log();

    if (passed === tests.length) {

        success("ALL TESTS PASSED");

    }

    else {

        warning("Some tests failed.");

    }

    await pause();

}//==========================================================
// Run All Tests
//==========================================================

async function runAllTests() {

    console.clear();

    title("RUNNING COMPLETE AI TEST SUITE");

    const tests = [

        {

            name: "Health Check",

            fn: testHealth,

            pass: false

        },

        {

            name: "Face Detection",

            fn: testDetect,

            pass: false

        },

        {

            name: "Face Embedding",

            fn: testEmbed,

            pass: false

        },

        {

            name: "Student Training",

            fn: testTrain,

            pass: false

        },

        {

            name: "Student Recognition",

            fn: testRecognize,

            pass: false

        }

    ];

    let passed = 0;

    for (const test of tests) {

        console.clear();

        title(test.name);

        try {

            await test.fn();

            test.pass = true;

            passed++;

        }

        catch (err) {

            test.pass = false;

        }

    }

    console.clear();

    title("FINAL RESULT");

    tests.forEach(test => {

        if (test.pass) {

            success(test.name);

        }

        else {

            fail(test.name);

        }

    });

    console.log();

    console.log(

        "Passed :",

        passed,

        "/",

        tests.length

    );

    console.log();

    if (passed === tests.length) {

        success("ALL TESTS PASSED");

    }

    else {

        warning("Some tests failed.");

    }

    await pause();

}

//==========================================================
// Start
//==========================================================

menu();