package utils

import (
	"net/url"
	"strconv"
	"strings"
	"time"
)

// QueryParser parses HTTP query parameters into DynamicQuery
type QueryParser struct {
	defaultLimit int
	maxLimit     int
}

// NewQueryParser creates a new query parser
func NewQueryParser() *QueryParser {
	return &QueryParser{
		defaultLimit: 10,
		maxLimit:     100,
	}
}

// SetLimits sets default and maximum limits
func (qp *QueryParser) SetLimits(defaultLimit, maxLimit int) *QueryParser {
	qp.defaultLimit = defaultLimit
	qp.maxLimit = maxLimit
	return qp
}

// ParseQuery parses URL query parameters into DynamicQuery
func (qp *QueryParser) ParseQuery(values url.Values) (DynamicQuery, error) {
	query := DynamicQuery{
		Limit:  qp.defaultLimit,
		Offset: 0,
	}

	// Parse fields
	if fields := values.Get("fields"); fields != "" {
		if fields == "*.*" || fields == "*" {
			query.Fields = []string{"*"}
		} else {
			query.Fields = strings.Split(fields, ",")
			for i, field := range query.Fields {
				query.Fields[i] = strings.TrimSpace(field)
			}
		}
	}

	// Parse pagination
	if limit := values.Get("limit"); limit != "" {
		if l, err := strconv.Atoi(limit); err == nil {
			if l > 0 && l <= qp.maxLimit {
				query.Limit = l
			}
		}
	}

	if offset := values.Get("offset"); offset != "" {
		if o, err := strconv.Atoi(offset); err == nil && o >= 0 {
			query.Offset = o
		}
	}

	// Parse filters
	filters, err := qp.parseFilters(values)
	if err != nil {
		return query, err
	}
	query.Filters = filters

	// Parse sorting
	sorts, err := qp.parseSorting(values)
	if err != nil {
		return query, err
	}
	query.Sort = sorts

	// Parse group by
	if groupBy := values.Get("group"); groupBy != "" {
		query.GroupBy = strings.Split(groupBy, ",")
		for i, field := range query.GroupBy {
			query.GroupBy[i] = strings.TrimSpace(field)
		}
	}

	return query, nil
}

// parseFilters parses filter parameters
// Supports format: filter[column][operator]=value
func (qp *QueryParser) parseFilters(values url.Values) ([]FilterGroup, error) {
	filterMap := make(map[string]map[string]string)

	// Group filters by column
	for key, vals := range values {
		if strings.HasPrefix(key, "filter[") && strings.HasSuffix(key, "]") {
			// Parse filter[column][operator] format
			parts := strings.Split(key[7:len(key)-1], "][")
			if len(parts) == 2 {
				column := parts[0]
				operator := parts[1]

				if filterMap[column] == nil {
					filterMap[column] = make(map[string]string)
				}

				if len(vals) > 0 {
					filterMap[column][operator] = vals[0]
				}
			}
		}
	}

	if len(filterMap) == 0 {
		return nil, nil
	}

	// Convert to FilterGroup
	var filters []DynamicFilter

	for column, operators := range filterMap {
		for opStr, value := range operators {
			operator := FilterOperator(opStr)

			// Parse value based on operator
			var parsedValue interface{}
			switch operator {
			case OpIn, OpNotIn:
				if value != "" {
					parsedValue = strings.Split(value, ",")
				}
			case OpBetween, OpNotBetween:
				if value != "" {
					parts := strings.Split(value, ",")
					if len(parts) == 2 {
						parsedValue = []interface{}{strings.TrimSpace(parts[0]), strings.TrimSpace(parts[1])}
					}
				}
			case OpNull, OpNotNull:
				parsedValue = nil
			default:
				parsedValue = value
			}

			filters = append(filters, DynamicFilter{
				Column:   column,
				Operator: operator,
				Value:    parsedValue,
			})
		}
	}

	if len(filters) == 0 {
		return nil, nil
	}

	return []FilterGroup{{
		Filters: filters,
		LogicOp: "AND",
	}}, nil
}

// parseSorting parses sort parameters
// Supports format: sort=column1,-column2 (- for DESC)
func (qp *QueryParser) parseSorting(values url.Values) ([]SortField, error) {
	sortParam := values.Get("sort")
	if sortParam == "" {
		return nil, nil
	}

	var sorts []SortField
	fields := strings.Split(sortParam, ",")

	for _, field := range fields {
		field = strings.TrimSpace(field)
		if field == "" {
			continue
		}

		order := "ASC"
		column := field

		if strings.HasPrefix(field, "-") {
			order = "DESC"
			column = field[1:]
		} else if strings.HasPrefix(field, "+") {
			column = field[1:]
		}

		sorts = append(sorts, SortField{
			Column: column,
			Order:  order,
		})
	}

	return sorts, nil
}

// ParseAdvancedFilters parses complex filter structures
// Supports nested filters and logic operators
func (qp *QueryParser) ParseAdvancedFilters(filterParam string) ([]FilterGroup, error) {
	// This would be for more complex JSON-based filters
	// Implementation depends on your specific needs
	return nil, nil
}

// Helper function to parse date values
func parseDate(value string) (interface{}, error) {
	// Try different date formats
	formats := []string{
		"2006-01-02",
		"2006-01-02T15:04:05Z",
		"2006-01-02T15:04:05.000Z",
		"2006-01-02 15:04:05",
	}

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

	return value, nil
}

// Helper function to parse numeric values
func parseNumeric(value string) interface{} {
	// Try integer first
	if i, err := strconv.Atoi(value); err == nil {
		return i
	}

	// Try float
	if f, err := strconv.ParseFloat(value, 64); err == nil {
		return f
	}

	// Return as string
	return value
}
