package handlers

import (
	"encoding/csv"
	"fmt"
	"io"
	"log"
	"net/http"
	"strconv"
	"strings"
	"time"

	"github.com/patel-mann/poll-system/app/internal/models"
	"github.com/patel-mann/poll-system/app/internal/utils"
)

// CSVUploadResult holds the results of CSV processing
type CSVUploadResult struct {
	TotalRecords      int
	ValidatedCount    int
	NotFoundCount     int
	ErrorCount        int
	ValidatedAddresses []string
	NotFoundAddresses  []string
	ErrorMessages     []string
}

// Combined CSV Upload Handler - handles both GET (display form) and POST (process CSV)
func CSVUploadHandler(w http.ResponseWriter, r *http.Request) {
	username, _ := models.GetCurrentUserName(r)
	
	// Base template data
	templateData := map[string]interface{}{
		"Title":           "CSV Address Validation",
		"IsAuthenticated": true,
		"ShowAdminNav":    true,
		"ActiveSection":   "address",
		"UserName":        username,
		"Role":            "admin",
	}

	// Handle GET request - show the upload form
	if r.Method == http.MethodGet {
		utils.Render(w, "csv-upload.html", templateData)
		return
	}

	// Handle POST request - process the CSV
	if r.Method == http.MethodPost {
		// Parse multipart form (10MB max)
		err := r.ParseMultipartForm(10 << 20)
		if err != nil {
			http.Error(w, "Error parsing form: "+err.Error(), http.StatusBadRequest)
			return
		}

		// Get form values
		addressColumnStr := r.FormValue("address_column")
		if addressColumnStr == "" {
			templateData["Error"] = "Address column is required"
			utils.Render(w, "csv-upload.html", templateData)
			return
		}

		addressColumn, err := strconv.Atoi(addressColumnStr)
		if err != nil {
			templateData["Error"] = "Invalid address column index"
			utils.Render(w, "csv-upload.html", templateData)
			return
		}

		// Get uploaded file
		file, header, err := r.FormFile("csv_file")
		if err != nil {
			templateData["Error"] = "Error retrieving file: " + err.Error()
			utils.Render(w, "csv-upload.html", templateData)
			return
		}
		defer file.Close()

		// Validate file type
		if !strings.HasSuffix(strings.ToLower(header.Filename), ".csv") {
			templateData["Error"] = "Please upload a CSV file"
			utils.Render(w, "csv-upload.html", templateData)
			return
		}

		// Read and parse CSV
		reader := csv.NewReader(file)
		reader.FieldsPerRecord = -1 // Allow variable number of fields

		var allRows [][]string
		for {
			record, err := reader.Read()
			if err == io.EOF {
				break
			}
			if err != nil {
				templateData["Error"] = "Error reading CSV: " + err.Error()
				utils.Render(w, "csv-upload.html", templateData)
				return
			}
			allRows = append(allRows, record)
		}

		if len(allRows) <= 1 {
			templateData["Error"] = "CSV file must contain data rows (header + at least 1 data row)"
			utils.Render(w, "csv-upload.html", templateData)
			return
		}

		// Validate address column index
		if addressColumn >= len(allRows[0]) {
			templateData["Error"] = "Invalid address column index"
			utils.Render(w, "csv-upload.html", templateData)
			return
		}

		// Process addresses
		result := processAddressValidation(allRows[1:], addressColumn) // Skip header
		
		// Add result to template data
		templateData["Result"] = result
		templateData["FileName"] = header.Filename

		// Render the same template with results
		utils.Render(w, "csv-upload.html", templateData)
		return
	}

	// Method not allowed
	http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
}

// processAddressValidation processes CSV data and validates addresses
func processAddressValidation(rows [][]string, addressColumn int) CSVUploadResult {
	result := CSVUploadResult{
		TotalRecords: len(rows),
	}

	for i, row := range rows {
		// Check if the row has enough columns
		if addressColumn >= len(row) {
			result.ErrorCount++
			result.ErrorMessages = append(result.ErrorMessages, 
				fmt.Sprintf("Row %d: Missing address column", i+2))
			continue
		}

		// Get and normalize address
		address := strings.ToLower(strings.TrimSpace(row[addressColumn]))
		if address == "" {
			result.ErrorCount++
			result.ErrorMessages = append(result.ErrorMessages, 
				fmt.Sprintf("Row %d: Empty address", i+2))
			continue
		}

		// Check if address exists in database
		var addressID int
		var currentStatus bool
		err := models.DB.QueryRow(`
			SELECT address_id, visited_validated 
			FROM address_database 
			WHERE LOWER(TRIM(address)) = $1
		`, address).Scan(&addressID, &currentStatus)

		if err != nil {
			// Address not found
			result.NotFoundCount++
			result.NotFoundAddresses = append(result.NotFoundAddresses, address)
			continue
		}

		// Address found - update validation status if not already validated
		if !currentStatus {
			_, err = models.DB.Exec(`
				UPDATE address_database 
				SET visited_validated = true, updated_at = NOW() 
				WHERE address_id = $1
			`, addressID)
			
			if err != nil {
				result.ErrorCount++
				result.ErrorMessages = append(result.ErrorMessages, 
					fmt.Sprintf("Row %d: Database update error for address '%s'", i+2, address))
				log.Printf("Error updating address %d: %v", addressID, err)
				continue
			}

			result.ValidatedCount++
			result.ValidatedAddresses = append(result.ValidatedAddresses, address)
		} else {
			// Address was already validated - still count as validated
			result.ValidatedCount++
			result.ValidatedAddresses = append(result.ValidatedAddresses, address+" (already validated)")
		}
	}

	return result
}

// Optional: Keep the export function if you need it
// ExportValidatedAddressesHandler exports validated addresses to CSV
func ExportValidatedAddressesHandler(w http.ResponseWriter, r *http.Request) {
	// Query validated addresses
	rows, err := models.DB.Query(`
		SELECT 
			a.address_id,
			a.address, 
			a.street_name, 
			a.street_type,
			a.street_quadrant, 
			a.house_number,
			COALESCE(a.house_alpha, '') as house_alpha,
			a.longitude, 
			a.latitude,
			a.visited_validated,
			a.created_at,
			a.updated_at,
			CASE 
				WHEN ap.sched_id IS NOT NULL THEN true 
				ELSE false 
			END as assigned,
			COALESCE(u.first_name || ' ' || u.last_name, '') as user_name,
			COALESCE(u.email, '') as user_email,
			COALESCE(ap.appointment_date::text, '') as appointment_date,
			COALESCE(ap.appointment_time::text, '') as appointment_time
		FROM address_database a
		LEFT JOIN appointment ap ON a.address_id = ap.address_id
		LEFT JOIN users u ON ap.user_id = u.user_id
		WHERE a.visited_validated = true
		ORDER BY a.updated_at DESC
	`)
	if err != nil {
		log.Println("Export query error:", err)
		http.Error(w, "Database error", http.StatusInternalServerError)
		return
	}
	defer rows.Close()

	// Set response headers for CSV download
	filename := fmt.Sprintf("validated_addresses_%s.csv", time.Now().Format("2006-01-02_15-04-05"))
	w.Header().Set("Content-Type", "text/csv")
	w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s\"", filename))

	// Create CSV writer
	writer := csv.NewWriter(w)
	defer writer.Flush()

	// Write header
	header := []string{
		"Address ID", "Address", "Street Name", "Street Type", "Street Quadrant",
		"House Number", "House Alpha", "Longitude", "Latitude", "Validated",
		"Created At", "Updated At", "Assigned", "Assigned User", "User Email",
		"Appointment Date", "Appointment Time",
	}
	writer.Write(header)

	// Write data rows (you'll need to define AddressWithDetails struct)
	// Implementation depends on your existing struct definitions
}