package handlers

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

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

// ReportData represents the combined data for reports
type ReportData struct {
	Users         []models.User
	Polls         []PollWithDetails
	Appointments  []AppointmentWithDetails
	Addresses     []models.AddressDatabase
	Teams         []TeamWithDetails
	TotalUsers    int
	TotalPolls    int
	TotalAddresses int
}

type PollWithDetails struct {
	PollID          int       `json:"poll_id"`
	UserID          int       `json:"user_id"`
	AuthorName      string    `json:"author_name"`
	AddressID       int       `json:"address_id"`
	Address         string    `json:"address"`
	PollTitle       string    `json:"poll_title"`
	PollDescription string    `json:"poll_description"`
	IsActive        bool      `json:"is_active"`
	AmountDonated   float64   `json:"amount_donated"`
	CreatedAt       time.Time `json:"created_at"`
	UpdatedAt       time.Time `json:"updated_at"`
}

type AppointmentWithDetails struct {
	SchedID         int       `json:"sched_id"`
	UserID          int       `json:"user_id"`
	UserName        string    `json:"user_name"`
	AddressID       int       `json:"address_id"`
	Address         string    `json:"address"`
	AppointmentDate time.Time `json:"appointment_date"`
	AppointmentTime time.Time `json:"appointment_time"`
	CreatedAt       time.Time `json:"created_at"`
}

type TeamWithDetails struct {
	TeamID       int    `json:"team_id"`
	TeamLeadID   int    `json:"team_lead_id"`
	TeamLeadName string `json:"team_lead_name"`
	VolunteerID  int    `json:"volunteer_id"`
	VolunteerName string `json:"volunteer_name"`
	CreatedAt    time.Time `json:"created_at"`
}

// ReportHandler handles the report page with search and filter functionality
func ReportHandler(w http.ResponseWriter, r *http.Request) {
	// currentUserID := r.Context().Value("user_id").(int)
	username, _ := models.GetCurrentUserName(r)
	role := r.Context().Value("user_role").(int)

	// Check if user has permission to view reports
	if role != 1 { // Assuming role 1 is admin
		http.Error(w, "Unauthorized", http.StatusForbidden)
		return
	}

	// Parse query parameters for filtering
	searchType := r.URL.Query().Get("search_type")     // users, polls, appointments, addresses, teams
	searchQuery := r.URL.Query().Get("search_query")   // general search term
	dateFrom := r.URL.Query().Get("date_from")
	dateTo := r.URL.Query().Get("date_to")
	roleFilter := r.URL.Query().Get("role_filter")
	statusFilter := r.URL.Query().Get("status_filter") // active, inactive for polls
	sortBy := r.URL.Query().Get("sort_by")             // created_at, name, email, etc.
	sortOrder := r.URL.Query().Get("sort_order")       // asc, desc
	page := r.URL.Query().Get("page")
	limit := r.URL.Query().Get("limit")

	// Set defaults
	if sortBy == "" {
		sortBy = "created_at"
	}
	if sortOrder == "" {
		sortOrder = "desc"
	}
	if page == "" {
		page = "1"
	}
	if limit == "" {
		limit = "50"
	}

	pageInt, _ := strconv.Atoi(page)
	limitInt, _ := strconv.Atoi(limit)
	offset := (pageInt - 1) * limitInt

	reportData := ReportData{}

	// Build queries based on search type and filters
	switch searchType {
	case "users":
		reportData.Users = searchUsers(searchQuery, roleFilter, dateFrom, dateTo, sortBy, sortOrder, limitInt, offset)
		reportData.TotalUsers = countUsers(searchQuery, roleFilter, dateFrom, dateTo)
	case "polls":
		reportData.Polls = searchPolls(searchQuery, statusFilter, dateFrom, dateTo, sortBy, sortOrder, limitInt, offset)
		reportData.TotalPolls = countPolls(searchQuery, statusFilter, dateFrom, dateTo)
	case "appointments":
		reportData.Appointments = searchAppointments(searchQuery, dateFrom, dateTo, sortBy, sortOrder, limitInt, offset)
	case "addresses":
		reportData.Addresses = searchAddresses(searchQuery, dateFrom, dateTo, sortBy, sortOrder, limitInt, offset)
		reportData.TotalAddresses = countAddresses(searchQuery, dateFrom, dateTo)
	case "teams":
		reportData.Teams = searchTeams(searchQuery, dateFrom, dateTo, sortBy, sortOrder, limitInt, offset)
	default:
		// Load summary data for all types
		reportData.Users = searchUsers("", "", "", "", "created_at", "desc", 10, 0)
		reportData.Polls = searchPolls("", "", "", "", "created_at", "desc", 10, 0)
		reportData.Appointments = searchAppointments("", "", "", "created_at", "desc", 10, 0)
		reportData.Addresses = searchAddresses("", "", "", "created_at", "desc", 10, 0)
		reportData.Teams = searchTeams("", "", "", "created_at", "desc", 10, 0)
		reportData.TotalUsers = countUsers("", "", "", "")
		reportData.TotalPolls = countPolls("", "", "", "")
		reportData.TotalAddresses = countAddresses("", "", "")
	}

	adminnav := role == 1
	volunteernav := role != 1

	utils.Render(w, "reports.html", map[string]interface{}{
		"Title":           "Reports & Analytics",
		"IsAuthenticated": true,
		"ShowAdminNav":    adminnav,
		"ShowVolunteerNav": volunteernav,
		"UserName":        username,
		"ActiveSection":   "reports",
		"ReportData":      reportData,
		"SearchType":      searchType,
		"SearchQuery":     searchQuery,
		"DateFrom":        dateFrom,
		"DateTo":          dateTo,
		"RoleFilter":      roleFilter,
		"StatusFilter":    statusFilter,
		"SortBy":          sortBy,
		"SortOrder":       sortOrder,
		"CurrentPage":     pageInt,
		"Limit":           limitInt,
	})
}

// searchUsers searches users with filters
func searchUsers(searchQuery, roleFilter, dateFrom, dateTo, sortBy, sortOrder string, limit, offset int) []models.User {
	var users []models.User
	
	query := `
		SELECT u.user_id, u.first_name, u.last_name, u.email, u.phone, u.role_id, u.created_at, u.updated_at, u.admin_code
		FROM users u
		LEFT JOIN role r ON u.role_id = r.role_id
		WHERE 1=1`
	
	var args []interface{}
	argCount := 0

	// Add search conditions
	if searchQuery != "" {
		argCount++
		query += fmt.Sprintf(` AND (LOWER(u.first_name) LIKE LOWER($%d) OR LOWER(u.last_name) LIKE LOWER($%d) OR LOWER(u.email) LIKE LOWER($%d))`, argCount, argCount, argCount)
		args = append(args, "%"+searchQuery+"%")
	}

	if roleFilter != "" {
		argCount++
		query += fmt.Sprintf(` AND u.role_id = $%d`, argCount)
		roleID, _ := strconv.Atoi(roleFilter)
		args = append(args, roleID)
	}

	if dateFrom != "" {
		argCount++
		query += fmt.Sprintf(` AND u.created_at >= $%d`, argCount)
		args = append(args, dateFrom)
	}

	if dateTo != "" {
		argCount++
		query += fmt.Sprintf(` AND u.created_at <= $%d`, argCount)
		args = append(args, dateTo+" 23:59:59")
	}

	// Add sorting
	validSortColumns := map[string]bool{"created_at": true, "first_name": true, "last_name": true, "email": true}
	if !validSortColumns[sortBy] {
		sortBy = "created_at"
	}
	if sortOrder != "asc" && sortOrder != "desc" {
		sortOrder = "desc"
	}
	query += fmt.Sprintf(` ORDER BY u.%s %s`, sortBy, strings.ToUpper(sortOrder))

	// Add pagination
	argCount++
	query += fmt.Sprintf(` LIMIT $%d`, argCount)
	args = append(args, limit)
	argCount++
	query += fmt.Sprintf(` OFFSET $%d`, argCount)
	args = append(args, offset)

	rows, err := models.DB.Query(query, args...)
	if err != nil {
		log.Println("Error searching users:", err)
		return users
	}
	defer rows.Close()

	for rows.Next() {
		var user models.User
		err := rows.Scan(&user.UserID, &user.FirstName, &user.LastName, &user.Email, &user.Phone, &user.RoleID, &user.CreatedAt, &user.UpdatedAt, &user.AdminCode)
		if err != nil {
			log.Println("Error scanning user:", err)
			continue
		}
		users = append(users, user)
	}

	return users
}

// searchPolls searches polls with filters
func searchPolls(searchQuery, statusFilter, dateFrom, dateTo, sortBy, sortOrder string, limit, offset int) []PollWithDetails {
	var polls []PollWithDetails
	
	query := `
		SELECT p.poll_id, p.user_id, COALESCE(u.first_name || ' ' || u.last_name, 'Unknown') as author_name,
			   p.address_id, COALESCE(a.address, 'No Address') as address,
			   p.poll_title, p.poll_description, p.is_active, p.amount_donated, p.created_at, p.updated_at
		FROM poll p
		LEFT JOIN users u ON p.user_id = u.user_id
		LEFT JOIN address_database a ON p.address_id = a.address_id
		WHERE 1=1`
	
	var args []interface{}
	argCount := 0

	if searchQuery != "" {
		argCount++
		query += fmt.Sprintf(` AND (LOWER(p.poll_title) LIKE LOWER($%d) OR LOWER(p.poll_description) LIKE LOWER($%d))`, argCount, argCount)
		args = append(args, "%"+searchQuery+"%")
	}

	if statusFilter == "active" {
		query += ` AND p.is_active = true`
	} else if statusFilter == "inactive" {
		query += ` AND p.is_active = false`
	}

	if dateFrom != "" {
		argCount++
		query += fmt.Sprintf(` AND p.created_at >= $%d`, argCount)
		args = append(args, dateFrom)
	}

	if dateTo != "" {
		argCount++
		query += fmt.Sprintf(` AND p.created_at <= $%d`, argCount)
		args = append(args, dateTo+" 23:59:59")
	}

	validSortColumns := map[string]bool{"created_at": true, "poll_title": true, "amount_donated": true, "is_active": true}
	if !validSortColumns[sortBy] {
		sortBy = "created_at"
	}
	if sortOrder != "asc" && sortOrder != "desc" {
		sortOrder = "desc"
	}
	query += fmt.Sprintf(` ORDER BY p.%s %s`, sortBy, strings.ToUpper(sortOrder))

	argCount++
	query += fmt.Sprintf(` LIMIT $%d`, argCount)
	args = append(args, limit)
	argCount++
	query += fmt.Sprintf(` OFFSET $%d`, argCount)
	args = append(args, offset)

	rows, err := models.DB.Query(query, args...)
	if err != nil {
		log.Println("Error searching polls:", err)
		return polls
	}
	defer rows.Close()

	for rows.Next() {
		var poll PollWithDetails
		err := rows.Scan(&poll.PollID, &poll.UserID, &poll.AuthorName, &poll.AddressID, &poll.Address,
			&poll.PollTitle, &poll.PollDescription, &poll.IsActive, &poll.AmountDonated, &poll.CreatedAt, &poll.UpdatedAt)
		if err != nil {
			log.Println("Error scanning poll:", err)
			continue
		}
		polls = append(polls, poll)
	}

	return polls
}

// searchAppointments searches appointments with filters
func searchAppointments(searchQuery, dateFrom, dateTo, sortBy, sortOrder string, limit, offset int) []AppointmentWithDetails {
	var appointments []AppointmentWithDetails
	
	query := `
		SELECT a.sched_id, a.user_id, COALESCE(u.first_name || ' ' || u.last_name, 'Unknown') as user_name,
			   a.address_id, COALESCE(ad.address, 'No Address') as address,
			   a.appointment_date, a.appointment_time, a.created_at
		FROM appointment a
		LEFT JOIN users u ON a.user_id = u.user_id
		LEFT JOIN address_database ad ON a.address_id = ad.address_id
		WHERE 1=1`
	
	var args []interface{}
	argCount := 0

	if searchQuery != "" {
		argCount++
		query += fmt.Sprintf(` AND (LOWER(u.first_name) LIKE LOWER($%d) OR LOWER(u.last_name) LIKE LOWER($%d) OR LOWER(ad.address) LIKE LOWER($%d))`, argCount, argCount, argCount)
		args = append(args, "%"+searchQuery+"%")
	}

	if dateFrom != "" {
		argCount++
		query += fmt.Sprintf(` AND a.appointment_date >= $%d`, argCount)
		args = append(args, dateFrom)
	}

	if dateTo != "" {
		argCount++
		query += fmt.Sprintf(` AND a.appointment_date <= $%d`, argCount)
		args = append(args, dateTo)
	}

	validSortColumns := map[string]bool{"created_at": true, "appointment_date": true, "appointment_time": true}
	if !validSortColumns[sortBy] {
		sortBy = "appointment_date"
	}
	if sortOrder != "asc" && sortOrder != "desc" {
		sortOrder = "desc"
	}
	query += fmt.Sprintf(` ORDER BY a.%s %s`, sortBy, strings.ToUpper(sortOrder))

	argCount++
	query += fmt.Sprintf(` LIMIT $%d`, argCount)
	args = append(args, limit)
	argCount++
	query += fmt.Sprintf(` OFFSET $%d`, argCount)
	args = append(args, offset)

	rows, err := models.DB.Query(query, args...)
	if err != nil {
		log.Println("Error searching appointments:", err)
		return appointments
	}
	defer rows.Close()

	for rows.Next() {
		var apt AppointmentWithDetails
		var appointmentTime sql.NullTime
		err := rows.Scan(&apt.SchedID, &apt.UserID, &apt.UserName, &apt.AddressID, &apt.Address,
			&apt.AppointmentDate, &appointmentTime, &apt.CreatedAt)
		if err != nil {
			log.Println("Error scanning appointment:", err)
			continue
		}
		if appointmentTime.Valid {
			apt.AppointmentTime = appointmentTime.Time
		}
		appointments = append(appointments, apt)
	}

	return appointments
}

// searchAddresses searches addresses with filters
func searchAddresses(searchQuery, dateFrom, dateTo, sortBy, sortOrder string, limit, offset int) []models.AddressDatabase {
	var addresses []models.AddressDatabase
	
	query := `
		SELECT address_id, address, street_name, street_type, street_quadrant, 
			   house_number, house_alpha, longitude, latitude, visited_validated, created_at, updated_at
		FROM address_database
		WHERE 1=1`
	
	var args []interface{}
	argCount := 0

	if searchQuery != "" {
		argCount++
		query += fmt.Sprintf(` AND (LOWER(address) LIKE LOWER($%d) OR LOWER(street_name) LIKE LOWER($%d) OR house_number LIKE $%d)`, argCount, argCount, argCount)
		args = append(args, "%"+searchQuery+"%")
	}

	if dateFrom != "" {
		argCount++
		query += fmt.Sprintf(` AND created_at >= $%d`, argCount)
		args = append(args, dateFrom)
	}

	if dateTo != "" {
		argCount++
		query += fmt.Sprintf(` AND created_at <= $%d`, argCount)
		args = append(args, dateTo+" 23:59:59")
	}

	validSortColumns := map[string]bool{"created_at": true, "address": true, "street_name": true, "visited_validated": true}
	if !validSortColumns[sortBy] {
		sortBy = "created_at"
	}
	if sortOrder != "asc" && sortOrder != "desc" {
		sortOrder = "desc"
	}
	query += fmt.Sprintf(` ORDER BY %s %s`, sortBy, strings.ToUpper(sortOrder))

	argCount++
	query += fmt.Sprintf(` LIMIT $%d`, argCount)
	args = append(args, limit)
	argCount++
	query += fmt.Sprintf(` OFFSET $%d`, argCount)
	args = append(args, offset)

	rows, err := models.DB.Query(query, args...)
	if err != nil {
		log.Println("Error searching addresses:", err)
		return addresses
	}
	defer rows.Close()

	for rows.Next() {
		var addr models.AddressDatabase
		err := rows.Scan(&addr.AddressID, &addr.Address, &addr.StreetName, &addr.StreetType, &addr.StreetQuadrant,
			&addr.HouseNumber, &addr.HouseAlpha, &addr.Longitude, &addr.Latitude, &addr.VisitedValidated, &addr.CreatedAt, &addr.UpdatedAt)
		if err != nil {
			log.Println("Error scanning address:", err)
			continue
		}
		addresses = append(addresses, addr)
	}

	return addresses
}

// searchTeams searches teams with filters
func searchTeams(searchQuery, dateFrom, dateTo, sortBy, sortOrder string, limit, offset int) []TeamWithDetails {
	var teams []TeamWithDetails
	
	query := `
		SELECT t.team_id, t.team_lead_id, 
			   COALESCE(lead.first_name || ' ' || lead.last_name, 'No Lead') as team_lead_name,
			   t.volunteer_id,
			   COALESCE(vol.first_name || ' ' || vol.last_name, 'No Volunteer') as volunteer_name,
			   t.created_at
		FROM team t
		LEFT JOIN users lead ON t.team_lead_id = lead.user_id
		LEFT JOIN users vol ON t.volunteer_id = vol.user_id
		WHERE 1=1`
	
	var args []interface{}
	argCount := 0

	if searchQuery != "" {
		argCount++
		query += fmt.Sprintf(` AND (LOWER(lead.first_name) LIKE LOWER($%d) OR LOWER(lead.last_name) LIKE LOWER($%d) OR LOWER(vol.first_name) LIKE LOWER($%d) OR LOWER(vol.last_name) LIKE LOWER($%d))`, argCount, argCount, argCount, argCount)
		args = append(args, "%"+searchQuery+"%")
	}

	if dateFrom != "" {
		argCount++
		query += fmt.Sprintf(` AND t.created_at >= $%d`, argCount)
		args = append(args, dateFrom)
	}

	if dateTo != "" {
		argCount++
		query += fmt.Sprintf(` AND t.created_at <= $%d`, argCount)
		args = append(args, dateTo+" 23:59:59")
	}

	validSortColumns := map[string]bool{"created_at": true, "team_id": true}
	if !validSortColumns[sortBy] {
		sortBy = "created_at"
	}
	if sortOrder != "asc" && sortOrder != "desc" {
		sortOrder = "desc"
	}
	query += fmt.Sprintf(` ORDER BY t.%s %s`, sortBy, strings.ToUpper(sortOrder))

	argCount++
	query += fmt.Sprintf(` LIMIT $%d`, argCount)
	args = append(args, limit)
	argCount++
	query += fmt.Sprintf(` OFFSET $%d`, argCount)
	args = append(args, offset)

	rows, err := models.DB.Query(query, args...)
	if err != nil {
		log.Println("Error searching teams:", err)
		return teams
	}
	defer rows.Close()

	for rows.Next() {
		var team TeamWithDetails
		err := rows.Scan(&team.TeamID, &team.TeamLeadID, &team.TeamLeadName, &team.VolunteerID, &team.VolunteerName, &team.CreatedAt)
		if err != nil {
			log.Println("Error scanning team:", err)
			continue
		}
		teams = append(teams, team)
	}

	return teams
}

// Helper functions for counting total records
func countUsers(searchQuery, roleFilter, dateFrom, dateTo string) int {
	query := `SELECT COUNT(*) FROM users u WHERE 1=1`
	var args []interface{}
	argCount := 0

	if searchQuery != "" {
		argCount++
		query += fmt.Sprintf(` AND (LOWER(u.first_name) LIKE LOWER($%d) OR LOWER(u.last_name) LIKE LOWER($%d) OR LOWER(u.email) LIKE LOWER($%d))`, argCount, argCount, argCount)
		args = append(args, "%"+searchQuery+"%")
	}

	if roleFilter != "" {
		argCount++
		query += fmt.Sprintf(` AND u.role_id = $%d`, argCount)
		roleID, _ := strconv.Atoi(roleFilter)
		args = append(args, roleID)
	}

	if dateFrom != "" {
		argCount++
		query += fmt.Sprintf(` AND u.created_at >= $%d`, argCount)
		args = append(args, dateFrom)
	}

	if dateTo != "" {
		argCount++
		query += fmt.Sprintf(` AND u.created_at <= $%d`, argCount)
		args = append(args, dateTo+" 23:59:59")
	}

	var count int
	err := models.DB.QueryRow(query, args...).Scan(&count)
	if err != nil {
		log.Println("Error counting users:", err)
		return 0
	}
	return count
}

func countPolls(searchQuery, statusFilter, dateFrom, dateTo string) int {
	query := `SELECT COUNT(*) FROM poll p WHERE 1=1`
	var args []interface{}
	argCount := 0

	if searchQuery != "" {
		argCount++
		query += fmt.Sprintf(` AND (LOWER(p.poll_title) LIKE LOWER($%d) OR LOWER(p.poll_description) LIKE LOWER($%d))`, argCount, argCount)
		args = append(args, "%"+searchQuery+"%")
	}

	if statusFilter == "active" {
		query += ` AND p.is_active = true`
	} else if statusFilter == "inactive" {
		query += ` AND p.is_active = false`
	}

	if dateFrom != "" {
		argCount++
		query += fmt.Sprintf(` AND p.created_at >= $%d`, argCount)
		args = append(args, dateFrom)
	}

	if dateTo != "" {
		argCount++
		query += fmt.Sprintf(` AND p.created_at <= $%d`, argCount)
		args = append(args, dateTo+" 23:59:59")
	}

	var count int
	err := models.DB.QueryRow(query, args...).Scan(&count)
	if err != nil {
		log.Println("Error counting polls:", err)
		return 0
	}
	return count
}

func countAddresses(searchQuery, dateFrom, dateTo string) int {
	query := `SELECT COUNT(*) FROM address_database WHERE 1=1`
	var args []interface{}
	argCount := 0

	if searchQuery != "" {
		argCount++
		query += fmt.Sprintf(` AND (LOWER(address) LIKE LOWER($%d) OR LOWER(street_name) LIKE LOWER($%d) OR house_number LIKE $%d)`, argCount, argCount, argCount)
		args = append(args, "%"+searchQuery+"%")
	}

	if dateFrom != "" {
		argCount++
		query += fmt.Sprintf(` AND created_at >= $%d`, argCount)
		args = append(args, dateFrom)
	}

	if dateTo != "" {
		argCount++
		query += fmt.Sprintf(` AND created_at <= $%d`, argCount)
		args = append(args, dateTo+" 23:59:59")
	}

	var count int
	err := models.DB.QueryRow(query, args...).Scan(&count)
	if err != nil {
		log.Println("Error counting addresses:", err)
		return 0
	}
	return count
}

// ExportReportHandler handles CSV export of filtered data
func ExportReportHandler(w http.ResponseWriter, r *http.Request) {
	role := r.Context().Value("user_role").(int)
	if role != 1 { // Admin only
		http.Error(w, "Unauthorized", http.StatusForbidden)
		return
	}

	searchType := r.URL.Query().Get("search_type")
	// Get all the same filter parameters
	searchQuery := r.URL.Query().Get("search_query")
	dateFrom := r.URL.Query().Get("date_from")
	dateTo := r.URL.Query().Get("date_to")
	roleFilter := r.URL.Query().Get("role_filter")
	statusFilter := r.URL.Query().Get("status_filter")

	w.Header().Set("Content-Type", "text/csv")
	w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s_report_%s.csv\"", searchType, time.Now().Format("2006-01-02")))

	switch searchType {
	case "users":
		users := searchUsers(searchQuery, roleFilter, dateFrom, dateTo, "created_at", "desc", 10000, 0) // Get all for export
		w.Write([]byte("User ID,First Name,Last Name,Email,Phone,Role ID,Admin Code,Created At\n"))
		for _, user := range users {
			line := fmt.Sprintf("%d,%s,%s,%s,%s,%d,%s,%s\n",
				user.UserID, user.FirstName, user.LastName, user.Email, user.Phone, user.RoleID, user.AdminCode, user.CreatedAt.Format("2006-01-02 15:04:05"))
			w.Write([]byte(line))
		}
	case "polls":
		polls := searchPolls(searchQuery, statusFilter, dateFrom, dateTo, "created_at", "desc", 10000, 0)
		w.Write([]byte("Poll ID,Author,Address,Title,Description,Active,Amount Donated,Created At\n"))
		for _, poll := range polls {
			line := fmt.Sprintf("%d,%s,%s,%s,%s,%t,%.2f,%s\n",
				poll.PollID, poll.AuthorName, poll.Address, poll.PollTitle, poll.PollDescription, poll.IsActive, poll.AmountDonated, poll.CreatedAt.Format("2006-01-02 15:04:05"))
			w.Write([]byte(line))
		}
	case "appointments":
		appointments := searchAppointments(searchQuery, dateFrom, dateTo, "appointment_date", "desc", 10000, 0)
		w.Write([]byte("Schedule ID,User,Address,Date,Time,Created At\n"))
		for _, apt := range appointments {
			timeStr := ""
			if !apt.AppointmentTime.IsZero() {
				timeStr = apt.AppointmentTime.Format("15:04:05")
			}
			line := fmt.Sprintf("%d,%s,%s,%s,%s,%s\n",
				apt.SchedID, apt.UserName, apt.Address, apt.AppointmentDate.Format("2006-01-02"), timeStr, apt.CreatedAt.Format("2006-01-02 15:04:05"))
			w.Write([]byte(line))
		}
	case "addresses":
		addresses := searchAddresses(searchQuery, dateFrom, dateTo, "created_at", "desc", 10000, 0)
		w.Write([]byte("Address ID,Address,Street Name,Street Type,Quadrant,House Number,Alpha,Longitude,Latitude,Visited,Created At\n"))
		for _, addr := range addresses {
			line := fmt.Sprintf("%d,%s,%s,%s,%s,%s,%s,%.6f,%.6f,%t,%s\n",
				addr.AddressID, addr.Address, addr.StreetName, addr.StreetType, addr.StreetQuadrant, addr.HouseNumber, addr.HouseAlpha, 
				addr.Longitude, addr.Latitude, addr.VisitedValidated, addr.CreatedAt.Format("2006-01-02 15:04:05"))
			w.Write([]byte(line))
		}
	case "teams":
		teams := searchTeams(searchQuery, dateFrom, dateTo, "created_at", "desc", 10000, 0)
		w.Write([]byte("Team ID,Team Lead,Volunteer,Created At\n"))
		for _, team := range teams {
			line := fmt.Sprintf("%d,%s,%s,%s\n",
				team.TeamID, team.TeamLeadName, team.VolunteerName, team.CreatedAt.Format("2006-01-02 15:04:05"))
			w.Write([]byte(line))
		}
	default:
		http.Error(w, "Invalid export type", http.StatusBadRequest)
		return
	}
}

// ReportStatsHandler provides JSON API for dashboard statistics
func ReportStatsHandler(w http.ResponseWriter, r *http.Request) {
	role := r.Context().Value("user_role").(int)
	if role != 1 { // Admin only
		http.Error(w, "Unauthorized", http.StatusForbidden)
		return
	}

	stats := make(map[string]interface{})

	// Get total counts
	var totalUsers, totalPolls, totalAddresses, totalAppointments, totalTeams int
	var activePolls, inactivePolls int
	var visitedAddresses, unvisitedAddresses int

	// Total users
	models.DB.QueryRow("SELECT COUNT(*) FROM users").Scan(&totalUsers)
	
	// Total and active/inactive polls
	models.DB.QueryRow("SELECT COUNT(*) FROM poll").Scan(&totalPolls)
	models.DB.QueryRow("SELECT COUNT(*) FROM poll WHERE is_active = true").Scan(&activePolls)
	models.DB.QueryRow("SELECT COUNT(*) FROM poll WHERE is_active = false").Scan(&inactivePolls)
	
	// Total and visited/unvisited addresses
	models.DB.QueryRow("SELECT COUNT(*) FROM address_database").Scan(&totalAddresses)
	models.DB.QueryRow("SELECT COUNT(*) FROM address_database WHERE visited_validated = true").Scan(&visitedAddresses)
	models.DB.QueryRow("SELECT COUNT(*) FROM address_database WHERE visited_validated = false").Scan(&unvisitedAddresses)
	
	// Total appointments and teams
	models.DB.QueryRow("SELECT COUNT(*) FROM appointment").Scan(&totalAppointments)
	models.DB.QueryRow("SELECT COUNT(*) FROM team").Scan(&totalTeams)

	// Recent activity (last 30 days)
	var recentUsers, recentPolls, recentAppointments int
	models.DB.QueryRow("SELECT COUNT(*) FROM users WHERE created_at >= NOW() - INTERVAL '30 days'").Scan(&recentUsers)
	models.DB.QueryRow("SELECT COUNT(*) FROM poll WHERE created_at >= NOW() - INTERVAL '30 days'").Scan(&recentPolls)
	models.DB.QueryRow("SELECT COUNT(*) FROM appointment WHERE created_at >= NOW() - INTERVAL '30 days'").Scan(&recentAppointments)

	// Total donations
	var totalDonations float64
	models.DB.QueryRow("SELECT COALESCE(SUM(amount_donated), 0) FROM poll").Scan(&totalDonations)

	stats["totals"] = map[string]int{
		"users":        totalUsers,
		"polls":        totalPolls,
		"addresses":    totalAddresses,
		"appointments": totalAppointments,
		"teams":        totalTeams,
	}

	stats["poll_breakdown"] = map[string]int{
		"active":   activePolls,
		"inactive": inactivePolls,
	}

	stats["address_breakdown"] = map[string]int{
		"visited":   visitedAddresses,
		"unvisited": unvisitedAddresses,
	}

	stats["recent_activity"] = map[string]int{
		"users":        recentUsers,
		"polls":        recentPolls,
		"appointments": recentAppointments,
	}

	stats["total_donations"] = totalDonations

	w.Header().Set("Content-Type", "application/json")
	// utils.WriteJSON(w, stats)
}

// Advanced search handler for complex queries
func AdvancedSearchHandler(w http.ResponseWriter, r *http.Request) {
	role := r.Context().Value("user_role").(int)
	if role != 1 { // Admin only
		http.Error(w, "Unauthorized", http.StatusForbidden)
		return
	}

	if r.Method != http.MethodPost {
		http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
		return
	}

	err := r.ParseForm()
	if err != nil {
		http.Error(w, "Invalid form data", http.StatusBadRequest)
		return
	}

	// Build complex query based on multiple criteria
	searchCriteria := map[string]string{
		"entity":          r.FormValue("entity"),      // users, polls, appointments, etc.
		"text_search":     r.FormValue("text_search"),
		"date_from":       r.FormValue("date_from"),
		"date_to":         r.FormValue("date_to"),
		"role_filter":     r.FormValue("role_filter"),
		"status_filter":   r.FormValue("status_filter"),
		"location_filter": r.FormValue("location_filter"), // address-based filtering
		"amount_min":      r.FormValue("amount_min"),       // for polls with donations
		"amount_max":      r.FormValue("amount_max"),
		"sort_by":         r.FormValue("sort_by"),
		"sort_order":      r.FormValue("sort_order"),
	}

	// Redirect with query parameters
	redirectURL := "/reports?"
	params := []string{}
	for key, value := range searchCriteria {
		if value != "" {
			params = append(params, fmt.Sprintf("%s=%s", key, value))
		}
	}
	redirectURL += strings.Join(params, "&")

	http.Redirect(w, r, redirectURL, http.StatusSeeOther)
}