class Leaderboard {
    constructor() {
        this.canvas = null
        this.ctx = null
        this.songId = null
        this.difficulty = null
        this.leaderboardData = []
        this.currentMonth = ""
        this.visible = false
        this.draw = null
        this.keyboard = null
    }

    init() {
        this.canvas = document.getElementById("leaderboard-canvas")
        if (!this.canvas) {
            console.error("Leaderboard canvas not found!")
            return false
        }
        this.ctx = this.canvas.getContext("2d")

        var resolution = settings.getItem("resolution")
        var noSmoothing = resolution === "low" || resolution === "lowest"
        if (noSmoothing) {
            this.ctx.imageSmoothingEnabled = false
        }

        this.draw = new CanvasDraw(noSmoothing)

        // Keyboard controls
        this.keyboard = new Keyboard({
            confirm: ["enter", "escape", "don_l", "don_r"],
            back: ["escape"],
            left: ["left", "ka_l"],
            right: ["right", "ka_r"]
        }, this.keyPress.bind(this))

        pageEvents.add(this.canvas, ["mousedown", "touchstart"], this.onClose.bind(this))
        return true
    }

    keyPress(pressed, name) {
        if (!pressed || !this.visible) {
            return
        }
        if (name === "confirm" || name === "back") {
            this.close()
        } else if (name === "left") {
            this.changeDifficulty(-1)
        } else if (name === "right") {
            this.changeDifficulty(1)
        }
    }

    async display(songId, difficulty) {
        this.songId = songId
        this.difficulty = difficulty
        this.visible = true

        loader.changePage("leaderboard", false)

        // Initialize after page is loaded
        if (!this.init()) {
            console.error("Failed to initialize leaderboard")
            return
        }

        // Fetch leaderboard data
        await this.fetchLeaderboard()

        // Start rendering
        this.redrawRunning = true
        this.redrawBind = this.redraw.bind(this)
        this.redraw()

        assets.sounds["se_don"].play()
    }

    async fetchLeaderboard() {
        // Validate songId is a valid number
        if (!this.songId || isNaN(parseInt(this.songId))) {
            console.error("Invalid song ID for leaderboard:", this.songId)
            this.leaderboardData = []
            return
        }

        try {
            var response = await loader.ajax(
                `${gameConfig.basedir || "/"}api/leaderboard/get?song_id=${parseInt(this.songId)}&difficulty=${this.difficulty}`
            )
            var data = JSON.parse(response)
            if (data.status === "ok") {
                this.leaderboardData = data.leaderboard || []
                this.currentMonth = data.month || ""
            } else {
                this.leaderboardData = []
            }
        } catch (e) {
            console.error("Failed to fetch leaderboard:", e)
            this.leaderboardData = []
        }
    }


    changeDifficulty(direction) {
        var difficulties = ["easy", "normal", "hard", "oni", "ura"]
        var currentIndex = difficulties.indexOf(this.difficulty)
        if (currentIndex === -1) {
            return
        }

        var newIndex = (currentIndex + direction + difficulties.length) % difficulties.length
        this.difficulty = difficulties[newIndex]

        this.fetchLeaderboard().then(() => {
            assets.sounds["se_ka"].play()
        })
    }

    onClose(event) {
        if (!this.visible) {
            return
        }

        var rect = this.canvas.getBoundingClientRect()
        var x = (event.offsetX || event.touches[0].pageX - rect.left)
        var y = (event.offsetY || event.touches[0].pageY - rect.top)

        // Check if clicked outside modal - updated dimensions
        var centerX = this.canvas.width / 2
        var centerY = this.canvas.height / 2
        var modalWidth = 880  // Updated from 800
        var modalHeight = 640  // Updated from 600

        if (x < centerX - modalWidth / 2 || x > centerX + modalWidth / 2 ||
            y < centerY - modalHeight / 2 || y > centerY + modalHeight / 2) {
            this.close()
        }
    }

    close() {
        this.visible = false
        this.redrawRunning = false

        if (this.keyboard) {
            this.keyboard.clean()
        }

        assets.sounds["se_cancel"].play()

        // Return to song select - get touchEnabled from global or default to false
        setTimeout(() => {
            var touchEnabled = typeof window.touchEnabled !== 'undefined' ? window.touchEnabled : false
            new SongSelect(false, false, touchEnabled)
        }, 100)
    }

    redraw() {
        if (!this.redrawRunning) {
            return
        }

        requestAnimationFrame(this.redrawBind)

        var winW = innerWidth
        var winH = innerHeight
        var ratio = winH / 720

        this.canvas.width = winW
        this.canvas.height = winH
        this.ctx.save()

        // Draw semi-transparent background
        this.ctx.fillStyle = "rgba(0, 0, 0, 0.8)"
        this.ctx.fillRect(0, 0, winW, winH)

        this.ctx.scale(ratio, ratio)

        // Draw modal background with gradient
        var modalX = 200
        var modalY = 40
        var modalW = 880
        var modalH = 640

        // Gradient background
        var bgGradient = this.ctx.createLinearGradient(modalX, modalY, modalX, modalY + modalH)
        bgGradient.addColorStop(0, "#ffffff")
        bgGradient.addColorStop(1, "#f0f4f8")
        this.ctx.fillStyle = bgGradient
        this.ctx.shadowColor = "rgba(0, 0, 0, 0.3)"
        this.ctx.shadowBlur = 30
        this.ctx.shadowOffsetX = 0
        this.ctx.shadowOffsetY = 10
        this.ctx.fillRect(modalX, modalY, modalW, modalH)
        this.ctx.shadowBlur = 0

        // Modal border with gradient
        var borderGradient = this.ctx.createLinearGradient(modalX, modalY, modalX + modalW, modalY + modalH)
        borderGradient.addColorStop(0, "#4a90e2")
        borderGradient.addColorStop(0.5, "#7b68ee")
        borderGradient.addColorStop(1, "#ff6b9d")
        this.ctx.strokeStyle = borderGradient
        this.ctx.lineWidth = 6
        this.ctx.strokeRect(modalX, modalY, modalW, modalH)

        // Draw title with gradient
        var titleGradient = this.ctx.createLinearGradient(0, 90, 0, 130)
        titleGradient.addColorStop(0, "#4a90e2")
        titleGradient.addColorStop(1, "#7b68ee")
        this.ctx.fillStyle = titleGradient
        this.ctx.font = "bold 48px " + (strings.font || "sans-serif")
        this.ctx.textAlign = "center"
        this.ctx.shadowColor = "rgba(0, 0, 0, 0.2)"
        this.ctx.shadowBlur = 5
        this.ctx.shadowOffsetX = 2
        this.ctx.shadowOffsetY = 2
        this.ctx.fillText("🏆 排行榜 Leaderboard", 640, 100)
        this.ctx.shadowBlur = 0

        // Draw difficulty selector with improved styling
        var diffX = 640
        var diffY = 155
        var difficulties = [
            { id: "easy", name: "簡単", color: "#00a0e9", glow: "#00d4ff" },
            { id: "normal", name: "普通", color: "#00a040", glow: "#00ff66" },
            { id: "hard", name: "難しい", color: "#ff8c00", glow: "#ffb347" },
            { id: "oni", name: "鬼", color: "#dc143c", glow: "#ff6b9d" },
            { id: "ura", name: "裏", color: "#9400d3", glow: "#da70d6" }
        ]

        this.ctx.font = "bold 22px " + (strings.font || "sans-serif")
        for (var i = 0; i < difficulties.length; i++) {
            var diff = difficulties[i]
            var x = diffX - 220 + i * 110

            if (diff.id === this.difficulty) {
                // Selected difficulty with glow effect
                this.ctx.shadowColor = diff.glow
                this.ctx.shadowBlur = 15
                var gradient = this.ctx.createLinearGradient(x - 50, diffY - 30, x + 50, diffY + 20)
                gradient.addColorStop(0, diff.color)
                gradient.addColorStop(1, diff.glow)
                this.ctx.fillStyle = gradient
                this.ctx.fillRect(x - 50, diffY - 30, 100, 50)
                this.ctx.shadowBlur = 0
                this.ctx.fillStyle = "#ffffff"
                this.ctx.shadowColor = "rgba(0, 0, 0, 0.5)"
                this.ctx.shadowBlur = 3
            } else {
                // Unselected difficulty
                this.ctx.strokeStyle = diff.color
                this.ctx.lineWidth = 3
                this.ctx.strokeRect(x - 50, diffY - 30, 100, 50)
                this.ctx.fillStyle = diff.color
            }

            this.ctx.textAlign = "center"
            this.ctx.fillText(diff.name, x, diffY)
            this.ctx.shadowBlur = 0
        }

        // Draw month info with style
        this.ctx.fillStyle = "#666666"
        this.ctx.font = "20px " + (strings.font || "sans-serif")
        this.ctx.textAlign = "center"
        this.ctx.fillText("📅 当月排行 " + this.currentMonth, 640, 215)

        // Header bar
        var headerY = 250
        var headerGradient = this.ctx.createLinearGradient(modalX, headerY, modalX, headerY + 35)
        headerGradient.addColorStop(0, "#e8eef5")
        headerGradient.addColorStop(1, "#d0dae8")
        this.ctx.fillStyle = headerGradient
        this.ctx.fillRect(modalX + 20, headerY, modalW - 40, 35)

        this.ctx.fillStyle = "#333333"
        this.ctx.font = "bold 18px " + (strings.font || "sans-serif")
        this.ctx.textAlign = "center"
        this.ctx.fillText("排名", modalX + 80, headerY + 23)
        this.ctx.textAlign = "left"
        this.ctx.fillText("玩家", modalX + 140, headerY + 23)
        this.ctx.textAlign = "right"
        this.ctx.fillText("分数", modalX + modalW - 60, headerY + 23)

        // Draw leaderboard entries
        var startY = 295
        var rowHeight = 38

        this.ctx.font = "22px " + (strings.font || "sans-serif")
        this.ctx.textAlign = "left"

        if (this.leaderboardData.length === 0) {
            this.ctx.fillStyle = "#999999"
            this.ctx.font = "24px " + (strings.font || "sans-serif")
            this.ctx.textAlign = "center"
            this.ctx.fillText("暂无排行数据", 640, startY + 120)
        } else {
            for (var i = 0; i < Math.min(this.leaderboardData.length, 15); i++) {
                var entry = this.leaderboardData[i]
                var y = startY + i * rowHeight
                var rank = entry.rank

                // Rank background color with gradient
                var gradient
                if (rank === 1) {
                    // Gold gradient for 1st place
                    gradient = this.ctx.createLinearGradient(modalX + 20, y - 25, modalX + 20, y + 10)
                    gradient.addColorStop(0, "#ffd700")
                    gradient.addColorStop(1, "#ffed4e")
                    this.ctx.fillStyle = gradient
                    this.ctx.shadowColor = "#ffd700"
                    this.ctx.shadowBlur = 20
                } else if (rank === 2) {
                    // Silver gradient for 2nd place
                    gradient = this.ctx.createLinearGradient(modalX + 20, y - 25, modalX + 20, y + 10)
                    gradient.addColorStop(0, "#c0c0c0")
                    gradient.addColorStop(1, "#e8e8e8")
                    this.ctx.fillStyle = gradient
                    this.ctx.shadowColor = "#c0c0c0"
                    this.ctx.shadowBlur = 15
                } else if (rank === 3) {
                    // Bronze gradient for 3rd place
                    gradient = this.ctx.createLinearGradient(modalX + 20, y - 25, modalX + 20, y + 10)
                    gradient.addColorStop(0, "#cd7f32")
                    gradient.addColorStop(1, "#e9a86a")
                    this.ctx.fillStyle = gradient
                    this.ctx.shadowColor = "#cd7f32"
                    this.ctx.shadowBlur = 12
                } else {
                    // Regular entries with subtle gradient
                    gradient = this.ctx.createLinearGradient(modalX + 20, y - 25, modalX + 20, y + 10)
                    gradient.addColorStop(0, "#ffffff")
                    gradient.addColorStop(1, "#f8f9fa")
                    this.ctx.fillStyle = gradient
                }

                // Rounded rectangle effect
                this.ctx.fillRect(modalX + 20, y - 25, modalW - 40, 35)
                this.ctx.shadowBlur = 0

                // Border for entries
                if (rank <= 3) {
                    this.ctx.strokeStyle = rank === 1 ? "#ffd700" : rank === 2 ? "#c0c0c0" : "#cd7f32"
                    this.ctx.lineWidth = 2
                    this.ctx.strokeRect(modalX + 20, y - 25, modalW - 40, 35)
                }

                // Rank with medal emoji for top 3
                if (rank === 1) {
                    this.ctx.fillStyle = "#8b6914"
                    this.ctx.font = "bold 24px " + (strings.font || "sans-serif")
                    this.ctx.textAlign = "center"
                    this.ctx.fillText("🥇", modalX + 80, y + 2)
                } else if (rank === 2) {
                    this.ctx.fillStyle = "#5c5c5c"
                    this.ctx.font = "bold 24px " + (strings.font || "sans-serif")
                    this.ctx.textAlign = "center"
                    this.ctx.fillText("🥈", modalX + 80, y + 2)
                } else if (rank === 3) {
                    this.ctx.fillStyle = "#6d4423"
                    this.ctx.font = "bold 24px " + (strings.font || "sans-serif")
                    this.ctx.textAlign = "center"
                    this.ctx.fillText("🥉", modalX + 80, y + 2)
                } else {
                    this.ctx.fillStyle = rank <= 3 ? "#ffffff" : "#555555"
                    this.ctx.font = "bold 22px " + (strings.font || "sans-serif")
                    this.ctx.textAlign = "center"
                    this.ctx.fillText("#" + rank, modalX + 80, y + 2)
                }

                // Display name
                this.ctx.fillStyle = rank <= 3 ? "#1a1a1a" : "#333333"
                this.ctx.font = (rank <= 3 ? "bold " : "") + "20px " + (strings.font || "sans-serif")
                this.ctx.textAlign = "left"
                var displayName = entry.display_name || entry.username
                if (displayName.length > 18) {
                    displayName = displayName.substring(0, 18) + "..."
                }
                this.ctx.fillText(displayName, modalX + 140, y + 2)

                // Score with formatting
                var score = entry.score && entry.score.score ? entry.score.score : 0
                this.ctx.fillStyle = rank <= 3 ? "#1a1a1a" : "#555555"
                this.ctx.font = (rank <= 3 ? "bold " : "") + "20px " + (strings.font || "sans-serif")
                this.ctx.textAlign = "right"
                this.ctx.fillText(score.toLocaleString(), modalX + modalW - 60, y + 2)
            }
        }

        // Draw close hint with icon
        this.ctx.fillStyle = "#888888"
        this.ctx.font = "18px " + (strings.font || "sans-serif")
        this.ctx.textAlign = "center"
        this.ctx.fillText("⌨️ 按ESC或点击外部关闭 Press ESC or click outside to close", 640, 665)

        this.ctx.restore()
    }

    clean() {
        if (this.keyboard) {
            this.keyboard.clean()
        }
        if (this.redrawRunning) {
            this.redrawRunning = false
        }
        pageEvents.remove(this.canvas, ["mousedown", "touchstart"])
    }
}
