// Package api provides HTTP handlers for camera operations.
package api

import (
	"database/sql"
	"encoding/json"
	"log"
	"net/http"

	"github.com/cubecraft/remoterig/internal/db"
	"github.com/cubecraft/remoterig/pkg/models"
	"github.com/go-chi/chi/v5"
)

// ListCameras returns a handler for GET /cameras.
// Returns all cameras with their latest status from status_logs.
func ListCameras(database *db.DB) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		ctx := r.Context()

		// Query: join cameras with their most recent status_logs row
		rows, err := database.QueryContext(ctx, `
			SELECT
				c.camera_id,
				c.friendly_name,
				s.battery_pct,
				s.video_remaining_sec,
				s.recording_state,
				s.mode,
				s.resolution,
				s.fps,
				s.online,
				s.recorded_at
			FROM cameras c
			LEFT JOIN (
				SELECT camera_id, battery_pct, video_remaining_sec, recording_state,
				       mode, resolution, fps, online, recorded_at,
				       ROW_NUMBER() OVER (PARTITION BY camera_id ORDER BY recorded_at DESC) as rn
				FROM status_logs
			) s ON c.camera_id = s.camera_id AND s.rn = 1
			ORDER BY c.camera_id
		`)
		if err != nil {
			log.Printf("Error querying cameras: %v", err)
			respondJSON(w, http.StatusInternalServerError, map[string]string{"error": "database error"})
			return
		}
		defer rows.Close()

		var statuses []models.CameraStatus
		for rows.Next() {
			var sl models.StatusLog
			var c models.Camera
			if err := rows.Scan(
				&c.CameraID, &c.FriendlyName,
				&sl.BatteryPct, &sl.VideoRemainingSec,
				&sl.RecordingState, &sl.Mode, &sl.Resolution, &sl.FPS,
				&sl.Online, &sl.RecordedAt,
			); err != nil {
				log.Printf("Error scanning camera row: %v", err)
				continue
			}
			statuses = append(statuses, models.NewCameraStatus(c, sl))
		}
		if err := rows.Err(); err != nil {
			log.Printf("Error iterating camera rows: %v", err)
			respondJSON(w, http.StatusInternalServerError, map[string]string{"error": "database error"})
			return
		}

		if statuses == nil {
			statuses = []models.CameraStatus{}
		}

		respondJSON(w, http.StatusOK, statuses)
	}
}

// RegisterCamera returns a handler for POST /cameras.
func RegisterCamera(database *db.DB) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		var req struct {
			CameraID     string  `json:"camera_id"`
			FriendlyName string  `json:"friendly_name"`
			MacAddress   *string `json:"mac_address,omitempty"`
		}
		if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
			respondJSON(w, http.StatusBadRequest, map[string]string{"error": "invalid request body"})
			return
		}

		if req.CameraID == "" || req.FriendlyName == "" {
			respondJSON(w, http.StatusBadRequest, map[string]string{"error": "camera_id and friendly_name are required"})
			return
		}

		_, err := database.ExecContext(r.Context(), `
			INSERT INTO cameras (camera_id, friendly_name, mac_address)
			VALUES (?, ?, ?)
		`, req.CameraID, req.FriendlyName, req.MacAddress)
		if err != nil {
			if err.Error() == "UNIQUE constraint failed: cameras.mac_address" {
				respondJSON(w, http.StatusConflict, map[string]string{"error": "camera with this mac_address already registered"})
				return
			}
			log.Printf("Error registering camera: %v", err)
			respondJSON(w, http.StatusInternalServerError, map[string]string{"error": "database error"})
			return
		}

		log.Printf("Registered camera %s (%s)", req.CameraID, req.FriendlyName)
		resp := map[string]interface{}{
			"camera_id":     req.CameraID,
			"friendly_name": req.FriendlyName,
		}
		if req.MacAddress != nil {
			resp["mac_address"] = *req.MacAddress
		}
		respondJSON(w, http.StatusCreated, resp)
	}
}

// GetCameraDetail returns a handler for GET /cameras/{id}.
func GetCameraDetail(database *db.DB) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		cameraID := chi.URLParam(r, "id")
		if cameraID == "" {
			respondJSON(w, http.StatusBadRequest, map[string]string{"error": "camera_id required"})
			return
		}

		// Get camera info
		var c models.Camera
		err := database.QueryRowContext(r.Context(), `
			SELECT camera_id, friendly_name, mac_address, created_at, updated_at
			FROM cameras WHERE camera_id = ?
		`, cameraID).Scan(
			&c.CameraID, &c.FriendlyName, &c.MacAddress,
			&c.CreatedAt, &c.UpdatedAt,
		)
		if err == sql.ErrNoRows {
			respondJSON(w, http.StatusNotFound, map[string]string{"error": "camera not found"})
			return
		}
		if err != nil {
			log.Printf("Error querying camera: %v", err)
			respondJSON(w, http.StatusInternalServerError, map[string]string{"error": "database error"})
			return
		}

		// Get latest status
		var sl models.StatusLog
		err = database.QueryRowContext(r.Context(), `
			SELECT id, camera_id, recorded_at, battery_pct, video_remaining_sec,
			       recording_state, mode, resolution, fps, online, raw_battery_pct
			FROM status_logs
			WHERE camera_id = ?
			ORDER BY recorded_at DESC
			LIMIT 1
		`, cameraID).Scan(
			&sl.ID, &sl.CameraID, &sl.RecordedAt,
			&sl.BatteryPct, &sl.VideoRemainingSec,
			&sl.RecordingState, &sl.Mode, &sl.Resolution, &sl.FPS,
			&sl.Online, &sl.RawBatteryPct,
		)
		if err != nil && err != sql.ErrNoRows {
			log.Printf("Error querying latest status: %v", err)
			respondJSON(w, http.StatusInternalServerError, map[string]string{"error": "database error"})
			return
		}

		// Get 24h history
		historyRows, err := database.QueryContext(r.Context(), `
			SELECT id, camera_id, recorded_at, battery_pct, video_remaining_sec,
			       recording_state, mode, resolution, fps, online, raw_battery_pct
			FROM status_logs
			WHERE camera_id = ? AND recorded_at >= datetime('now', '-24 hours')
			ORDER BY recorded_at DESC
			LIMIT 100
		`, cameraID)
		if err != nil {
			log.Printf("Error querying history: %v", err)
			respondJSON(w, http.StatusInternalServerError, map[string]string{"error": "database error"})
			return
		}
		defer historyRows.Close()

		var history []models.StatusLog
		for historyRows.Next() {
			var h models.StatusLog
			if err := historyRows.Scan(
				&h.ID, &h.CameraID, &h.RecordedAt,
				&h.BatteryPct, &h.VideoRemainingSec,
				&h.RecordingState, &h.Mode, &h.Resolution, &h.FPS,
				&h.Online, &h.RawBatteryPct,
			); err != nil {
				continue
			}
			history = append(history, h)
		}
		if history == nil {
			history = []models.StatusLog{}
		}

		respondJSON(w, http.StatusOK, map[string]interface{}{
			"camera":    c,
			"last_status": sl,
			"history":     history,
		})
	}
}

// respondJSON writes a JSON response with the given status code.
func respondJSON(w http.ResponseWriter, status int, data interface{}) {
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(status)
	json.NewEncoder(w).Encode(data)
}
