package handlers

import (
	"Portifolio/internal/model"
	"Portifolio/internal/service"
	"database/sql"
	"encoding/json"
	"net/http"
	"runtime"
	"time"

	_ "github.com/mattn/go-sqlite3"
)

var startTime = time.Now()

func HealthHandler(db *sql.DB) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "application/json")

		health := checkHealth(db)

		if health["status"] != "ok" {
			w.WriteHeader(http.StatusServiceUnavailable)
		}

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

func checkHealth(db *sql.DB) map[string]any {
	// database
	dbStatus := "ok"
	dbLatency := ""
	t := time.Now()
	if err := db.Ping(); err != nil {
		dbStatus = "error: " + err.Error()
	} else {
		dbLatency = time.Since(t).String()
	}

	// db pool stats
	stats := db.Stats()

	// overall status
	status := "ok"
	if dbStatus != "ok" {
		status = "degraded"
	}

	var mem runtime.MemStats
	runtime.ReadMemStats(&mem)

	return map[string]any{
		"status": status,
		"uptime": time.Since(startTime).String(),
		"database": map[string]any{
			"status":           dbStatus,
			"latency":          dbLatency,
			"open_connections": stats.OpenConnections,
			"in_use":           stats.InUse,
			"idle":             stats.Idle,
		},
		"memory": map[string]any{
			"alloc_mb": bToMb(mem.Alloc),
			"sys_mb":   bToMb(mem.Sys),
			"num_gc":   mem.NumGC,
		},
		"go_version": runtime.Version(),
		"goroutines": runtime.NumGoroutine(),
	}
}

func bToMb(b uint64) float64 {
	return float64(b) / 1024 / 1024
}

func AddCompanyHandler(db *sql.DB) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		var input model.CompanyInput
		if err := json.NewDecoder(r.Body).Decode(&input); err != nil {
			http.Error(w, "invalid json", http.StatusBadRequest)
			return
		}

		id, err := service.InsertCompany(db, input)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		w.Header().Set("Content-Type", "application/json")
		w.WriteHeader(http.StatusCreated)
		json.NewEncoder(w).Encode(map[string]any{"status": "created", "id": id})
	}
}

func GetCompaniesHandler(db *sql.DB) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		companies, err := service.GetAllCompanies(db)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		w.Header().Set("Content-Type", "application/json")
		json.NewEncoder(w).Encode(companies)
	}
}
