package importer

import (
	"fmt"
	"regexp"
	"sort"
	"strconv"
	"strings"

	"github.com/xuri/excelize/v2"

	"git.dumerain.org/alban/calcul-astreintes/internal/models"
)

// Feuille de mois acceptée :
// - YYYY-MM  (ex: 2025-01)
// - MM-YYYY  (ex: 01-2025)
var sheetRe = regexp.MustCompile(`^(\d{4})-(\d{2})$|^(\d{2})-(\d{4})$`)

func normalizeYearMonth(sheet string) (string, bool) {
	sheet = strings.TrimSpace(sheet)
	m := sheetRe.FindStringSubmatch(sheet)
	if m == nil {
		return "", false
	}
	// YYYY-MM
	if m[1] != "" && m[2] != "" {
		return fmt.Sprintf("%s-%s", m[1], m[2]), true
	}
	// MM-YYYY
	if m[3] != "" && m[4] != "" {
		return fmt.Sprintf("%s-%s", m[4], m[3]), true
	}
	return "", false
}

// parseNumberFR convertit "1,92" / "1.92" / "" -> float64
func parseNumberFR(s string) float64 {
	s = strings.TrimSpace(s)
	if s == "" {
		return 0
	}
	s = strings.ReplaceAll(s, "\u00a0", "")
	s = strings.ReplaceAll(s, " ", "")
	s = strings.ReplaceAll(s, ",", ".")
	f, _ := strconv.ParseFloat(s, 64)
	return f
}

func isMatriculeCell(s string) bool {
	s = strings.TrimSpace(s)
	if s == "" {
		return false
	}
	for _, r := range s {
		if r < '0' || r > '9' {
			return false
		}
	}
	return true
}

// FindMonthSheet: prend la première feuille qui match YYYY-MM ou MM-YYYY, sinon la première feuille.
func FindMonthSheet(f *excelize.File) (string, error) {
	sheets := f.GetSheetList()
	for _, sh := range sheets {
		if _, ok := normalizeYearMonth(sh); ok {
			return strings.TrimSpace(sh), nil
		}
	}
	if len(sheets) == 0 {
		return "", fmt.Errorf("aucune feuille trouvée dans le fichier")
	}
	return sheets[0], nil
}

// ParseAgentsAndTotals lit la feuille détectée et renvoie agents + totaux.
// (Le mois est géré côté app/app.go via normalizeYearMonth)
func ParseAgentsAndTotals(path string) ([]models.Agent, map[string]models.AgentTotals, error) {
	f, err := excelize.OpenFile(path)
	if err != nil {
		return nil, nil, err
	}
	defer func() { _ = f.Close() }()

	sheet, err := FindMonthSheet(f)
	if err != nil {
		return nil, nil, err
	}

	rows, err := f.GetRows(sheet)
	if err != nil {
		return nil, nil, err
	}

	agents := []models.Agent{}
	totals := map[string]models.AgentTotals{}

	// Dedup P_DIM-JF par agent (par date)
	dimDates := map[string]map[string]struct{}{}
	currentMatricule := ""

	cell := func(col string, excelRow int) string {
		v, _ := f.GetCellValue(sheet, fmt.Sprintf("%s%d", col, excelRow))
		return v
	}

	for i := 0; i < len(rows); i++ {
		row := rows[i]

		colA := ""
		if len(row) >= 1 {
			colA = row[0]
		}

		if isMatriculeCell(colA) {
			currentMatricule = strings.TrimSpace(colA)

			if _, ok := totals[currentMatricule]; !ok {
				fullName := ""
				if len(row) >= 2 {
					fullName = strings.TrimSpace(row[1]) // Col B = "NOM Prenom"
				}

				nom, prenom := "", ""
				if fullName != "" {
					parts := strings.Fields(fullName)
					if len(parts) >= 1 {
						nom = parts[0]
					}
					if len(parts) >= 2 {
						prenom = strings.Join(parts[1:], " ")
					}
				}

				displayName := strings.TrimSpace(strings.Join([]string{nom, prenom}, " "))
				if displayName == "" {
					displayName = currentMatricule
				}
				display := fmt.Sprintf("%s (%s)", displayName, currentMatricule)

				if i == 0 {
					continue
				}

				totalExcelRow := i // ligne au-dessus en Excel (cf logique actuelle)

				q471 := parseNumberFR(cell("G", totalExcelRow))
				q456 := parseNumberFR(cell("L", totalExcelRow))
				q459 := parseNumberFR(cell("M", totalExcelRow))
				q458 := parseNumberFR(cell("N", totalExcelRow))

				agents = append(agents, models.Agent{
					Matricule: currentMatricule,
					Nom:       nom,
					Prenom:    prenom,
					Display:   display,
				})

				totals[currentMatricule] = models.AgentTotals{
					Matricule:  currentMatricule,
					Q471:       q471,
					Q456:       q456,
					Q459:       q459,
					Q458:       q458,
					NbDimFerie: 0,
				}
			}
		}

		if currentMatricule != "" {
			typeLigne := ""
			if len(row) >= 3 {
				typeLigne = strings.TrimSpace(row[2]) // Col C
			}
			if typeLigne == "P_DIM-JF" {
				dateStr := ""
				if len(row) >= 4 {
					dateStr = strings.TrimSpace(row[3]) // Col D
				}
				if _, ok := dimDates[currentMatricule]; !ok {
					dimDates[currentMatricule] = map[string]struct{}{}
				}
				if dateStr != "" {
					dimDates[currentMatricule][dateStr] = struct{}{}
				} else {
					dimDates[currentMatricule][fmt.Sprintf("row-%d", i+1)] = struct{}{}
				}
			}
		}
	}

	for mat, t := range totals {
		if s, ok := dimDates[mat]; ok {
			t.NbDimFerie = len(s)
			totals[mat] = t
		}
	}

	sort.Slice(agents, func(i, j int) bool {
		return strings.ToLower(agents[i].Display) < strings.ToLower(agents[j].Display)
	})

	return agents, totals, nil
}
