package handlers

import (
	"fmt"
	"log"
	"net/http"
	"strconv"
	"strings"
	"time"

	"tankstopp/internal/currency"
	"tankstopp/internal/models"
	"tankstopp/internal/views/pages"

	"github.com/gorilla/mux"
)

// AddFuelStopHandler handles adding new fuel stops
func (h *Handler) AddFuelStopHandler(w http.ResponseWriter, r *http.Request) {
	userID, _ := h.getCurrentUser(r)
	if userID == 0 {
		http.Redirect(w, r, "/login", http.StatusSeeOther)
		return
	}

	switch r.Method {
	case "GET":
		// Get user for default currency
		user, err := h.db.GetUserByID(userID)
		if err != nil {
			log.Printf("Error getting user: %v", err)
			http.Error(w, "Internal server error", http.StatusInternalServerError)
			return
		}

		// Get vehicles for the user
		vehicles, err := h.db.GetVehicles(userID)
		if err != nil {
			log.Printf("Error getting vehicles: %v", err)
			http.Error(w, "Internal server error", http.StatusInternalServerError)
			return
		}

		// Render add fuel stop form using templ
		currencies := currency.SupportedCurrencies()
		component := pages.AddFuelStopPage(user, user.Username, vehicles, currencies)

		w.Header().Set("Content-Type", "text/html")
		err = component.Render(r.Context(), w)
		if err != nil {
			log.Printf("Error rendering template: %v", err)
			http.Error(w, "Internal server error", http.StatusInternalServerError)
		}
	case "POST":
		h.handleAddFuelStop(w, r, userID)
	default:
		http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
	}
}

// handleAddFuelStop processes the form submission for adding fuel stops
func (h *Handler) handleAddFuelStop(w http.ResponseWriter, r *http.Request, userID uint) {
	err := r.ParseForm()
	if err != nil {
		log.Printf("Error parsing form: %v", err)
		http.Error(w, "Bad request", http.StatusBadRequest)
		return
	}

	// Parse form data
	form := models.FuelStopForm{
		Date:        strings.TrimSpace(r.FormValue("date")),
		VehicleID:   parseUint(r.FormValue("vehicle_id")),
		StationName: strings.TrimSpace(r.FormValue("station_name")),
		Location:    strings.TrimSpace(r.FormValue("location")),
		FuelType:    r.FormValue("fuel_type"),
		Liters:      parseFloat(r.FormValue("amount")),
		PricePerL:   parseFloat(r.FormValue("price_per_liter")),
		TotalPrice:  parseFloat(r.FormValue("total_cost")),
		Currency:    r.FormValue("currency"),
		Odometer:    parseInt(r.FormValue("odometer")),
		TripLength:  parseFloat(r.FormValue("trip_length")),
		Notes:       r.FormValue("notes"),
	}

	// Validate form
	if err := h.validateFuelStopForm(&form); err != nil {
		log.Printf("Validation error: %v", err)
		http.Redirect(w, r, "/add?error="+err.Error(), http.StatusSeeOther)
		return
	}

	// Convert form to fuel stop
	fuelStop, err := form.ToFuelStop(userID)
	if err != nil {
		log.Printf("Error converting form to fuel stop: %v", err)
		http.Redirect(w, r, "/add?error=Invalid+date+format", http.StatusSeeOther)
		return
	}

	// Use station name as location if location is empty
	if fuelStop.Location == "" {
		fuelStop.Location = fuelStop.StationName
	}

	// Save to database
	err = h.db.CreateFuelStop(fuelStop)
	if err != nil {
		log.Printf("Error creating fuel stop: %v", err)
		http.Redirect(w, r, "/add?error=Failed+to+save+fuel+stop", http.StatusSeeOther)
		return
	}

	// Redirect to dashboard with success message
	http.Redirect(w, r, "/dashboard?success=Fuel+stop+added+successfully", http.StatusSeeOther)
}

// EditFuelStopHandler handles editing existing fuel stops
func (h *Handler) EditFuelStopHandler(w http.ResponseWriter, r *http.Request) {
	userID, _ := h.getCurrentUser(r)
	if userID == 0 {
		http.Redirect(w, r, "/login", http.StatusSeeOther)
		return
	}

	// Get the user object
	user, err := h.db.GetUserByID(userID)
	if err != nil {
		log.Printf("Error getting user: %v", err)
		http.Error(w, "Internal server error", http.StatusInternalServerError)
		return
	}

	vars := mux.Vars(r)
	idInt, err := strconv.Atoi(vars["id"])
	if err != nil {
		http.Error(w, "Invalid ID", http.StatusBadRequest)
		return
	}
	id := uint(idInt)

	switch r.Method {
	case "GET":
		stop, err := h.db.GetFuelStopByID(id, userID)
		if err != nil {
			log.Printf("Error getting fuel stop: %v", err)
			http.Error(w, "Internal server error", http.StatusInternalServerError)
			return
		}
		if stop == nil {
			http.Error(w, "Fuel stop not found", http.StatusNotFound)
			return
		}

		// Get vehicles for the user
		vehicles, err := h.db.GetVehicles(userID)
		if err != nil {
			log.Printf("Error getting vehicles: %v", err)
			http.Error(w, "Internal server error", http.StatusInternalServerError)
			return
		}

		// Render edit fuel stop form using templ
		currencies := currency.SupportedCurrencies()
		component := pages.EditFuelStopPage(user, user.Username, stop, vehicles, currencies)

		w.Header().Set("Content-Type", "text/html")
		err = component.Render(r.Context(), w)
		if err != nil {
			log.Printf("Error rendering template: %v", err)
			http.Error(w, "Internal server error", http.StatusInternalServerError)
		}
	case "POST":
		h.handleEditFuelStop(w, r, id, userID)
	default:
		http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
	}
}

// handleEditFuelStop processes the form submission for editing fuel stops
func (h *Handler) handleEditFuelStop(w http.ResponseWriter, r *http.Request, id, userID uint) {
	err := r.ParseForm()
	if err != nil {
		log.Printf("Error parsing form: %v", err)
		http.Error(w, "Bad request", http.StatusBadRequest)
		return
	}

	// Get existing fuel stop
	existingStop, err := h.db.GetFuelStopByID(id, userID)
	if err != nil {
		log.Printf("Error getting fuel stop: %v", err)
		http.Error(w, "Internal server error", http.StatusInternalServerError)
		return
	}
	if existingStop == nil {
		http.Error(w, "Fuel stop not found", http.StatusNotFound)
		return
	}

	// Parse form data
	form := models.FuelStopForm{
		Date:        strings.TrimSpace(r.FormValue("date")),
		VehicleID:   parseUint(r.FormValue("vehicle_id")),
		StationName: strings.TrimSpace(r.FormValue("station_name")),
		Location:    strings.TrimSpace(r.FormValue("location")),
		FuelType:    r.FormValue("fuel_type"),
		Liters:      parseFloat(r.FormValue("amount")),
		PricePerL:   parseFloat(r.FormValue("price_per_liter")),
		TotalPrice:  parseFloat(r.FormValue("total_cost")),
		Currency:    r.FormValue("currency"),
		Odometer:    parseInt(r.FormValue("odometer")),
		TripLength:  parseFloat(r.FormValue("trip_length")),
		Notes:       r.FormValue("notes"),
	}

	// Validate form
	if err := h.validateFuelStopForm(&form); err != nil {
		log.Printf("Validation error: %v", err)
		http.Redirect(w, r, fmt.Sprintf("/edit/%d?error=%s", id, err.Error()), http.StatusSeeOther)
		return
	}

	// Convert form to fuel stop
	updatedStop, err := form.ToFuelStop(userID)
	if err != nil {
		log.Printf("Error converting form to fuel stop: %v", err)
		http.Redirect(w, r, fmt.Sprintf("/edit/%d?error=Invalid+date+format", id), http.StatusSeeOther)
		return
	}

	// Set the ID to update existing record
	updatedStop.ID = id

	// Use station name as location if location is empty
	if updatedStop.Location == "" {
		updatedStop.Location = updatedStop.StationName
	}

	// Update in database
	err = h.db.UpdateFuelStop(updatedStop)
	if err != nil {
		log.Printf("Error updating fuel stop: %v", err)
		http.Redirect(w, r, fmt.Sprintf("/edit/%d?error=Failed+to+update+fuel+stop", id), http.StatusSeeOther)
		return
	}

	// Redirect to dashboard with success message
	http.Redirect(w, r, "/dashboard?success=Fuel+stop+updated+successfully", http.StatusSeeOther)
}

// DeleteFuelStopHandler handles deleting fuel stops
func (h *Handler) DeleteFuelStopHandler(w http.ResponseWriter, r *http.Request) {
	if r.Method != "POST" {
		http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
		return
	}

	userID, _ := h.getCurrentUser(r)
	if userID == 0 {
		http.Redirect(w, r, "/login", http.StatusSeeOther)
		return
	}

	vars := mux.Vars(r)
	idInt, err := strconv.Atoi(vars["id"])
	if err != nil {
		http.Error(w, "Invalid ID", http.StatusBadRequest)
		return
	}
	id := uint(idInt)

	// Verify fuel stop exists and belongs to user
	fuelStop, err := h.db.GetFuelStopByID(id, userID)
	if err != nil {
		log.Printf("Error getting fuel stop: %v", err)
		http.Error(w, "Internal server error", http.StatusInternalServerError)
		return
	}
	if fuelStop == nil {
		http.Error(w, "Fuel stop not found", http.StatusNotFound)
		return
	}

	// Delete fuel stop
	err = h.db.DeleteFuelStop(id, userID)
	if err != nil {
		log.Printf("Error deleting fuel stop: %v", err)
		http.Redirect(w, r, "/dashboard?error=Failed+to+delete+fuel+stop", http.StatusSeeOther)
		return
	}

	// Redirect to dashboard with success message
	http.Redirect(w, r, "/dashboard?success=Fuel+stop+deleted+successfully", http.StatusSeeOther)
}

// validateFuelStopForm validates the fuel stop form data
func (h *Handler) validateFuelStopForm(form *models.FuelStopForm) error {
	if form.Date == "" {
		return fmt.Errorf("Date is required")
	}

	// Validate date format
	_, err := time.Parse("2006-01-02", form.Date)
	if err != nil {
		return fmt.Errorf("Invalid date format")
	}

	if form.VehicleID == 0 {
		return fmt.Errorf("Vehicle is required")
	}

	if form.StationName == "" && form.Location == "" {
		return fmt.Errorf("Station name or location is required")
	}

	if form.FuelType == "" {
		return fmt.Errorf("Fuel type is required")
	}

	if form.Liters <= 0 {
		return fmt.Errorf("Amount must be greater than 0")
	}

	if form.PricePerL <= 0 {
		return fmt.Errorf("Price per liter must be greater than 0")
	}

	if form.TotalPrice <= 0 {
		return fmt.Errorf("Total price must be greater than 0")
	}

	if form.Currency != "" && !currency.IsValidCurrency(form.Currency) {
		return fmt.Errorf("Invalid currency")
	}

	if form.Odometer < 0 {
		return fmt.Errorf("Odometer reading cannot be negative")
	}

	if form.TripLength < 0 {
		return fmt.Errorf("Trip length cannot be negative")
	}

	if form.TripLength > 2000 {
		return fmt.Errorf("Trip length cannot exceed 2000 km")
	}

	// Validate consumption if both trip length and amount are provided
	if form.TripLength > 0 && form.Liters > 0 {
		consumption := (form.Liters / form.TripLength) * 100
		if consumption > 50 {
			return fmt.Errorf("Fuel consumption %.1f L/100km seems unrealistic. Please check trip length and amount", consumption)
		}
		if consumption < 1 {
			return fmt.Errorf("Fuel consumption %.1f L/100km seems too low. Please check trip length and amount", consumption)
		}
	}

	return nil
}

// Helper functions for parsing form values
func parseFloat(s string) float64 {
	if s == "" {
		return 0
	}
	f, err := strconv.ParseFloat(s, 64)
	if err != nil {
		return 0
	}
	return f
}

func parseInt(s string) int {
	if s == "" {
		return 0
	}
	i, err := strconv.Atoi(s)
	if err != nil {
		return 0
	}
	return i
}

func parseUint(s string) uint {
	if s == "" {
		return 0
	}
	i, err := strconv.ParseUint(s, 10, 32)
	if err != nil {
		return 0
	}
	return uint(i)
}
