// CctvPlugin.kt
package com.example.cctv

import org.bukkit.Bukkit
import org.bukkit.Location
import org.bukkit.Material
import org.bukkit.configuration.file.YamlConfiguration
import org.bukkit.entity.Player
import org.bukkit.event.EventHandler
import org.bukkit.event.Listener
import org.bukkit.event.inventory.InventoryClickEvent
import org.bukkit.event.player.PlayerJoinEvent
import org.bukkit.event.player.PlayerQuitEvent
import org.bukkit.inventory.ItemStack
import org.bukkit.plugin.java.JavaPlugin
import org.bukkit.scheduler.BukkitTask
import java.io.File
import java.util.*
import com.example.cctv.menus.CctvMenu
import com.example.cctv.menus.MainMenu
import com.example.cctv.menus.ViewCamerasMenu
import com.example.cctv.menus.ManageCamerasMenu
import com.example.cctv.menus.PlaceCameraMenu

class CctvPlugin : JavaPlugin(), Listener {
    private val cameras = mutableMapOf<String, Camera>()
    private val playerViewing = mutableMapOf<UUID, Camera>()
    private val viewingTasks = mutableMapOf<UUID, BukkitTask>()
    private lateinit var cameraFile: File
    private lateinit var cameraConfig: YamlConfiguration

    override fun onEnable() {
        // Create config if it doesn't exist
        saveDefaultConfig()

        // Register command
        getCommand("cctv")?.setExecutor(CctvCommand(this))

        // Register events
        server.pluginManager.registerEvents(this, this)

        // Initialize camera data
        cameraFile = File(dataFolder, "cameras.yml")
        if (!cameraFile.exists()) {
            saveResource("cameras.yml", false)
        }
        cameraConfig = YamlConfiguration.loadConfiguration(cameraFile)

        // Load cameras from configuration
        loadCameras()

        logger.info("CCTV Plugin enabled!")
    }

    override fun onDisable() {
        // Stop all viewing sessions
        playerViewing.keys.forEach { stopViewing(it) }

        // Save cameras to configuration
        saveCameras()

        logger.info("CCTV Plugin disabled!")
    }

    @EventHandler
    fun onPlayerQuit(event: PlayerQuitEvent) {
        // Stop viewing when player leaves
        stopViewing(event.player.uniqueId)
    }

    private fun loadCameras() {
        if (cameraConfig.contains("cameras")) {
            val camerasSection = cameraConfig.getConfigurationSection("cameras")
            camerasSection?.getKeys(false)?.forEach { id ->
                val section = camerasSection.getConfigurationSection(id)
                if (section != null) {
                    val world = Bukkit.getWorld(section.getString("world") ?: "world")
                    if (world != null) {
                        val x = section.getDouble("x")
                        val y = section.getDouble("y")
                        val z = section.getDouble("z")
                        val yaw = section.getDouble("yaw").toFloat()
                        val pitch = section.getDouble("pitch").toFloat()
                        val name = section.getString("name") ?: "Camera $id"
                        val owner = UUID.fromString(section.getString("owner") ?: "00000000-0000-0000-0000-000000000000")

                        val location = Location(world, x, y, z, yaw, pitch)
                        cameras[id] = Camera(id, name, location, owner)
                    }
                }
            }
        }
    }

    private fun saveCameras() {
        // Clear existing cameras
        cameraConfig.set("cameras", null)

        // Save each camera
        cameras.forEach { (id, camera) ->
            val path = "cameras.$id"
            cameraConfig.set("$path.name", camera.name)
            cameraConfig.set("$path.world", camera.location.world?.name)
            cameraConfig.set("$path.x", camera.location.x)
            cameraConfig.set("$path.y", camera.location.y)
            cameraConfig.set("$path.z", camera.location.z)
            cameraConfig.set("$path.yaw", camera.location.yaw)
            cameraConfig.set("$path.pitch", camera.location.pitch)
            cameraConfig.set("$path.owner", camera.owner.toString())
        }

        // Save to file
        cameraConfig.save(cameraFile)
    }

    fun getCameras(): Map<String, Camera> {
        return cameras.toMap()
    }

    fun createCamera(player: Player, name: String): Boolean {
        val id = UUID.randomUUID().toString().substring(0, 8)
        val camera = Camera(id, name, player.location.clone(), player.uniqueId)
        cameras[id] = camera
        saveCameras()
        return true
    }

    fun removeCamera(id: String, player: Player): Boolean {
        val camera = cameras[id] ?: return false

        // Check if the player is the owner or has permission
        if (camera.owner != player.uniqueId && !player.hasPermission("cctv.admin")) {
            return false
        }

        // Stop anyone viewing this camera
        playerViewing.forEach { (uuid, cam) ->
            if (cam.id == id) {
                stopViewing(uuid)
            }
        }

        cameras.remove(id)
        saveCameras()
        return true
    }

    fun startViewing(player: Player, cameraId: String): Boolean {
        // Stop current viewing if any
        stopViewing(player.uniqueId)

        val camera = cameras[cameraId] ?: return false

        // Store original location
        val originalLocation = player.location.clone()
        camera.viewerLocations[player.uniqueId] = originalLocation

        // Teleport to camera view (spectator mode)
        val gameMode = player.gameMode
        camera.viewerGameModes[player.uniqueId] = gameMode

        player.gameMode = org.bukkit.GameMode.SPECTATOR
        player.teleport(camera.location)

        // Set up viewing task
        playerViewing[player.uniqueId] = camera

        // Create a task to check if player tries to exit spectator
        val task = Bukkit.getScheduler().runTaskTimer(this, Runnable {
            val currentPlayer = Bukkit.getPlayer(player.uniqueId)
            if (currentPlayer == null || !currentPlayer.isOnline) {
                stopViewing(player.uniqueId)
                return@Runnable
            }

            // Keep the player at the camera location
            if (currentPlayer.location.distance(camera.location) > 0.5) {
                currentPlayer.teleport(camera.location)
            }
        }, 5L, 5L)

        viewingTasks[player.uniqueId] = task

        return true
    }

    fun stopViewing(uuid: UUID) {
        val camera = playerViewing[uuid] ?: return
        val player = Bukkit.getPlayer(uuid) ?: return

        // Restore original location
        val originalLocation = camera.viewerLocations[uuid]
        if (originalLocation != null) {
            player.teleport(originalLocation)
            camera.viewerLocations.remove(uuid)
        }

        // Restore game mode
        val originalGameMode = camera.viewerGameModes[uuid]
        if (originalGameMode != null) {
            player.gameMode = originalGameMode
            camera.viewerGameModes.remove(uuid)
        }

        // Cancel task
        viewingTasks[uuid]?.cancel()
        viewingTasks.remove(uuid)

        // Remove from viewing map
        playerViewing.remove(uuid)
    }

    @EventHandler
    fun onInventoryClick(event: InventoryClickEvent) {
        val player = event.whoClicked as? Player ?: return
        val inventory = event.inventory

        if (inventory.holder is CctvMenu) {
            event.isCancelled = true
            val item = event.currentItem ?: return

            val menu = inventory.holder as CctvMenu
            menu.handleClick(player, item, event.slot)
        }
    }

    data class Camera(
        val id: String,
        val name: String,
        val location: Location,
        val owner: UUID,
        val viewerLocations: MutableMap<UUID, Location> = mutableMapOf(),
        val viewerGameModes: MutableMap<UUID, org.bukkit.GameMode> = mutableMapOf()
    )
}