package Web

import Log.LogGetter
import aas1
import aas2
import aas3
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.kotlin.registerKotlinModule
import config
import database.FlightFilter
import io.javalin.Javalin
import io.javalin.apibuilder.ApiBuilder.before
import io.javalin.apibuilder.ApiBuilder.get
import io.javalin.apibuilder.ApiBuilder.post
import org.tinylog.Logger

@Suppress("unused")
/**
 * Start WebUI Server
 */
class WebUI {
    // regex untuk date dengan format YYYY-MM-DD
    private val dateRegex1 = """\d{4}-\d{2}-\d{2}""".toRegex()
    private val mapper = ObjectMapper().registerKotlinModule()
    private var app: Javalin = Javalin.create { cfg ->
        cfg.staticFiles.add("/")
        cfg.router.apiBuilder {
            get("/") {
                if (config.WebUsername == it.cookie("username")) {
                    Logger.info { "${it.ip()} logged in as ${it.cookie("username")}, forward to home.html" }
                    it.redirect("home.html")
                } else {
                    Logger.info { "${it.ip()} have not logged in, forward to login.html" }
                    it.redirect("login.html")
                }
            }
            post("login.html") {
                val username = it.formParam("username")
                val password = it.formParam("password")
                if (config.WebUsername == username && config.WebPassword == password) {
                    Logger.info { "${it.ip()} login successful for user $username" }
                    it.cookie("username", username)
                    it.redirect("home.html")
                } else {
                    Logger.info { "${it.ip()} Login failed for user $username" }
                    it.redirect("/login.html?error=1")
                }
            }

            get("getLogs") {
                var date = it.queryParam("date")
                Logger.info { "${it.ip()} User ${it.cookie("username")} requested logs for date: $date" }
                if (date != null) {
                    if (date.isNotEmpty()) {
                        if (dateRegex1.matches(date)) {
                            // ketemu format YYYY-MM-DD,  convert format ke dd/MM/yyyy
                            val parts = date.split("-")
                            date = "${parts[2]}/${parts[1]}/${parts[0]}"
                        }
                        val logs = LogGetter().getLog(date)
                        if (logs.isNotEmpty()) {
                            it.json(logs)
                        } else it.status(404).json(webReply(message = "No logs found for the specified date"))
                    } else it.status(400).json(webReply(message = "Date parameter is empty"))
                } else it.status(400).json(webReply(message = "Please provide a date"))
            }

            get("logout") {
                Logger.info { "${it.ip()} User ${it.cookie("username")} logged out" }
                it.removeCookie("username")
                it.redirect("login.html")
            }

            

            get("getSetting") {
                val fd = farmData(
                    config.ActiveMQ_BrokerURL,
                    config.ActiveMQ_Username,
                    config.ActiveMQ_Password,
                    config.ActiveMQ_QueueName
                )
                val aas1 = aasData(config.MySQL_AAS1, config.MySQL_AAS1_Username, config.MySQL_AAS1_Password)
                val aas2 = aasData(config.MySQL_AAS2, config.MySQL_AAS2_Username, config.MySQL_AAS2_Password)
                val aas3 = aasData(config.MySQL_AAS3, config.MySQL_AAS3_Username, config.MySQL_AAS3_Password)
                val setting = getSetting(fd, aas1, aas2, aas3)
                it.json(setting)
            }
            post("saveFARM") {

                try {
                    val fd = it.bodyAsClass(saveFARM::class.java)
                    config.ActiveMQ_BrokerURL = fd.farm.url
                    config.ActiveMQ_Username = fd.farm.username
                    config.ActiveMQ_Password = fd.farm.password
                    config.ActiveMQ_QueueName = fd.farm.queue
                    config.Save()
                    it.json(webReply(message = "success"))
                } catch (e: Exception) {
                    val str = "Error saving FARM settings: ${e.message}"
                    Logger.error { str }
                    it.status(500).json(webReply(message = str))
                }
            }
            post("saveAAS") {

                try {
                    val ax = it.bodyAsClass(saveAAS::class.java)
                    config.MySQL_AAS1 = ax.aas1.url
                    config.MySQL_AAS1_Username = ax.aas1.username
                    config.MySQL_AAS1_Password = ax.aas1.password
                    config.MySQL_AAS2 = ax.aas2.url
                    config.MySQL_AAS2_Username = ax.aas2.username
                    config.MySQL_AAS2_Password = ax.aas2.password
                    config.MySQL_AAS3 = ax.aas3.url
                    config.MySQL_AAS3_Username = ax.aas3.username
                    config.MySQL_AAS3_Password = ax.aas3.password
                    config.Save()
                    it.json(webReply(message = "success"))

                } catch (e: Exception) {
                    val str = "Error saving AAS settings: ${e.message}"
                    Logger.error { str }
                    it.status(500).json(webReply(message = str))
                }
            }

            get("getBroadcastZones") {
                val id = it.queryParam("id")?.toIntOrNull() ?: 0
                val aas = when (id) {
                    1 -> aas1
                    2 -> aas2
                    3 -> aas3
                    else -> null
                }
                if (aas != null) {
                    aas.GetBroadcastZones { success, zones ->
                        if (success) {
                            it.json(zones)
                        } else {
                            it.status(500).json(webReply(message = "Failed to retrieve broadcast zones"))
                        }
                    }
                } else it.status(400).json(webReply(message = "Invalid AAS id"))
            }

            get("getAirlineCodes") {
                val id = it.queryParam("id")?.toIntOrNull() ?: 0
                val aas = when (id) {
                    1 -> aas1
                    2 -> aas2
                    3 -> aas3
                    else -> null
                }
                if (aas != null) {
                    aas.GetAirlineCode { success, codes ->
                        if (success) {
                            it.json(codes)
                        } else {
                            it.status(500).json(webReply(message = "Failed to retrieve airline codes"))
                        }
                    }
                } else it.status(400).json(webReply(message = "Invalid AAS id"))
            }

            post("FlightFilter") {
                try {
                    val req = it.bodyAsClass(webRequest::class.java)
                    val aas_id = req.aas_id.toIntOrNull() ?: 0
                    val aas = when (aas_id) {
                        1 -> aas1
                        2 -> aas2
                        3 -> aas3
                        else -> throw Exception("Invalid AAS id")
                    }
                    when (req.command) {
                        "get" -> {
                            if (aas != null) {
                                aas.GetFlightFilterTable { success, filters ->
                                    if (success) {
                                        it.json(webReply(command = req.command, message = "success"))
                                    } else throw Exception("Failed to retrieve Flight Filter data")
                                }
                            } else throw Exception("Invalid AAS id")
                        }
                        "clear" ->{
                            if (aas != null) {
                                aas.ClearFlightFilterTable { success ->
                                    if (success) {
                                        it.json(webReply(command = req.command, message = "success"))
                                    } else throw Exception("Failed to clear Flight Filter data")
                                }
                            } else throw Exception("Invalid AAS id")
                        }
                        "add" ->{
                            val data = mapper.readValue(req.data, FlightFilter::class.java)
                            if (aas != null) {
                                aas.InsertFlightFilter(data) { success ->
                                    if (success) {
                                        it.json(webReply(command = req.command, data=req.data, message = "success"))
                                    } else throw Exception("Failed to add Flight Filter data")
                                }
                            } else throw Exception("Invalid AAS id")
                        }
                        "delete"->{
                            // data is index of flight filter to delete
                            val data = req.data.toIntOrNull() ?: 0
                            if (aas != null) {
                                aas.DeleteFlightFilter(data) { success ->
                                    if (success) {
                                        it.json(webReply(command = req.command, data=req.data, message = "success"))
                                    } else throw Exception("Failed to delete Flight Filter data")
                                }
                            } else throw Exception("Invalid AAS id")
                        }
                        "patch"->{
                            val data = mapper.readValue(req.data, FlightFilter::class.java)
                            if (aas != null) {
                                aas.PatchFlightFilter(data.id, data) { success ->
                                    if (success) {
                                        it.json(webReply(command = req.command, data=req.data, message = "success"))
                                    } else throw Exception("Failed to patch Flight Filter data")
                                }
                            } else throw Exception("Invalid AAS id")
                        }
                        else -> throw Exception("Invalid FlightFilter command")
                    }
                } catch (e: Exception) {
                    val str = "Error parsing FlightFilter request: ${e.message}"
                    Logger.error { str }
                    it.status(500).json(webReply(message = str))
                }
            }

            before("home.html") {
                if (config.WebUsername != it.cookie("username")) {
                    Logger.info { "${it.ip()} Have not logged in, forward to login.html" }
                    it.redirect("login.html")
                }
            }
            before("log.html") {
                if (config.WebUsername != it.cookie("username")) {
                    Logger.info { "${it.ip()} Have not logged in, forward to login.html" }
                    it.redirect("login.html")
                }
            }
            before("setting.html") {
                if (config.WebUsername != it.cookie("username")) {
                    Logger.info { "${it.ip()} Have not logged in, forward to login.html" }
                    it.redirect("login.html")
                }
            }
        }

    }

    /**
     * Start WebUI Server
     */
    fun Start() {
        app.start(config.WebPort)
    }

    /**
     * Stop WebUI Server
     */
    fun Stop() {
        app.stop()
    }


}