package qc

import (
	"fmt"
	"net/http"
	"strconv"
	"verofy-backend/models"

	"github.com/gin-gonic/gin"
	"gorm.io/gorm"
)

func SiteConnectivityRoute(router *gin.Engine, db *gorm.DB, schema string) {
	router.GET("/api/qc/site-connectivity", func(c *gin.Context) {
		mapID := c.Query("map_id")
		zone := c.Query("zone")
		maxDistanceStr := c.Query("max_distance")

		if mapID == "" {
			c.JSON(http.StatusBadRequest, gin.H{"error": "map_id is required"})
			return
		}

		// Default max distance is 50 meters
		maxDistance := 50.0
		if maxDistanceStr != "" {
			if dist, err := strconv.ParseFloat(maxDistanceStr, 64); err == nil {
				maxDistance = dist
			}
		}

		// Get all sites for the market (and zone if specified)
		var sites []models.SitesGeoJSON
		siteQuery := db.Table(fmt.Sprintf("%s.sites", schema)).
			Select("gid, id, mapprojectid, name, address1, city, state, zip, ST_AsGeoJSON(geom)::json AS geometry")

		if mapID != "" {
			siteQuery = siteQuery.Where("mapprojectid = ?", mapID)
		}

		siteQuery.Find(&sites)

		// Get all segments for connectivity analysis
		var segments []models.SegmentGeoJSON
		segmentQuery := db.Table(fmt.Sprintf("%s.segment2", schema)).
			Select("id_0, mapid, segment_type, segment_status, id, protection_status, qc_flag, ST_AsGeoJSON(geom)::json AS geometry")

		if mapID != "" {
			segmentQuery = segmentQuery.Where("mapid = ?", mapID)
		}
		if zone != "" {
			segmentQuery = segmentQuery.Where("group_1 = ?", zone)
		}

		segmentQuery.Find(&segments)

		// Analyze connectivity for each site
		results := []map[string]interface{}{}
		connectedCount := 0
		disconnectedCount := 0

		for _, site := range sites {
			if len(site.Geometry) == 0 {
				continue
			}

			// Use PostGIS to find the nearest segment within max distance
			var nearestDistance float64
			nearestQuery := fmt.Sprintf(`
				SELECT ST_Distance(
					ST_Transform(sites.geom, 3857),
					ST_Transform(segments.geom, 3857)
				) as distance
				FROM %s.sites sites, %s.segment2 segments
				WHERE sites.gid = ? AND segments.mapid = ?
				ORDER BY ST_Distance(
					ST_Transform(sites.geom, 3857), 
					ST_Transform(segments.geom, 3857)
				)
				LIMIT 1
			`, schema, schema)

			db.Raw(nearestQuery, site.GID, mapID).Scan(&nearestDistance)

			isConnected := nearestDistance <= maxDistance
			status := "connected"
			if !isConnected {
				status = "disconnected"
				disconnectedCount++
			} else {
				connectedCount++
			}

			// Update the site's connectivity status in the database
			updateQuery := fmt.Sprintf("UPDATE %s.sites SET connectivity_status = ?, connectivity_distance = ? WHERE gid = ?", schema)
			db.Exec(updateQuery, status, nearestDistance, site.GID)

			siteResult := map[string]interface{}{
				"site_id":             site.GID,
				"site_name":           site.Name,
				"mapprojectid":        site.MapProjectID,
				"is_connected":        isConnected,
				"nearest_distance":    nearestDistance,
				"connectivity_status": status,
				"geometry":            site.Geometry,
				"address":             site.Address1,
				"city":                site.City,
				"state":               site.State,
			}

			results = append(results, siteResult)
		}

		response := map[string]interface{}{
			"total_sites":         len(sites),
			"connected_sites":     connectedCount,
			"disconnected_sites":  disconnectedCount,
			"connectivity_rate":   float64(connectedCount) / float64(len(sites)) * 100,
			"max_distance_meters": maxDistance,
			"results":             results,
		}

		c.JSON(http.StatusOK, response)
	})
}
