package main

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

// GET /api/assets/dashboard?customer_id=X&location_id=Y
// Returns asset categories, asset groups, and GIS-ready assets for the selected scope.
func assetDashboardHandler(db *DB) http.HandlerFunc {
	type AssetCategory struct {
		AssetCategoryID   int    `json:"asset_category_id"`
		AssetCategoryName string `json:"asset_category_name"`
		Count             int    `json:"count"`
	}
	type AssetGroup struct {
		AssetGroupID    int    `json:"asset_group_id"`
		AssetGroupName  string `json:"asset_group_name"`
		AssetGroupImage string `json:"asset_group_image"`
		Count           int    `json:"count"`
	}
	type GISAsset struct {
		AssetID           int     `json:"asset_id"`
		AssetName         string  `json:"asset_name"`
		Latitude          float64 `json:"latitude"`
		Longitude         float64 `json:"longitude"`
		AssetGroupID      int     `json:"asset_group_id"`
		AssetGroupName    string  `json:"asset_group_name"`
		AssetGroupImage   string  `json:"asset_group_image"`
		AssetCategoryName string  `json:"asset_category_name"`
		LocationID        int     `json:"location_id"`
	}

	return func(w http.ResponseWriter, r *http.Request) {
		ctx, cancel := context.WithTimeout(r.Context(), 10*time.Second)
		defer cancel()

		// Parse optional scope filters
		var customerID, locationID int
		var hasCustomer, hasLocation bool
		if v := r.URL.Query().Get("customer_id"); v != "" {
			id, err := strconv.Atoi(v)
			if err != nil {
				w.WriteHeader(http.StatusBadRequest)
				json.NewEncoder(w).Encode(map[string]string{"error": "invalid customer_id"})
				return
			}
			customerID = id
			hasCustomer = true
		}
		if v := r.URL.Query().Get("location_id"); v != "" {
			id, err := strconv.Atoi(v)
			if err != nil {
				w.WriteHeader(http.StatusBadRequest)
				json.NewEncoder(w).Encode(map[string]string{"error": "invalid location_id"})
				return
			}
			locationID = id
			hasLocation = true
		}

		// Require at least customer_id to avoid full-table scans
		if !hasCustomer {
			w.Header().Set("Content-Type", "application/json")
			json.NewEncoder(w).Encode(map[string]any{
				"assetCategories": []AssetCategory{},
				"assetGroups":     []AssetGroup{},
				"gisAssets":       []GISAsset{},
			})
			return
		}

		// Build WHERE clause
		where := "am.customer_id = $1"
		args := []any{customerID}
		if hasLocation {
			args = append(args, locationID)
			where += " AND am.location_id = $2"
		}

		// ── 1. Asset Categories ──────────────────────────────────────────────
		catSQL := `
SELECT ac.cat_id, ac.category_name, COUNT(am.asset_id)
FROM ic3_asset_category ac
INNER JOIN ic3_asset_group ag ON ag.cat_id = ac.cat_id
INNER JOIN ic3_asset_master am ON am.asset_group_id = ag.subcategory_id
WHERE ` + where + `
GROUP BY ac.cat_id, ac.category_name
ORDER BY COUNT(am.asset_id) DESC`

		catRows, err := db.pool.Query(ctx, catSQL, args...)
		if err != nil {
			w.WriteHeader(500)
			json.NewEncoder(w).Encode(map[string]string{"error": err.Error()})
			return
		}
		defer catRows.Close()
		cats := []AssetCategory{}
		for catRows.Next() {
			var c AssetCategory
			if catRows.Scan(&c.AssetCategoryID, &c.AssetCategoryName, &c.Count) == nil {
				cats = append(cats, c)
			}
		}

		// ── 2. Asset Groups ──────────────────────────────────────────────────
		grpSQL := `
SELECT ag.subcategory_id, ag.asset_group_name, COALESCE(ag.icon,''), COUNT(am.asset_id)
FROM ic3_asset_group ag
INNER JOIN ic3_asset_master am ON am.asset_group_id = ag.subcategory_id
WHERE ` + where + `
GROUP BY ag.subcategory_id, ag.asset_group_name, ag.icon
ORDER BY COUNT(am.asset_id) DESC
LIMIT 50`

		grpRows, err := db.pool.Query(ctx, grpSQL, args...)
		if err != nil {
			w.WriteHeader(500)
			json.NewEncoder(w).Encode(map[string]string{"error": err.Error()})
			return
		}
		defer grpRows.Close()
		groups := []AssetGroup{}
		for grpRows.Next() {
			var g AssetGroup
			if grpRows.Scan(&g.AssetGroupID, &g.AssetGroupName, &g.AssetGroupImage, &g.Count) == nil {
				groups = append(groups, g)
			}
		}

		// ── 3. GIS Assets (with GPS) ─────────────────────────────────────────
		gisSQL := `
SELECT
  am.asset_id,
  COALESCE(am.serialnumber, ''),
  am.asset_current_lattitude,
  am.asset_current_longitude,
  COALESCE(am.asset_group_id, 0),
  COALESCE(ag.asset_group_name, ''),
  COALESCE(ag.icon, ''),
  COALESCE(ac.category_name, ''),
  COALESCE(am.location_id, 0)
FROM ic3_asset_master am
LEFT JOIN ic3_asset_group ag ON ag.subcategory_id = am.asset_group_id
LEFT JOIN ic3_asset_category ac ON ac.cat_id = ag.cat_id
WHERE ` + where + `
  AND am.asset_current_lattitude IS NOT NULL
  AND am.asset_current_longitude IS NOT NULL
LIMIT 10000`

		gisRows, err := db.pool.Query(ctx, gisSQL, args...)
		if err != nil {
			w.WriteHeader(500)
			json.NewEncoder(w).Encode(map[string]string{"error": err.Error()})
			return
		}
		defer gisRows.Close()
		gisAssets := []GISAsset{}
		for gisRows.Next() {
			var g GISAsset
			if gisRows.Scan(&g.AssetID, &g.AssetName, &g.Latitude, &g.Longitude,
				&g.AssetGroupID, &g.AssetGroupName, &g.AssetGroupImage, &g.AssetCategoryName, &g.LocationID) == nil {
				gisAssets = append(gisAssets, g)
			}
		}

		w.Header().Set("Content-Type", "application/json")
		json.NewEncoder(w).Encode(map[string]any{
			"assetCategories": cats,
			"assetGroups":     groups,
			"gisAssets":       gisAssets,
		})
	}
}
