package app

import (
	"context"
	"encoding/json"
	"errors"
	"net"
	"net/http"
	"strconv"
	"strings"
	"time"

	mysqlstorage "hyapp/services/statistics-service/internal/storage/mysql"
)

type queryHTTPServer struct {
	repo     *mysqlstorage.Repository
	server   *http.Server
	listener net.Listener
}

func newQueryHTTPServer(addr string, repo *mysqlstorage.Repository) (*queryHTTPServer, error) {
	addr = strings.TrimSpace(addr)
	if addr == "" {
		return nil, nil
	}
	listener, err := net.Listen("tcp", addr)
	if err != nil {
		return nil, err
	}
	s := &queryHTTPServer{repo: repo, listener: listener}
	mux := http.NewServeMux()
	mux.HandleFunc("/internal/v1/statistics/overview", s.overview)
	s.server = &http.Server{Handler: mux, ReadHeaderTimeout: 2 * time.Second}
	return s, nil
}

func (s *queryHTTPServer) Run() error {
	if s == nil {
		return nil
	}
	err := s.server.Serve(s.listener)
	if errors.Is(err, http.ErrServerClosed) {
		return nil
	}
	return err
}

func (s *queryHTTPServer) Close(ctx context.Context) error {
	if s == nil {
		return nil
	}
	return s.server.Shutdown(ctx)
}

func (s *queryHTTPServer) overview(w http.ResponseWriter, r *http.Request) {
	query := r.URL.Query()
	startMS := parseInt64(query.Get("start_ms"))
	endMS := parseInt64(query.Get("end_ms"))
	if startMS <= 0 {
		now := time.Now().UTC()
		startMS = time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, time.UTC).UnixMilli()
	}
	if endMS <= startMS {
		endMS = startMS + 24*time.Hour.Milliseconds()
	}
	overview, err := s.repo.QueryOverview(r.Context(), mysqlstorage.OverviewQuery{
		AppCode:       query.Get("app_code"),
		StartMS:       startMS,
		EndMS:         endMS,
		SeriesStartMS: parseInt64(query.Get("series_start_ms")),
		SeriesEndMS:   parseInt64(query.Get("series_end_ms")),
		CountryID:     parseInt64(query.Get("country_id")),
		RegionID:      parseInt64(query.Get("region_id")),
	})
	if err != nil {
		writeJSON(w, http.StatusInternalServerError, map[string]any{"error": err.Error()})
		return
	}
	writeJSON(w, http.StatusOK, overview)
}

func parseInt64(value string) int64 {
	parsed, _ := strconv.ParseInt(strings.TrimSpace(value), 10, 64)
	return parsed
}

func writeJSON(w http.ResponseWriter, status int, payload any) {
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(status)
	_ = json.NewEncoder(w).Encode(payload)
}
