package dav

import (
	"crussell/clock"
	"fmt"
	"strings"
	"time"
)

// ============================================================================
// Calendar Types
// ============================================================================

type Calendar struct {
	ID            int    `json:"id"`
	PrincipalURI  string `json:"principaluri"`
	DisplayName   string `json:"displayname"`
	URI           string `json:"uri"`
	Description   string `json:"description"`
	CalendarOrder int    `json:"calendarorder"`
	CalendarColor string `json:"calendarcolor"`
	Components    string `json:"components"`
}

type CalendarEvent struct {
	ID             int      `json:"id"`
	CalendarID     int      `json:"calendarid"`
	URI            string   `json:"uri"`
	CalendarData   string   `json:"calendardata"`
	LastModified   int64    `json:"lastmodified"`
	Etag           string   `json:"etag"`
	Size           int      `json:"size"`
	ComponentType  string   `json:"componenttype"`
	FirstOccurence int64    `json:"firstoccurence"`
	LastOccurence  int64    `json:"lastoccurence"`
	UID            string   `json:"uid"`
	ContactURIs    []string `json:"contact_uris"` // Extracted from ATTENDEE fields
}

type EventInput struct {
	Summary     string
	Description string
	Location    string
	Start       time.Time
	End         time.Time
	AllDay      bool
	ContactURIs []string // URIs of contacts to attach as attendees
}

// ============================================================================
// CardDAV Types
// ============================================================================

type AddressBook struct {
	ID           int    `json:"id"`
	PrincipalURI string `json:"principaluri"`
	DisplayName  string `json:"displayname"`
	URI          string `json:"uri"`
	Description  string `json:"description"`
	SyncToken    int    `json:"synctoken"`
}

type Contact struct {
	ID            int    `json:"id"`
	AddressBookID int    `json:"addressbookid"`
	URI           string `json:"uri"`
	CardData      string `json:"carddata"`
	LastModified  int64  `json:"lastmodified"`
	Etag          string `json:"etag"`
	Size          int    `json:"size"`
}

type ContactInput struct {
	UserID    string
	FirstName string
	LastName  string
	Email     string
	Phone     string
	DOB       string
}

// ============================================================================
// Helper Functions
// ============================================================================

// GenerateICalEvent creates iCalendar format.
// All times stored in the system are UTC equivalents of Europe/London
// wall-clock times (e.g., 10:00 BST is stored as 09:00 UTC). The generated
// iCal uses UTC-flagged DTSTART/DTEND (with Z suffix) so calendar apps
// correctly display the intended wall-clock time regardless of the reader's
// timezone.
func GenerateICalEvent(input EventInput) string {
	uid := fmt.Sprintf("%d@example.com", clock.Now().UnixNano())
	dtstamp := clock.Now().UTC().Format("20060102T150405Z")

	var dtstart, dtend string
	if input.AllDay {
		dtstart = fmt.Sprintf("DTSTART;VALUE=DATE:%s", input.Start.Format("20060102"))
		dtend = fmt.Sprintf("DTEND;VALUE=DATE:%s", input.End.Format("20060102"))
	} else {
		dtstart = fmt.Sprintf("DTSTART:%sZ", input.Start.UTC().Format("20060102T150405"))
		dtend = fmt.Sprintf("DTEND:%sZ", input.End.UTC().Format("20060102T150405"))
	}

	// Build attendees section
	var attendees strings.Builder
	for _, contactURI := range input.ContactURIs {
		attendees.WriteString(fmt.Sprintf("ATTENDEE;CN=%s:%s\n", contactURI, contactURI))
	}

	ical := fmt.Sprintf(`BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Your App//EN
CALSCALE:GREGORIAN
BEGIN:VEVENT
UID:%s
DTSTAMP:%s
%s
%s
SUMMARY:%s
DESCRIPTION:%s
LOCATION:%s
%sSEQUENCE:0
STATUS:CONFIRMED
TRANSP:OPAQUE
END:VEVENT
END:VCALENDAR`, uid, dtstamp, dtstart, dtend,
		escapeICalText(input.Summary),
		escapeICalText(input.Description),
		escapeICalText(input.Location),
		attendees.String())

	return ical
}

// GenerateVCard creates vCard format (version 3.0)
func GenerateVCard(input ContactInput) string {
	vcard := fmt.Sprintf(`BEGIN:VCARD
VERSION:3.0
UID:%s
FN:%s %s
N:%s;%s;;;
EMAIL;TYPE=INTERNET:%s
TEL;TYPE=CELL:%s
BDAY:%s
REV:%s
END:VCARD`,
		input.UserID,
		input.FirstName, input.LastName,
		input.LastName, input.FirstName,
		input.Email,
		input.Phone,
		input.DOB,
		clock.Now().UTC().Format("20060102T150405Z"))

	return vcard
}

func escapeICalText(text string) string {
	text = replaceAll(text, "\\", "\\\\")
	text = replaceAll(text, "\n", "\\n")
	text = replaceAll(text, ",", "\\,")
	text = replaceAll(text, ";", "\\;")
	return text
}

func replaceAll(s, old, new string) string {
	var result strings.Builder
	for _, char := range s {
		if string(char) == old {
			result.WriteString(new)
		} else {
			result.WriteString(string(char))
		}
	}
	return result.String()
}
