package admin

import (
	"crussell/db"
	"crussell/internal/validators"
	"crussell/mw"
	"database/sql"
	"encoding/json"
	"errors"
	"log"
	"log/slog"
	"net/http"
	"strconv"
	"time"

	"github.com/go-chi/chi/v5"
	"github.com/jackc/pgx/v5"
)

// DiscountCampaign represents a discount campaign in the system
type DiscountCampaign struct {
	ID              string     `json:"id"`
	Name            string     `json:"name"`
	Description     *string    `json:"description,omitempty"`
	CampaignType    string     `json:"campaign_type"`
	DiscountPercent float64    `json:"discount_percent"`
	Scope           *string    `json:"scope,omitempty"`
	StartDate       *time.Time `json:"start_date,omitempty"`
	EndDate         *time.Time `json:"end_date,omitempty"`
	MilestoneType   *string    `json:"milestone_type,omitempty"`
	MilestoneValue  *int       `json:"milestone_value,omitempty"`
	MilestoneUnit   *string    `json:"milestone_unit,omitempty"`
	Status          string     `json:"status"`
	MaxRedemptions  *int       `json:"max_redemptions,omitempty"`
	TimesRedeemed   int        `json:"times_redeemed"`
	CreatedAt       time.Time  `json:"created_at"`
	UpdatedAt       time.Time  `json:"updated_at"`
	CreatedBy       *string    `json:"created_by,omitempty"`
}

// CreateCampaignRequest represents the request payload for creating a new campaign
type CreateCampaignRequest struct {
	Name            string  `json:"name" validate:"required,min=1,max=200"`
	Description     *string `json:"description,omitempty" validate:"omitempty,max=1000"`
	CampaignType    string  `json:"campaign_type"` // "time_based" or "milestone"
	DiscountPercent float64 `json:"discount_percent"`
	Scope           *string `json:"scope,omitempty"`
	StartDate       *string `json:"start_date,omitempty"` // ISO 8601
	EndDate         *string `json:"end_date,omitempty"`   // ISO 8601
	MilestoneType   *string `json:"milestone_type,omitempty"`
	MilestoneValue  *int    `json:"milestone_value,omitempty"`
	MilestoneUnit   *string `json:"milestone_unit,omitempty"`
	MaxRedemptions  *int    `json:"max_redemptions,omitempty"`
}

// UpdateCampaignRequest represents the request payload for updating a campaign
type UpdateCampaignRequest struct {
	Name            *string  `json:"name,omitempty" validate:"omitempty,min=1,max=200"`
	Description     *string  `json:"description,omitempty" validate:"omitempty,max=1000"`
	DiscountPercent *float64 `json:"discount_percent,omitempty"`
	Scope           *string  `json:"scope,omitempty"`
	StartDate       *string  `json:"start_date,omitempty"`
	EndDate         *string  `json:"end_date,omitempty"`
	MilestoneType   *string  `json:"milestone_type,omitempty"`
	MilestoneValue  *int     `json:"milestone_value,omitempty"`
	MilestoneUnit   *string  `json:"milestone_unit,omitempty"`
	Status          *string  `json:"status,omitempty"`
	MaxRedemptions  *int     `json:"max_redemptions,omitempty"`
}

// CampaignStats represents statistics for a campaign
type CampaignStats struct {
	Campaign       DiscountCampaign `json:"campaign"`
	TotalDiscounts float64          `json:"total_discount_amount"`
	BookingCount   int              `json:"booking_count"`
}

// GetDiscountCampaigns handles GET /api/admin/discount-campaigns
// Optional query param ?status=active to filter by status
func GetDiscountCampaigns(w http.ResponseWriter, r *http.Request) {
	statusFilter := r.URL.Query().Get("status")
	if statusFilter != "" {
		validStatuses := map[string]bool{"draft": true, "active": true, "completed": true, "cancelled": true}
		if !validStatuses[statusFilter] {
			http.Error(w, "invalid status filter", http.StatusBadRequest)
			return
		}
	}

	var query string
	var rows pgx.Rows
	var err error

	if statusFilter != "" {
		query = `
			SELECT id, name, description, campaign_type, discount_percent, scope,
			       start_date, end_date, milestone_type, milestone_value, milestone_unit,
			       status, max_redemptions, times_redeemed, created_at, updated_at, created_by
			FROM discount_campaigns
			WHERE status = $1
			ORDER BY created_at DESC
		`
		rows, err = db.Conn.Query(r.Context(), query, statusFilter)
	} else {
		query = `
			SELECT id, name, description, campaign_type, discount_percent, scope,
			       start_date, end_date, milestone_type, milestone_value, milestone_unit,
			       status, max_redemptions, times_redeemed, created_at, updated_at, created_by
			FROM discount_campaigns
			ORDER BY created_at DESC
		`
		rows, err = db.Conn.Query(r.Context(), query)
	}

	if err != nil {
		http.Error(w, "Failed to fetch campaigns: "+err.Error(), http.StatusInternalServerError)
		return
	}
	defer rows.Close()

	var campaigns []DiscountCampaign

	for rows.Next() {
		var campaign DiscountCampaign
		var description, scope, campaignType, status, milestoneType, milestoneUnit sql.NullString
		var startDate, endDate sql.NullTime
		var milestoneValue, maxRedemptions sql.NullInt32
		var createdBy sql.NullString

		err := rows.Scan(
			&campaign.ID,
			&campaign.Name,
			&description,
			&campaignType,
			&campaign.DiscountPercent,
			&scope,
			&startDate,
			&endDate,
			&milestoneType,
			&milestoneValue,
			&milestoneUnit,
			&status,
			&maxRedemptions,
			&campaign.TimesRedeemed,
			&campaign.CreatedAt,
			&campaign.UpdatedAt,
			&createdBy,
		)
		if err != nil {
			http.Error(w, "Failed to read campaign data: "+err.Error(), http.StatusInternalServerError)
			return
		}

		// Convert nullable fields
		if description.Valid {
			campaign.Description = &description.String
		}
		if campaignType.Valid {
			campaign.CampaignType = campaignType.String
		}
		if scope.Valid {
			campaign.Scope = &scope.String
		}
		if startDate.Valid {
			campaign.StartDate = &startDate.Time
		}
		if endDate.Valid {
			campaign.EndDate = &endDate.Time
		}
		if milestoneType.Valid {
			campaign.MilestoneType = &milestoneType.String
		}
		if milestoneValue.Valid {
			val := int(milestoneValue.Int32)
			campaign.MilestoneValue = &val
		}
		if milestoneUnit.Valid {
			campaign.MilestoneUnit = &milestoneUnit.String
		}
		if status.Valid {
			campaign.Status = status.String
		}
		if maxRedemptions.Valid {
			val := int(maxRedemptions.Int32)
			campaign.MaxRedemptions = &val
		}
		if createdBy.Valid {
			campaign.CreatedBy = &createdBy.String
		}

		campaigns = append(campaigns, campaign)
	}

	if err = rows.Err(); err != nil {
		http.Error(w, "Error iterating over campaigns: "+err.Error(), http.StatusInternalServerError)
		return
	}

	w.WriteHeader(http.StatusOK)

	if campaigns == nil {
		campaigns = []DiscountCampaign{}
	}

	if err := json.NewEncoder(w).Encode(campaigns); err != nil {
		log.Printf("Error encoding campaigns: %v", err)
	}
}

// CreateDiscountCampaign handles POST /api/admin/discount-campaigns
func CreateDiscountCampaign(w http.ResponseWriter, r *http.Request) {
	var req CreateCampaignRequest
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		http.Error(w, "Invalid JSON: "+err.Error(), http.StatusBadRequest)
		return
	}

	if err := validators.Validate.Struct(&req); err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	// Validate required fields
	if req.Name == "" {
		http.Error(w, "Name is required", http.StatusBadRequest)
		return
	}
	if req.DiscountPercent <= 0 || req.DiscountPercent > 100 {
		http.Error(w, "Discount percent must be greater than 0 and less than or equal to 100", http.StatusBadRequest)
		return
	}
	if req.CampaignType != "time_based" && req.CampaignType != "milestone" {
		http.Error(w, "Campaign type must be 'time_based' or 'milestone'", http.StatusBadRequest)
		return
	}

	// Validate time_based requirements
	if req.CampaignType == "time_based" {
		if req.StartDate == nil || req.EndDate == nil {
			http.Error(w, "Start date and end date are required for time_based campaigns", http.StatusBadRequest)
			return
		}

		startTime, err := time.Parse(time.RFC3339, *req.StartDate)
		if err != nil {
			http.Error(w, "Invalid start date format. Use ISO 8601 format", http.StatusBadRequest)
			return
		}
		endTime, err := time.Parse(time.RFC3339, *req.EndDate)
		if err != nil {
			http.Error(w, "Invalid end date format. Use ISO 8601 format", http.StatusBadRequest)
			return
		}
		if !endTime.After(startTime) {
			http.Error(w, "End date must be after start date", http.StatusBadRequest)
			return
		}
	}

	// Validate milestone requirements
	if req.CampaignType == "milestone" {
		if req.MilestoneType == nil || req.MilestoneValue == nil || req.MilestoneUnit == nil {
			http.Error(w, "Milestone type, value, and unit are required for milestone campaigns", http.StatusBadRequest)
			return
		}
		if *req.MilestoneValue <= 0 {
			http.Error(w, "Milestone value must be greater than 0", http.StatusBadRequest)
			return
		}
	}

	// Get creator ID from context
	var createdBy *string
	if userID, ok := r.Context().Value(mw.UserIDKey).(string); ok {
		createdBy = &userID
	}

	tx, err := db.Conn.Begin(r.Context())
	if err != nil {
		http.Error(w, "Internal server error", http.StatusInternalServerError)
		return
	}
	defer func() {
    if err := tx.Rollback(r.Context()); err != nil {
        slog.Error("failed to rollback transaction", "err", err)
    }
}()

	// Insert new campaign
	query := `
		INSERT INTO discount_campaigns (
			name, description, campaign_type, discount_percent, scope,
			start_date, end_date, milestone_type, milestone_value, milestone_unit,
			max_redemptions, status, created_by
		)
		VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13)
		RETURNING
			id, name, description, campaign_type, discount_percent, scope,
			start_date, end_date, milestone_type, milestone_value, milestone_unit,
			status, max_redemptions, times_redeemed, created_at, updated_at, created_by
	`

	var campaign DiscountCampaign
	var description, scope, campaignType, status, milestoneType, milestoneUnit sql.NullString
	var startDate, endDate sql.NullTime
	var milestoneValue, maxRedemptions sql.NullInt32
	var createdByDB sql.NullString

	err = tx.QueryRow(r.Context(),
		query,
		req.Name,
		req.Description,
		req.CampaignType,
		req.DiscountPercent,
		req.Scope,
		req.StartDate,
		req.EndDate,
		req.MilestoneType,
		req.MilestoneValue,
		req.MilestoneUnit,
		req.MaxRedemptions,
		"draft",
		createdBy,
	).Scan(
		&campaign.ID,
		&campaign.Name,
		&description,
		&campaignType,
		&campaign.DiscountPercent,
		&scope,
		&startDate,
		&endDate,
		&milestoneType,
		&milestoneValue,
		&milestoneUnit,
		&status,
		&maxRedemptions,
		&campaign.TimesRedeemed,
		&campaign.CreatedAt,
		&campaign.UpdatedAt,
		&createdByDB,
	)

	if err != nil {
		http.Error(w, "Failed to create campaign: "+err.Error(), http.StatusInternalServerError)
		return
	}

	if err := tx.Commit(r.Context()); err != nil {
		http.Error(w, "Internal server error", http.StatusInternalServerError)
		return
	}

	// Convert nullable fields
	if description.Valid {
		campaign.Description = &description.String
	}
	if campaignType.Valid {
		campaign.CampaignType = campaignType.String
	}
	if scope.Valid {
		campaign.Scope = &scope.String
	}
	if startDate.Valid {
		campaign.StartDate = &startDate.Time
	}
	if endDate.Valid {
		campaign.EndDate = &endDate.Time
	}
	if milestoneType.Valid {
		campaign.MilestoneType = &milestoneType.String
	}
	if milestoneValue.Valid {
		val := int(milestoneValue.Int32)
		campaign.MilestoneValue = &val
	}
	if milestoneUnit.Valid {
		campaign.MilestoneUnit = &milestoneUnit.String
	}
	if status.Valid {
		campaign.Status = status.String
	}
	if maxRedemptions.Valid {
		val := int(maxRedemptions.Int32)
		campaign.MaxRedemptions = &val
	}
	if createdByDB.Valid {
		campaign.CreatedBy = &createdByDB.String
	}

	w.WriteHeader(http.StatusCreated)
	if err := json.NewEncoder(w).Encode(campaign); err != nil {
		log.Printf("Error encoding campaign: %v", err)
	}
}

// UpdateDiscountCampaign handles PUT /api/admin/discount-campaigns/{id}
func UpdateDiscountCampaign(w http.ResponseWriter, r *http.Request) {
	campaignID := chi.URLParam(r, "id")
	if campaignID == "" || !validators.IsValidID(campaignID) {
		http.Error(w, "Campaign not found", http.StatusNotFound)
		return
	}

	// Check if campaign exists
	var exists bool
	err := db.Conn.QueryRow(r.Context(), "SELECT EXISTS(SELECT 1 FROM discount_campaigns WHERE id = $1)", campaignID).Scan(&exists)
	if err != nil {
		http.Error(w, "Failed to check campaign: "+err.Error(), http.StatusInternalServerError)
		return
	}
	if !exists {
		http.Error(w, "Campaign not found", http.StatusNotFound)
		return
	}

	var req UpdateCampaignRequest
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		http.Error(w, "Invalid JSON: "+err.Error(), http.StatusBadRequest)
		return
	}

	if err := validators.Validate.Struct(&req); err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	// Build dynamic update query
	query := "UPDATE discount_campaigns SET updated_at = NOW()"
	args := []any{}
	argNum := 1

	if req.Name != nil {
		query += ", name = $" + strconv.Itoa(argNum)
		args = append(args, *req.Name)
		argNum++
	}
	if req.Description != nil {
		query += ", description = $" + strconv.Itoa(argNum)
		args = append(args, *req.Description)
		argNum++
	}
	if req.DiscountPercent != nil {
		if *req.DiscountPercent <= 0 || *req.DiscountPercent > 100 {
			http.Error(w, "Discount percent must be greater than 0 and less than or equal to 100", http.StatusBadRequest)
			return
		}
		query += ", discount_percent = $" + strconv.Itoa(argNum)
		args = append(args, *req.DiscountPercent)
		argNum++
	}
	if req.Scope != nil {
		query += ", scope = $" + strconv.Itoa(argNum)
		args = append(args, *req.Scope)
		argNum++
	}
	if req.StartDate != nil {
		startTime, err := time.Parse(time.RFC3339, *req.StartDate)
		if err != nil {
			http.Error(w, "Invalid start date format. Use ISO 8601 format", http.StatusBadRequest)
			return
		}
		query += ", start_date = $" + strconv.Itoa(argNum)
		args = append(args, startTime)
		argNum++
	}
	if req.EndDate != nil {
		endTime, err := time.Parse(time.RFC3339, *req.EndDate)
		if err != nil {
			http.Error(w, "Invalid end date format. Use ISO 8601 format", http.StatusBadRequest)
			return
		}
		query += ", end_date = $" + strconv.Itoa(argNum)
		args = append(args, endTime)
		argNum++
	}
	if req.MilestoneType != nil {
		query += ", milestone_type = $" + strconv.Itoa(argNum)
		args = append(args, *req.MilestoneType)
		argNum++
	}
	if req.MilestoneValue != nil {
		if *req.MilestoneValue <= 0 {
			http.Error(w, "Milestone value must be greater than 0", http.StatusBadRequest)
			return
		}
		query += ", milestone_value = $" + strconv.Itoa(argNum)
		args = append(args, *req.MilestoneValue)
		argNum++
	}
	if req.MilestoneUnit != nil {
		query += ", milestone_unit = $" + strconv.Itoa(argNum)
		args = append(args, *req.MilestoneUnit)
		argNum++
	}
	if req.Status != nil {
		if *req.Status != "draft" && *req.Status != "active" && *req.Status != "cancelled" && *req.Status != "completed" {
			http.Error(w, "Status must be 'draft', 'active', 'cancelled', or 'completed'", http.StatusBadRequest)
			return
		}
		query += ", status = $" + strconv.Itoa(argNum)
		args = append(args, *req.Status)
		argNum++
	}
	if req.MaxRedemptions != nil {
		query += ", max_redemptions = $" + strconv.Itoa(argNum)
		args = append(args, *req.MaxRedemptions)
		argNum++
	}

	query += " WHERE id = $" + strconv.Itoa(argNum)
	args = append(args, campaignID)

	tx, err := db.Conn.Begin(r.Context())
	if err != nil {
		log.Printf("Failed to begin transaction: %v", err)
		http.Error(w, "Internal server error", http.StatusInternalServerError)
		return
	}
	defer func() {
    if err := tx.Rollback(r.Context()); err != nil {
        slog.Error("failed to rollback transaction", "err", err)
    }
}()

	_, err = tx.Exec(r.Context(), query, args...)
	if err != nil {
		http.Error(w, "Failed to update campaign: "+err.Error(), http.StatusInternalServerError)
		return
	}

	if err := tx.Commit(r.Context()); err != nil {
		log.Printf("Failed to commit transaction: %v", err)
		http.Error(w, "Internal server error", http.StatusInternalServerError)
		return
	}

	// Fetch updated campaign
	var campaign DiscountCampaign
	var description, scope, campaignType, status, milestoneType, milestoneUnit sql.NullString
	var startDate, endDate sql.NullTime
	var milestoneValue, maxRedemptions sql.NullInt32
	var createdBy sql.NullString

	err = db.Conn.QueryRow(r.Context(), `
		SELECT id, name, description, campaign_type, discount_percent, scope,
		       start_date, end_date, milestone_type, milestone_value, milestone_unit,
		       status, max_redemptions, times_redeemed, created_at, updated_at, created_by
		FROM discount_campaigns
		WHERE id = $1
	`, campaignID).Scan(
		&campaign.ID,
		&campaign.Name,
		&description,
		&campaignType,
		&campaign.DiscountPercent,
		&scope,
		&startDate,
		&endDate,
		&milestoneType,
		&milestoneValue,
		&milestoneUnit,
		&status,
		&maxRedemptions,
		&campaign.TimesRedeemed,
		&campaign.CreatedAt,
		&campaign.UpdatedAt,
		&createdBy,
	)

	if err != nil {
		http.Error(w, "Failed to fetch updated campaign: "+err.Error(), http.StatusInternalServerError)
		return
	}

	// Convert nullable fields
	if description.Valid {
		campaign.Description = &description.String
	}
	if campaignType.Valid {
		campaign.CampaignType = campaignType.String
	}
	if scope.Valid {
		campaign.Scope = &scope.String
	}
	if startDate.Valid {
		campaign.StartDate = &startDate.Time
	}
	if endDate.Valid {
		campaign.EndDate = &endDate.Time
	}
	if milestoneType.Valid {
		campaign.MilestoneType = &milestoneType.String
	}
	if milestoneValue.Valid {
		val := int(milestoneValue.Int32)
		campaign.MilestoneValue = &val
	}
	if milestoneUnit.Valid {
		campaign.MilestoneUnit = &milestoneUnit.String
	}
	if status.Valid {
		campaign.Status = status.String
	}
	if maxRedemptions.Valid {
		val := int(maxRedemptions.Int32)
		campaign.MaxRedemptions = &val
	}
	if createdBy.Valid {
		campaign.CreatedBy = &createdBy.String
	}

	w.WriteHeader(http.StatusOK)
	if err := json.NewEncoder(w).Encode(campaign); err != nil {
		log.Printf("Error encoding campaign: %v", err)
	}
}

// DeleteDiscountCampaign handles DELETE /api/admin/discount-campaigns/{id}
// Soft delete - sets status to "cancelled"
func DeleteDiscountCampaign(w http.ResponseWriter, r *http.Request) {
	campaignID := chi.URLParam(r, "id")
	if campaignID == "" || !validators.IsValidID(campaignID) {
		http.Error(w, "Campaign not found", http.StatusNotFound)
		return
	}

	// Check if campaign exists
	var exists bool
	err := db.Conn.QueryRow(r.Context(), "SELECT EXISTS(SELECT 1 FROM discount_campaigns WHERE id = $1)", campaignID).Scan(&exists)
	if err != nil {
		http.Error(w, "Failed to check campaign: "+err.Error(), http.StatusInternalServerError)
		return
	}
	if !exists {
		http.Error(w, "Campaign not found", http.StatusNotFound)
		return
	}

	// Soft delete - set status to cancelled
	query := "UPDATE discount_campaigns SET status = 'cancelled', updated_at = NOW() WHERE id = $1"
	tx, err := db.Conn.Begin(r.Context())
	if err != nil {
		log.Printf("Failed to begin transaction: %v", err)
		http.Error(w, "Internal server error", http.StatusInternalServerError)
		return
	}
	defer func() {
    if err := tx.Rollback(r.Context()); err != nil {
        slog.Error("failed to rollback transaction", "err", err)
    }
}()

	result, err := tx.Exec(r.Context(), query, campaignID)
	if err != nil {
		http.Error(w, "Failed to delete campaign: "+err.Error(), http.StatusInternalServerError)
		return
	}

	if result.RowsAffected() == 0 {
		http.Error(w, "Campaign not found", http.StatusNotFound)
		return
	}

	if err := tx.Commit(r.Context()); err != nil {
		log.Printf("Failed to commit transaction: %v", err)
		http.Error(w, "Internal server error", http.StatusInternalServerError)
		return
	}

	w.WriteHeader(http.StatusOK)
	_ = json.NewEncoder(w).Encode(map[string]any{
		"message": "Campaign deleted successfully",
		"id":      campaignID,
	})
}

// GetCampaignStats handles GET /api/admin/discount-campaigns/{id}/stats
func GetCampaignStats(w http.ResponseWriter, r *http.Request) {
	campaignID := chi.URLParam(r, "id")
	if campaignID == "" || !validators.IsValidID(campaignID) {
		http.Error(w, "Campaign not found", http.StatusNotFound)
		return
	}

	// Fetch campaign details
	var campaign DiscountCampaign
	var description, scope, campaignType, status, milestoneType, milestoneUnit sql.NullString
	var startDate, endDate sql.NullTime
	var milestoneValue, maxRedemptions sql.NullInt32
	var createdBy sql.NullString

	err := db.Conn.QueryRow(r.Context(), `
		SELECT id, name, description, campaign_type, discount_percent, scope,
		       start_date, end_date, milestone_type, milestone_value, milestone_unit,
		       status, max_redemptions, times_redeemed, created_at, updated_at, created_by
		FROM discount_campaigns
		WHERE id = $1
	`, campaignID).Scan(
		&campaign.ID,
		&campaign.Name,
		&description,
		&campaignType,
		&campaign.DiscountPercent,
		&scope,
		&startDate,
		&endDate,
		&milestoneType,
		&milestoneValue,
		&milestoneUnit,
		&status,
		&maxRedemptions,
		&campaign.TimesRedeemed,
		&campaign.CreatedAt,
		&campaign.UpdatedAt,
		&createdBy,
	)

	if errors.Is(err, pgx.ErrNoRows) {
		http.Error(w, "Campaign not found", http.StatusNotFound)
		return
	}
	if err != nil {
		http.Error(w, "Failed to fetch campaign: "+err.Error(), http.StatusInternalServerError)
		return
	}

	// Convert nullable fields
	if description.Valid {
		campaign.Description = &description.String
	}
	if campaignType.Valid {
		campaign.CampaignType = campaignType.String
	}
	if scope.Valid {
		campaign.Scope = &scope.String
	}
	if startDate.Valid {
		campaign.StartDate = &startDate.Time
	}
	if endDate.Valid {
		campaign.EndDate = &endDate.Time
	}
	if milestoneType.Valid {
		campaign.MilestoneType = &milestoneType.String
	}
	if milestoneValue.Valid {
		val := int(milestoneValue.Int32)
		campaign.MilestoneValue = &val
	}
	if milestoneUnit.Valid {
		campaign.MilestoneUnit = &milestoneUnit.String
	}
	if status.Valid {
		campaign.Status = status.String
	}
	if maxRedemptions.Valid {
		val := int(maxRedemptions.Int32)
		campaign.MaxRedemptions = &val
	}
	if createdBy.Valid {
		campaign.CreatedBy = &createdBy.String
	}

	// Get stats from booking_discounts table
	var totalDiscounts float64
	var bookingCount int

	err = db.Conn.QueryRow(r.Context(), `
		SELECT COALESCE(SUM(discount_amount), 0), COUNT(*)
		FROM booking_discounts
		WHERE source_id = $1
	`, campaignID).Scan(&totalDiscounts, &bookingCount)

	if err != nil {
		http.Error(w, "Failed to fetch campaign stats: "+err.Error(), http.StatusInternalServerError)
		return
	}

	stats := CampaignStats{
		Campaign:       campaign,
		TotalDiscounts: totalDiscounts,
		BookingCount:   bookingCount,
	}

	w.WriteHeader(http.StatusOK)
	if err := json.NewEncoder(w).Encode(stats); err != nil {
		log.Printf("Error encoding stats: %v", err)
	}
}
