package ted

import (
	"fmt"
	"strconv"
	"strings"
	"time"
)

// ParseIssueDateTimeToUnix combines cbc:IssueDate and cbc:IssueTime (with timezone offsets) into one Unix timestamp.
func ParseIssueDateTimeToUnix(issueDate, issueTime string) int64 {
	issueDate = strings.TrimSpace(issueDate)
	issueTime = strings.TrimSpace(issueTime)
	if issueDate == "" {
		return 0
	}
	if issueTime == "" {
		return ParseDateToUnix(issueDate)
	}
	dateCore := issueDate
	if len(issueDate) >= 10 && issueDate[4] == '-' && issueDate[7] == '-' {
		dateCore = issueDate[:10]
	}
	combined := dateCore + "T" + issueTime
	if t, err := ParseDate(combined); err == nil {
		return t.Unix()
	}
	return ParseDateToUnix(issueDate)
}

// TransmissionDispatchUnix reads BT-803 (eSender) transmission date/time from extension content (root or eForms extension).
func TransmissionDispatchUnix(ext *UBLExtensions) int64 {
	if ext == nil || ext.UBLExtension == nil || ext.UBLExtension.ExtensionContent == nil {
		return 0
	}
	ec := ext.UBLExtension.ExtensionContent
	if u := ParseIssueDateTimeToUnix(ec.TransmissionDate, ec.TransmissionTime); u != 0 {
		return u
	}
	if ec.EformsExtension != nil {
		if u := ParseIssueDateTimeToUnix(ec.EformsExtension.TransmissionDate, ec.EformsExtension.TransmissionTime); u != 0 {
			return u
		}
	}
	return 0
}

// ParseEuropeanAmount normalizes TED amount strings (spaces, comma decimal) for strconv.ParseFloat.
func ParseEuropeanAmount(raw string) (float64, bool) {
	s := strings.TrimSpace(raw)
	s = strings.ReplaceAll(s, "\u00a0", "")
	s = strings.ReplaceAll(s, " ", "")
	s = strings.ReplaceAll(s, ",", ".")
	if s == "" {
		return 0, false
	}
	v, err := strconv.ParseFloat(s, 64)
	return v, err == nil
}

// parseDate parses various date formats used in TED XML
func ParseDate(dateStr string) (time.Time, error) {
	if dateStr == "" {
		return time.Time{}, fmt.Errorf("empty date string")
	}

	// Common TED date formats
	formats := []string{
		"2006-01-02+07:00",
		"2006-01-02-07:00",
		"2006-01-02T15:04:05+07:00",
		"2006-01-02T15:04:05-07:00",
		"2006-01-02T15:04:05Z",
		"2006-01-02Z",
		"2006-01-02",
		time.RFC3339,
		time.RFC3339Nano,
	}

	for _, format := range formats {
		if parsedTime, err := time.Parse(format, dateStr); err == nil {
			return parsedTime, nil
		}
	}

	return time.Time{}, fmt.Errorf("unable to parse date: %s", dateStr)
}

// parseDateToUnixMilli converts string date to Unix milliseconds (int64)
func ParseDateToUnix(dateStr string) int64 {
	if dateStr == "" {
		return 0
	}

	if parsedTime, err := ParseDate(dateStr); err == nil {
		return parsedTime.Unix()
	}

	return 0
}

// parseTimeToUnix converts string time to Unix milliseconds (int64)
func ParseTimeToUnix(timeStr string) int64 {
	if timeStr == "" {
		return 0
	}

	// If time string is just time without date, use today's date
	if !strings.Contains(timeStr, "T") && !strings.Contains(timeStr, " ") {
		// Assume it's just a time like "15:04:05"
		today := time.Now().Format("2006-01-02")
		timeStr = fmt.Sprintf("%sT%s", today, timeStr)
	}

	if parsedTime, err := ParseDate(timeStr); err == nil {
		return parsedTime.Unix()
	}

	return 0
}

func CalculateSubmissionDeadline(publicationDate time.Time) time.Time {
	deadline := publicationDate
	workingHoursAdded := 0

	for workingHoursAdded < 48 {
		deadline = deadline.Add(1 * time.Hour)

		if deadline.Weekday() != time.Saturday && deadline.Weekday() != time.Sunday {
			workingHoursAdded++
		}
	}

	return deadline
}

func CalculateApplicationDeadline(tenderDeadline time.Time) time.Time {
	applicationDeadline := tenderDeadline
	workingDaysSubtracted := 0

	for workingDaysSubtracted < 7 {
		applicationDeadline = applicationDeadline.AddDate(0, 0, -1)

		if applicationDeadline.Weekday() != time.Saturday && applicationDeadline.Weekday() != time.Sunday {
			workingDaysSubtracted++
		}
	}

	return applicationDeadline
}

// generateTenderURL generates the TED tender URL from NoticePublicationID
func GenerateTenderURL(noticePublicationID string) string {
	if noticePublicationID == "" {
		return ""
	}

	// Remove leading zeros and format for URL
	// Example: 00522942-2025 -> https://ted.europa.eu/en/notice/-/detail/522942-2025
	parts := strings.Split(noticePublicationID, "-")
	if len(parts) != 2 {
		return ""
	}

	// Convert to int and back to string to remove leading zeros
	if num, err := strconv.Atoi(parts[0]); err == nil {
		cleanID := fmt.Sprintf("%d-%s", num, parts[1])
		return fmt.Sprintf("https://ted.europa.eu/en/notice/-/detail/%s", cleanID)
	}

	return ""
}
