package templates

import (
	"strconv"
	"time"

	"backend/internal/db/sqlc"

	"github.com/google/uuid"
	"github.com/jackc/pgx/v5/pgtype"
)

type EventCreateForm struct {
	Title       string
	EventDate   string
	StartTime   string
	EndTime     string
	Location    string
	Description string
}

type EventCreateErrors struct {
	Title     string
	EventDate string
	StartTime string
	EndTime   string
	General   string
}

type EventsCalendar struct {
	Month          string
	MonthLabel     string
	PrevMonth      string
	PrevMonthLabel string
	NextMonth      string
	NextMonthLabel string
	Days           []EventCalendarDay
	WeekdayLabs    []string
}

type EventCalendarDay struct {
	Date      string
	DayNumber int
	InMonth   bool
	Events    []sqlc.Event
	MoreCount int
}

func DefaultWeekdayLabels() []string {
	return []string{"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"}
}

func EventFormFromEvent(event sqlc.Event) EventCreateForm {
	return EventCreateForm{
		Title:       event.Title,
		EventDate:   FormatEventDate(event.EventDate),
		StartTime:   FormatEventTime(event.StartTime),
		EndTime:     FormatOptionalEventTime(event.EndTime),
		Location:    event.Location.String,
		Description: event.Description.String,
	}
}

func FormatEventDate(date pgtype.Date) string {
	if !date.Valid {
		return ""
	}
	return date.Time.Format("2006-01-02")
}

func FormatEventTime(value pgtype.Time) string {
	if !value.Valid {
		return ""
	}
	minutes := value.Microseconds / int64(time.Minute/time.Microsecond)
	hours := minutes / 60
	mins := minutes % 60
	return twoDigits(int(hours)) + ":" + twoDigits(int(mins))
}

func FormatOptionalEventTime(value pgtype.Time) string {
	if !value.Valid {
		return ""
	}
	return FormatEventTime(value)
}

func EventTimeRange(event sqlc.Event) string {
	start := FormatEventTime(event.StartTime)
	if start == "" {
		return ""
	}
	if !event.EndTime.Valid {
		return start
	}
	return start + "-" + FormatEventTime(event.EndTime)
}

func EventDayEvents(events []sqlc.Event) []sqlc.Event {
	if len(events) <= 3 {
		return events
	}
	return events[:3]
}

func EventMoreLabel(count int) string {
	if count <= 0 {
		return ""
	}
	return "+" + strconv.Itoa(count) + " more"
}

func EventNewURL(tabloID uuid.UUID, month string) string {
	if month == "" {
		return "/tablos/" + tabloID.String() + "/events/new"
	}
	return "/tablos/" + tabloID.String() + "/events/new?month=" + month
}

func EventNewForDayURL(tabloID uuid.UUID, date string, month string) string {
	url := "/tablos/" + tabloID.String() + "/events/new?date=" + date
	if month != "" {
		url += "&month=" + month
	}
	return url
}

func EventPostURL(tabloID uuid.UUID, month string) string {
	if month == "" {
		return "/tablos/" + tabloID.String() + "/events"
	}
	return "/tablos/" + tabloID.String() + "/events?month=" + month
}

func EventEditURL(tabloID uuid.UUID, eventID uuid.UUID, month string) string {
	if month == "" {
		return "/tablos/" + tabloID.String() + "/events/" + eventID.String() + "/edit"
	}
	return "/tablos/" + tabloID.String() + "/events/" + eventID.String() + "/edit?month=" + month
}

func EventUpdateURL(tabloID uuid.UUID, eventID uuid.UUID, month string) string {
	if month == "" {
		return "/tablos/" + tabloID.String() + "/events/" + eventID.String()
	}
	return "/tablos/" + tabloID.String() + "/events/" + eventID.String() + "?month=" + month
}

func EventDeleteConfirmURL(tabloID uuid.UUID, eventID uuid.UUID, month string) string {
	if month == "" {
		return "/tablos/" + tabloID.String() + "/events/" + eventID.String() + "/delete-confirm"
	}
	return "/tablos/" + tabloID.String() + "/events/" + eventID.String() + "/delete-confirm?month=" + month
}

func EventDeleteURL(tabloID uuid.UUID, eventID uuid.UUID, month string) string {
	if month == "" {
		return "/tablos/" + tabloID.String() + "/events/" + eventID.String() + "/delete"
	}
	return "/tablos/" + tabloID.String() + "/events/" + eventID.String() + "/delete?month=" + month
}

func EventMonthURL(tabloID uuid.UUID, month string) string {
	return "/tablos/" + tabloID.String() + "/events?month=" + month
}

func twoDigits(value int) string {
	if value < 10 {
		return "0" + strconv.Itoa(value)
	}
	return strconv.Itoa(value)
}
