package parser

import (
	"backend/utils"
	"regexp"
	"strconv"
	"strings"
	"time"
)

func parseDispTime(disp string, currConsegna *int) *string {
	if currConsegna == nil {
		return nil
	}
	var day int
	var err error
	if disp != "" {
		//get only the day part from disp
		parts := strings.Split(disp, "/")
		dayStr := strings.TrimSpace(parts[0])

		day, err = strconv.Atoi(dayStr)
		if err != nil || day < 1 || day > 31 {
			// Invalid day, default to 1
			day = 1
		}
	} else {
		day = 1
	}
	month := *currConsegna
	currMonth := int(time.Now().Month())
	year := time.Now().Year()
	if month < currMonth {
		year++
	}

	t := time.Date(year, time.Month(month), day, 0, 0, 0, 0, time.UTC)
	if t.Day() != day {
		// Invalid day for month, default to first day of month
		t = time.Date(year, time.Month(month), 1, 0, 0, 0, 0, time.UTC)

	}
	formatted := t.Format(time.DateOnly)
	return &formatted
}

func ParseDettaglio(dettaglio string, currConsegna *int) (disp_time *string, perm_arr *[]int, persone_arr *[]string, err error) {

	dettaglio = strings.TrimSpace(dettaglio)

	disp := getKeyValueUpToXorWhitespace(dettaglio, "disp:", "perm:")

	perm := getKeyValueUpToXorWhitespace(dettaglio, "perm:", "persone:")

	persone := getKeyValueUpToXorWhitespace(dettaglio, "persone:", "")

	disp_time = parseDispTime(disp, currConsegna)

	if perm != "" {
		parts := strings.Split(perm, "-")
		for _, part := range parts {
			part = strings.TrimSpace(part)
			if part != "" {
				num, err := strconv.Atoi(part)
				if err == nil {
					if perm_arr == nil {
						perm_arr = &[]int{}
					}
					*perm_arr = append(*perm_arr, num)
				}
			}
		}
	}
	if persone != "" {
		parts := strings.Split(persone, "/")
		for _, part := range parts {
			part = strings.TrimSpace(part)
			if part != "" {
				if persone_arr == nil {
					persone_arr = &[]string{}
				}
				*persone_arr = append(*persone_arr, part)
			}
		}
	}
	return

}

func getKeyValueUpToXorWhitespace(input, key, stopstring string) string {
	input = strings.TrimSpace(input)
	i := strings.Index(input, key)
	if i == -1 {
		return ""
	}
	start := i + len(key)
	rest := strings.TrimSpace(input[start:])

	// Find stopstring, whitespace, or repeated key
	stop_pos := len(rest)
	stops := []int{}

	if stopstring != "" {
		if j := strings.Index(rest, stopstring); j != -1 {
			stops = append(stops, j)
		}
	}
	// Find whitespace
	if ws := strings.IndexAny(rest, " \n\r\t"); ws != -1 {
		stops = append(stops, ws)
	}
	// Find repeated key
	if k := strings.Index(rest, key); k != -1 {
		stops = append(stops, k)
	}
	// Use the earliest stop
	for _, s := range stops {
		if s < stop_pos {
			stop_pos = s
		}
	}

	val := strings.TrimSpace(rest[:stop_pos])
	// Only take the first token before any whitespace or another key
	if idx := strings.IndexAny(val, " \n\r\t"); idx != -1 {
		val = val[:idx]
	}
	//fmt.Printf("Extracted value for key '%s': '%s'\n", key, val)
	return val
}

var mesiMapping = map[int]string{
	1:  "Gennaio",
	2:  "Febbraio",
	3:  "Marzo",
	4:  "Aprile",
	5:  "Maggio",
	6:  "Giugno",
	7:  "Luglio",
	8:  "Agosto",
	9:  "Settembre",
	10: "Ottobre",
	11: "Novembre",
	12: "Dicembre",
}

func ParseConsegna(original *string) *int {
	currentMonth := int(time.Now().Month())
	if original == nil {
		return nil
	}
	if *original == "Libero" {
		return &currentMonth
	} else {
		for k, v := range mesiMapping {
			if *original == v {
				return &k
			}
		}
	}
	return &currentMonth
}

func ParsePrezzo(input *string) int {
	if input == nil || len(*input) == 0 {
		return 0
	}
	s := *input
	s = strings.ReplaceAll(s, "€", "")
	s = strings.ReplaceAll(s, " ", "")
	s = strings.ReplaceAll(s, ".", "")
	s = strings.ReplaceAll(s, ",", ".")
	re := regexp.MustCompile(`\d+(\.\d+)?`)
	match := re.FindString(s)
	if match == "" {
		return 0
	}
	f, err := strconv.ParseFloat(match, 64)
	if err != nil {
		return 0
	}
	return int(f * 100)
}

func ParseTipologia(t1, t2 *string) (tipo *string) {

	if t1 == nil {
		return utils.Ptr("Errore")
	}

	if *t1 == "V" {
		return utils.Ptr("Vendita")
	}

	if *t1 == "I" {
		return utils.Ptr("Cessione")
	}

	if *t1 == "A" {
		if t2 != nil {
			normalized := strings.TrimSpace(*t2)
			normalized = strings.ToLower(normalized)
			switch normalized {
			case "residenziale", "turistico", "stanza":
				return utils.Ptr("Transitorio")
			}
		}
		return utils.Ptr("Stabile")
	}
	return utils.Ptr("Errore")

}

func ParseEmail(input *string) *string {
	if input == nil {
		return nil
	}
	email := strings.TrimLeft(*input, " ")
	if email == "" {
		return nil
	}
	parts := strings.Split(email, " ")
	if len(parts) > 0 {
		email = parts[0]
	}
	email = strings.TrimSpace(email)
	if email == "" {
		return nil
	}
	// Basic email validation
	if !isValidEmail(email) {
		return nil
	}

	return &email
}

func isValidEmail(email string) bool {
	// Must contain exactly one @ symbol
	atCount := strings.Count(email, "@")
	if atCount != 1 {
		return false
	}

	// Split on @ to get local and domain parts
	parts := strings.Split(email, "@")
	if len(parts) != 2 {
		return false
	}

	local := parts[0]
	domain := parts[1]

	// Local part cannot be empty
	if local == "" {
		return false
	}

	// Domain part cannot be empty
	if domain == "" {
		return false
	}

	// Domain must contain at least one dot
	if !strings.Contains(domain, ".") {
		return false
	}

	// Domain cannot start or end with dot
	if strings.HasPrefix(domain, ".") || strings.HasSuffix(domain, ".") {
		return false
	}

	// Domain cannot have consecutive dots
	if strings.Contains(domain, "..") {
		return false
	}

	// Local part cannot start or end with dot
	if strings.HasPrefix(local, ".") || strings.HasSuffix(local, ".") {
		return false
	}

	// Local part cannot have consecutive dots
	if strings.Contains(local, "..") {
		return false
	}

	// Basic check for valid characters (this is simplified)
	// In production, you might want to use a proper regex or email validation library
	for _, char := range email {
		if char == ' ' || char == '\t' || char == '\n' || char == '\r' {
			return false
		}
	}

	return true
}
