package web

import (
	"log/slog"
	"net/http"
	"strings"
	"time"

	"backend/internal/auth"
	"backend/internal/db/sqlc"
	"backend/templates"

	"github.com/gorilla/csrf"
)

type PlanningDeps struct {
	Queries *sqlc.Queries
	Now     func() time.Time
}

func parsePlanningStart(raw string, now time.Time) time.Time {
	today := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, time.Local)
	raw = strings.TrimSpace(raw)
	if raw == "" {
		return today
	}
	parsed, err := time.Parse("2006-01-02", raw)
	if err != nil {
		return today
	}
	return time.Date(parsed.Year(), parsed.Month(), parsed.Day(), 0, 0, 0, 0, time.Local)
}

func parsePlanningMonth(raw string, now time.Time) time.Time {
	raw = strings.TrimSpace(raw)
	if raw == "" {
		return time.Date(now.Year(), now.Month(), 1, 0, 0, 0, 0, time.Local)
	}
	parsed, err := time.Parse("2006-01", raw)
	if err != nil {
		return time.Date(now.Year(), now.Month(), 1, 0, 0, 0, 0, time.Local)
	}
	return time.Date(parsed.Year(), parsed.Month(), 1, 0, 0, 0, 0, time.Local)
}

func PlanningPageHandler(deps PlanningDeps) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		_, user, _ := auth.Authed(r.Context())
		now := time.Now
		if deps.Now != nil {
			now = deps.Now
		}
		today := parsePlanningStart("", now())

		view := strings.TrimSpace(r.URL.Query().Get("view"))
		if view == "" {
			view = "month"
		}

		sidebarTablos, err := deps.Queries.ListTablosByUser(r.Context(), user.ID)
		if err != nil {
			slog.Default().Error("planning: ListTablosByUser failed", "user_id", user.ID, "err", err)
			http.Error(w, "internal server error", http.StatusInternalServerError)
			return
		}
		if sidebarTablos == nil {
			sidebarTablos = []sqlc.Tablo{}
		}

		var cal templates.PlanningCalendar

		switch view {
		case "week":
			weekStart := templates.MondayOf(parsePlanningStart(r.URL.Query().Get("start"), now()))
			weekEnd := weekStart.AddDate(0, 0, 6)
			rows, err := deps.Queries.ListUserEventsRange(r.Context(), sqlc.ListUserEventsRangeParams{
				UserID:    user.ID,
				StartDate: pgDateFromTime(weekStart),
				EndDate:   pgDateFromTime(weekEnd),
			})
			if err != nil {
				slog.Default().Error("planning: ListUserEventsRange (week) failed", "user_id", user.ID, "err", err)
				http.Error(w, "internal server error", http.StatusInternalServerError)
				return
			}
			cal = templates.BuildWeekCalendar(weekStart, today, rows)

		case "day":
			date := parsePlanningStart(r.URL.Query().Get("date"), now())
			rows, err := deps.Queries.ListUserEventsRange(r.Context(), sqlc.ListUserEventsRangeParams{
				UserID:    user.ID,
				StartDate: pgDateFromTime(date),
				EndDate:   pgDateFromTime(date),
			})
			if err != nil {
				slog.Default().Error("planning: ListUserEventsRange (day) failed", "user_id", user.ID, "err", err)
				http.Error(w, "internal server error", http.StatusInternalServerError)
				return
			}
			cal = templates.BuildDayCalendar(date, today, rows)

		default: // "month"
			month := parsePlanningMonth(r.URL.Query().Get("month"), now())
			firstOfMonth := time.Date(month.Year(), month.Month(), 1, 0, 0, 0, 0, time.Local)
			lastOfMonth := firstOfMonth.AddDate(0, 1, -1)
			rows, err := deps.Queries.ListUserEventsRange(r.Context(), sqlc.ListUserEventsRangeParams{
				UserID:    user.ID,
				StartDate: pgDateFromTime(firstOfMonth),
				EndDate:   pgDateFromTime(lastOfMonth),
			})
			if err != nil {
				slog.Default().Error("planning: ListUserEventsRange (month) failed", "user_id", user.ID, "err", err)
				http.Error(w, "internal server error", http.StatusInternalServerError)
				return
			}
			cal = templates.BuildMonthCalendar(month, today, rows)
		}

		w.Header().Set("Content-Type", "text/html; charset=utf-8")
		_ = templates.PlanningCalendarPage(user, csrf.Token(r), "/planning", sidebarTablos, cal,
			"Planning",
			[]templates.BreadcrumbItem{{Label: "Planning", Href: ""}},
		).Render(r.Context(), w)
	}
}
