package main

import (
	"context"
	"encoding/json"
	"log"
	"net/http"
	"strconv"
	"time"
)

// MenuItem represents a system menu item
type MenuItem struct {
	ID          int    `json:"id"`
	Label       string `json:"label"`
	Domain      string `json:"domain"`
	Role        string `json:"role"`
	Visible     bool   `json:"visible"`
	Description string `json:"description"`
	Order       int    `json:"order"`
	CreatedAt   string `json:"created_at"`
	UpdatedAt   string `json:"updated_at"`
}

// GET /api/admin/menu
// List all system menu items
func listMenuHandler(db *DB) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		ctx, cancel := context.WithTimeout(r.Context(), 10*time.Second)
		defer cancel()

		items, err := db.ListMenuItems(ctx)
		if err != nil {
			w.WriteHeader(500)
			json.NewEncoder(w).Encode(map[string]string{"error": err.Error()})
			return
		}
		if items == nil {
			items = []MenuItem{}
		}
		json.NewEncoder(w).Encode(map[string]any{
			"data":  items,
			"count": len(items),
		})
	}
}

// GET /api/admin/menu/{id}
// Get a single menu item
func getMenuHandler(db *DB) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		id := r.PathValue("id")
		if id == "" {
			w.WriteHeader(400)
			json.NewEncoder(w).Encode(map[string]string{"error": "id required"})
			return
		}
		menuID, _ := strconv.Atoi(id)
		ctx, cancel := context.WithTimeout(r.Context(), 5*time.Second)
		defer cancel()

		item, err := db.GetMenuItem(ctx, menuID)
		if err != nil {
			w.WriteHeader(404)
			json.NewEncoder(w).Encode(map[string]string{"error": "menu item not found"})
			return
		}
		json.NewEncoder(w).Encode(item)
	}
}

// POST /api/admin/menu
// Create a new menu item
func createMenuHandler(db *DB) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		var req MenuItem
		if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
			w.WriteHeader(400)
			json.NewEncoder(w).Encode(map[string]string{"error": "invalid request body"})
			return
		}

		if req.Label == "" {
			w.WriteHeader(400)
			json.NewEncoder(w).Encode(map[string]string{"error": "label is required"})
			return
		}

		ctx, cancel := context.WithTimeout(r.Context(), 10*time.Second)
		defer cancel()

		item, err := db.CreateMenuItem(ctx, &req)
		if err != nil {
			log.Printf("create menu error: %v", err)
			w.WriteHeader(500)
			json.NewEncoder(w).Encode(map[string]string{"error": err.Error()})
			return
		}

		w.WriteHeader(201)
		json.NewEncoder(w).Encode(item)
	}
}

// PUT /api/admin/menu/{id}
// Update a menu item
func updateMenuHandler(db *DB) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		id := r.PathValue("id")
		if id == "" {
			w.WriteHeader(400)
			json.NewEncoder(w).Encode(map[string]string{"error": "id required"})
			return
		}
		menuID, _ := strconv.Atoi(id)

		var req MenuItem
		if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
			w.WriteHeader(400)
			json.NewEncoder(w).Encode(map[string]string{"error": "invalid request body"})
			return
		}

		if req.Label == "" {
			w.WriteHeader(400)
			json.NewEncoder(w).Encode(map[string]string{"error": "label is required"})
			return
		}

		ctx, cancel := context.WithTimeout(r.Context(), 10*time.Second)
		defer cancel()

		req.ID = menuID
		item, err := db.UpdateMenuItem(ctx, &req)
		if err != nil {
			w.WriteHeader(500)
			json.NewEncoder(w).Encode(map[string]string{"error": err.Error()})
			return
		}

		json.NewEncoder(w).Encode(item)
	}
}

// DELETE /api/admin/menu/{id}
// Delete a menu item
func deleteMenuHandler(db *DB) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		id := r.PathValue("id")
		if id == "" {
			w.WriteHeader(400)
			json.NewEncoder(w).Encode(map[string]string{"error": "id required"})
			return
		}
		menuID, _ := strconv.Atoi(id)

		ctx, cancel := context.WithTimeout(r.Context(), 10*time.Second)
		defer cancel()

		if err := db.DeleteMenuItem(ctx, menuID); err != nil {
			w.WriteHeader(500)
			json.NewEncoder(w).Encode(map[string]string{"error": err.Error()})
			return
		}

		w.WriteHeader(204)
	}
}
