/*
 *   This file is a part of the SteamWar software.
 *
 *   Copyright (C) 2025 SteamWar.de-Serverteam
 *
 *   This program is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU Affero General Public License as published by
 *   the Free Software Foundation, either version 3 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 *   GNU Affero General Public License for more details.
 *
 *   You should have received a copy of the GNU Affero General Public License
 *   along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */

package de.steamwar.sql

import de.steamwar.sql.internal.useDb
import org.jetbrains.exposed.v1.core.ReferenceOption
import org.jetbrains.exposed.v1.core.dao.id.EntityID
import org.jetbrains.exposed.v1.core.dao.id.IdTable
import org.jetbrains.exposed.v1.core.eq
import org.jetbrains.exposed.v1.dao.IntEntity
import org.jetbrains.exposed.v1.dao.IntEntityClass
import org.jetbrains.exposed.v1.javatime.CurrentTimestamp
import org.jetbrains.exposed.v1.javatime.timestamp
import java.security.MessageDigest
import java.sql.Timestamp
import java.time.Instant

object NodeDownloadTable : IdTable<Int>("NodeDownload") {
    override val id = reference("NodeId", SchematicNodeTable, onDelete = ReferenceOption.CASCADE).uniqueIndex()
    val link = varchar("Link", 255).uniqueIndex()
    val timestamp = timestamp("Timestamp").defaultExpression(CurrentTimestamp)
}

class NodeDownload(id: EntityID<Int>) : IntEntity(id) {
    companion object : IntEntityClass<NodeDownload>(NodeDownloadTable) {
        const val LINK_BASE = "https://api.steamwar.de/download/"

        @JvmStatic
        fun getLink(schem: SchematicNode): String {
            if (schem.isDir()) throw IllegalArgumentException("Cannot get link for directory")

            val digest = MessageDigest.getInstance("SHA-1")
            digest.update("${Instant.now()}${schem.owner}${schem.nodeId}".toByteArray())
            val hash = digest.digest().joinToString("") { "%02x".format(it) }
            useDb {
                findByIdAndUpdate(schem.id.value) {
                    it.link = hash
                }
                    ?: new {
                        nodeId = schem.id.value
                        link = hash
                    }
            }
            return "${LINK_BASE}${hash}"
        }

        @JvmStatic
        fun get(link: String) =
            useDb {
                find { NodeDownloadTable.link eq link }.firstOrNull()
            }
    }

    var nodeId by NodeDownloadTable.id.transform({ EntityID(it, SchematicNodeTable) }, { it.value })
    var link by NodeDownloadTable.link
    var timestamp by NodeDownloadTable.timestamp.transform({ it.toInstant() }, { Timestamp.from(it) })

    override fun delete() =
        useDb {
            super.delete()
        }
}