package domain

import (
	"errors"
	"nearle/db"
	"nearle/models"
	"nearle/utils"
	"strconv"
	"strings"
	"time"

	"gorm.io/gorm"
	"gorm.io/gorm/clause"
)

func GetProductCategory() []models.ProductCategory {
	var data []models.ProductCategory

	q1 := `SELECT * FROM productcategories WHERE moduleid = 2 and status = "Active"`
	db.DB.Raw(q1).Scan(&data)

	return data
}

func GetProductSubCategory(categoryID, tenantID int) []models.ProductSubCategory {
	var data []models.ProductSubCategory
	var query strings.Builder
	var args []interface{}

	query.WriteString("SELECT * FROM productsubcategories WHERE 1=1")

	if tenantID != 0 {
		query.WriteString(" AND tenantid = ?")
		args = append(args, tenantID)
	}
	if categoryID != 0 {
		query.WriteString(" AND categoryid = ?")
		args = append(args, categoryID)
	}

	db.DB.Raw(query.String(), args...).Scan(&data)
	return data
}

func CreateProduct(product *models.Products) error {

	tx := db.DB.Begin()

	t1 := tx.Create(&product)
	if t1.Error != nil {
		utils.Error("CreateProduct error", "error", t1.Error)
		tx.Rollback()
		return t1.Error
	}

	err := tx.Commit().Error
	if err != nil {

		return err

	}

	return nil

}

func CreateProductVariant(input models.Productvariant) error {

	tx := db.DB.Begin()

	t1 := tx.Create(&input)
	if t1.Error != nil {
		utils.Error("CreateProductVariant error", "error", t1.Error)
		tx.Rollback()
		return t1.Error
	}

	err := tx.Commit().Error
	if err != nil {

		return err

	}

	return nil

}

func FetchFilteredProducts(categoryID, subcategoryID, productID, applocationID, tenantID, locationID int, keyword, productStatus, approve string, pageno, pagesize int) ([]models.Tenantproducts, error) {
	offset := (pageno - 1) * pagesize
	results := make([]models.Tenantproducts, 0)

	if tenantID == 0 {
		return results, nil
	}

	var tenant models.TenantInfo
	err := db.DB.Table("tenants").Where("tenantid = ?", tenantID).First(&tenant).Error
	if err != nil {
		return nil, err
	}

	var products []models.Products
	query := db.DB.
		Debug().
		Table("products a").
		Select(`
			a.*, 
			c.categoryname, 
			d.subcatname AS subcategoryname,
			e.locationid,
			COALESCE(
				SUM(CASE WHEN e.stocktype = 'in'  THEN e.quantity ELSE 0 END) -
				SUM(CASE WHEN e.stocktype = 'out' THEN e.quantity ELSE 0 END),
				0
			) AS quantity
		`).
		Joins("LEFT JOIN productcategories c ON a.categoryid = c.categoryid").
		Joins("LEFT JOIN productsubcategories d ON a.subcategoryid = d.subcatid").
		Joins("LEFT JOIN productstocks e ON e.productid = a.productid").
		Where("a.tenantid = ?", tenantID).
		Group("a.productid"). // Important for SUM
		Order("a.productid DESC")

	if categoryID != 0 {
		query = query.Where("a.categoryid = ?", categoryID)
	}
	if subcategoryID != 0 {
		query = query.Where("a.subcategoryid = ?", subcategoryID)
	}
	if productID != 0 {
		query = query.Where("a.productid = ?", productID)
	}
	if productStatus != "" {
		query = query.Where("a.productstatus = ?", productStatus)
	}
	if locationID != 0 {
		query = query.Where("e.locationid = ?", locationID)
	}
	if approve != "" {
		query = query.Where("a.approve = ?", approve)
	}

	if keyword != "" {
		like := "%" + strings.ToLower(keyword) + "%"
		query = query.Where(
			db.DB.Where("LOWER(a.productname) LIKE ?", like).
				Or("LOWER(a.unitvalue) LIKE ?", like).
				Or("LOWER(CAST(a.productcost AS CHAR)) LIKE ?", like),
		)
	}

	if pagesize > 0 && offset >= 0 {
		query = query.Limit(pagesize).Offset(offset)
	}

	err = query.Scan(&products).Error
	if err != nil {
		return nil, err
	}

	if products == nil {
		products = []models.Products{}
	}

	results = append(results, models.Tenantproducts{
		Tenant:   tenant,
		Products: products,
	})

	return results, nil
}

func UpdateProduct(input models.Products) error {

	tx := db.DB.Begin()

	t1 := tx.Where("productid=?", input.Productid).Updates(&input)
	if t1.Error != nil {

		tx.Rollback()
		return t1.Error
	}

	err := tx.Commit().Error
	if err != nil {

		return err

	}

	return nil

}

func Getproductcount(tenantid, categoryid, subcategory int, approve string) ([]models.Productcount, error) {
	var data []models.Productcount

	baseQuery := `
		SELECT 
			COUNT(*) AS total,
			SUM(CASE WHEN a.productstatus = 'available' THEN 1 ELSE 0 END) AS available,
			SUM(CASE WHEN a.productstatus = 'outofstock' THEN 1 ELSE 0 END) AS outofstock
		FROM products a
		WHERE 1 = 1
	`

	var conditions []string
	var params []interface{}

	if tenantid != 0 {
		conditions = append(conditions, "a.tenantid = ?")
		params = append(params, tenantid)
	}
	if categoryid != 0 {
		conditions = append(conditions, "a.categoryid = ?")
		params = append(params, categoryid)
	}
	if subcategory != 0 {
		conditions = append(conditions, "a.subcategoryid = ?")
		params = append(params, subcategory)
	}
	if approve != "" {
		conditions = append(conditions, "a.approve = ?")
		params = append(params, approve)
	}

	if len(conditions) > 0 {
		baseQuery += " AND " + strings.Join(conditions, " AND ")
	}

	if err := db.DB.Raw(baseQuery, params...).Scan(&data).Error; err != nil {
		return nil, err
	}


	return data, nil
}

func GetproductbyVariant(tenantid, variantid int) ([]models.Products, error) {

	var data []models.Products

	err := db.DB.
		Table("products p").
		Select("p.*, c.categoryname, d.subcatname as subcategoryname").
		Joins("LEFT JOIN productcategories c ON p.categoryid = c.categoryid").
		Joins("LEFT JOIN productsubcategories d ON p.subcategoryid = d.subcatid").
		Where("p.tenantid = ? and p.variants = ?", tenantid, variantid).
		Order("p.productid desc").Scan(&data).Error


	if err != nil {
		return nil, err
	}

	return data, nil

}

func GetProductVariants(tenantId int, subcategoryId int) []models.Productvariant {
	var data []models.Productvariant

	var query string
	var params []interface{}

	query = `
		SELECT a.*, b.categoryname
		FROM productvariants a
		JOIN app_category b ON a.categoryid = b.categoryid
		WHERE a.tenantid = ?
	`
	params = append(params, tenantId)

	if subcategoryId != 0 {
		query += " AND a.subcategoryid = ?"
		params = append(params, subcategoryId)
	}

	db.DB.Raw(query, params...).Scan(&data)


	return data
}

func GetCatalougeProducts(tenantId, locationid, subcategoryid, pageno, pagesize int, keyword string) []models.Products {
	var data []models.Products

	var query string

	if pageno < 1 {
		pageno = 1
	}
	if pagesize < 1 {
		pagesize = 10
	}

	offset := (pageno - 1) * pagesize

	params := []interface{}{locationid, tenantId}

	query = `SELECT a.* FROM products a 
	         LEFT JOIN productlocations b ON a.productid = b.productid  
			 AND b.locationid =?  AND b.tenantid = a.tenantid  
			 WHERE a.approve=1 and a.tenantid = ? AND b.productid IS NULL order by a.productid desc LIMIT ` + strconv.Itoa(pagesize) + ` OFFSET ` + strconv.Itoa(offset)

	if subcategoryid != 0 {
		query += " AND a.subcategoryid = ?"
		params = append(params, subcategoryid)
	}

	if keyword != "" {
		query += " AND LOWER(a.productname) LIKE ?"
		params = append(params, "%"+strings.ToLower(keyword)+"%")
	}

	db.DB.Raw(query, params...).Scan(&data)

	utils.Logger.Debugf("Query: %s", query)

	return data
}

func GetLocationProducts(tenantid, locationid, subcategoryid, pageno, pagesize int, keyword string) []models.Products {
	var data []models.Products

	if pageno < 1 {
		pageno = 1
	}
	if pagesize < 1 {
		pagesize = 10
	}

	offset := (pageno - 1) * pagesize
	params := []interface{}{tenantid, locationid}

	query := `SELECT a.*,  
			  COALESCE(SUM(CASE WHEN UPPER(c.stocktype) = 'IN' THEN c.quantity ELSE 0 END), 0) AS total_in,
    		  COALESCE(SUM(CASE WHEN UPPER(c.stocktype) = 'OUT' THEN c.quantity ELSE 0 END), 0) AS total_out,
    		  COALESCE(SUM(CASE WHEN UPPER(c.stocktype) = 'IN' THEN c.quantity ELSE 0 END) - 
              SUM(CASE WHEN UPPER(c.stocktype) = 'OUT' THEN c.quantity ELSE 0 END), 0) AS productstock 
              FROM products a 
              INNER JOIN productlocations b 
                  ON a.productid = b.productid AND a.tenantid = b.tenantid
			  LEFT JOIN productstocks c 
				 ON a.productid = c.productid 
				 AND b.locationid = c.locationid
				 AND a.tenantid = c.tenantid  
              WHERE a.approve=1 AND a.tenantid = ? 
                AND b.locationid = ?`

	if subcategoryid != 0 {
		query += " AND a.subcategoryid = ?"
		params = append(params, subcategoryid)
	}

	if keyword != "" {
		query += " AND LOWER(a.productname) LIKE ?"
		params = append(params, "%"+strings.ToLower(keyword)+"%")
	}

	query += ` GROUP BY a.productid, a.productname, a.productimage, a.categoryid, a.subcategoryid,
			 a.productunit, a.productcost, a.taxpercent, a.taxamount, a.retailprice,
			 b.tenantid, b.locationid`

	query += " ORDER BY a.productid DESC LIMIT ? OFFSET ?"
	params = append(params, pagesize, offset)

	db.DB.Raw(query, params...).Scan(&data)


	return data
}

func GetStockStatement(tenantid, locationid, subcategoryid, pageno, pagesize int, keyword string) []models.Productstockstatement {
	data := make([]models.Productstockstatement, 0)

	if pageno < 1 {
		pageno = 1
	}
	if pagesize < 1 {
		pagesize = 10
	}

	offset := (pageno - 1) * pagesize

	params := []interface{}{tenantid, locationid}

	query := `SELECT a.productid,a.productname,a.productimage,a.categoryid,a.subcategoryid,a.productunit,a.unitvalue,a.productcost,a.taxpercent,a.taxamount,a.retailprice,b.tenantid,b.locationid,
     		 COALESCE( SUM(CASE WHEN UPPER(c.stocktype) = 'IN'  AND c.stockdate::date <= CURRENT_DATE THEN c.quantity ELSE 0 END) -
			           SUM(CASE WHEN UPPER(c.stocktype) = 'OUT' AND  c.stockdate::date <= CURRENT_DATE THEN c.quantity ELSE 0 END),0 )
			 AS opening,
    		 COALESCE(SUM(CASE WHEN UPPER(c.stocktype) = 'IN'  AND c.stockdate::date = CURRENT_DATE THEN c.quantity ELSE 0 END), 0) AS credit,
    		 COALESCE(SUM(CASE WHEN UPPER(c.stocktype) = 'OUT' AND  c.stockdate::date= CURRENT_DATE THEN c.quantity ELSE 0 END), 0) AS debit,
    		COALESCE(
        		( SUM(CASE WHEN UPPER(c.stocktype) = 'IN'  AND  c.stockdate::date < CURRENT_DATE THEN c.quantity ELSE 0 END) -
				  SUM(CASE WHEN UPPER(c.stocktype) = 'OUT' AND c.stockdate::date < CURRENT_DATE THEN c.quantity ELSE 0 END)
				) +
			SUM(CASE WHEN UPPER(c.stocktype) = 'IN'  AND c.stockdate::date = CURRENT_DATE THEN c.quantity ELSE 0 END) -
			SUM(CASE WHEN UPPER(c.stocktype) = 'OUT' AND  c.stockdate::date = CURRENT_DATE THEN c.quantity ELSE 0 END),
			0
			) AS closing
			FROM products a
			JOIN productlocations b  ON a.productid = b.productid AND a.tenantid = b.tenantid
			LEFT JOIN productstocks c ON a.productid = c.productid AND b.locationid = c.locationid AND b.tenantid = c.tenantid
			WHERE b.tenantid = ? AND b.locationid = ?`

	if subcategoryid != 0 {
		query += " AND a.subcategoryid = ?"
		params = append(params, subcategoryid)
	}

	if keyword != "" {
		query += " AND (CAST(a.productid AS CHAR) LIKE ? OR LOWER(a.productname) LIKE ?)"
		likeParam := "%" + strings.ToLower(keyword) + "%"
		params = append(params, likeParam, likeParam)
	}

	query += `
			GROUP BY
				a.productid, a.productname, a.productimage,
				a.categoryid, a.subcategoryid, a.productunit,
				a.productcost, a.taxpercent, a.taxamount,
				a.retailprice, b.tenantid, b.locationid
			ORDER BY a.productid DESC LIMIT ` + strconv.Itoa(pagesize) + ` OFFSET ` + strconv.Itoa(offset)

	db.DB.Raw(query, params...).Scan(&data)

	utils.Logger.Debugf("Query: %s", query)

	return data
}

func CreateProductLocation(input []models.Productlocations) error {

	var stk []models.Productstock

	tx := db.DB.Begin()

	if err := tx.Clauses(clause.OnConflict{
		Columns:   []clause.Column{{Name: "tenantid"}, {Name: "locationid"}, {Name: "productid"}},
		DoUpdates: clause.AssignmentColumns([]string{"price", "minquantity", "maxquantity"}),
	}).Create(&input).Error; err != nil {
		tx.Rollback()
		return err
	}

	for _, loc := range input {

		if loc.Quantity > 0 {
			stk = append(stk, models.Productstock{
				Tenantid:   loc.Tenantid,
				Stockdate:  time.Now(),
				Locationid: loc.Locationid,
				Productid:  loc.Productid,
				Quantity:   loc.Quantity,
				Stocktype:  loc.Stocktype,
			})

		}

	}

	if len(stk) > 0 {
		t2 := tx.Create(&stk)
		if t2.Error != nil {
			tx.Rollback()
			return t2.Error
		}
	}

	err := tx.Commit().Error
	if err != nil {

		return err

	}

	return nil

}

func UpdateProductLocation(input models.Productlocations) error {

	tx := db.DB.Begin()

	t1 := tx.Where("productlocationid=?", input.Productlocationid).Updates(&input)
	if t1.Error != nil {

		tx.Rollback()
		return t1.Error
	}

	err := tx.Commit().Error
	if err != nil {

		return err

	}

	return nil

}

func FetchProductsBySubcategory(categoryID, tenantID, applocationID, locationID, productID int, keyword string) (map[string]interface{}, error) {
	utils.Logger.Infof("Domain: Fetching products for categoryID=%d, tenantID=%d", categoryID, tenantID)

	// Step 1: Fetch subcategories
	var subcategories []models.Subcategory
	err := db.DB.Table("productsubcategories").
		Where("categoryid = ?", categoryID).
		Find(&subcategories).Error
	if err != nil {
		utils.Error("Error fetching subcategories", "error", err)
		return nil, err
	}

	// Step 2: Build product query
	var products []models.Products
	query := db.DB.Table("products a").
		Joins("LEFT JOIN productlocations pl ON pl.productid = a.productid").
		Where("a.categoryid = ? AND a.tenantid = ?", categoryID, tenantID)

	if locationID > 0 {
		query = query.Where("pl.locationid = ?", locationID)
	}
	if applocationID > 0 {
		query = query.Where("a.applocationid = ?", applocationID)
	}
	if productID > 0 {
		query = query.Where("a.productid = ?", productID)
	}
	if keyword != "" {
		like := "%" + strings.ToLower(keyword) + "%"
		query = query.Where(
			db.DB.Where("LOWER(a.productname) LIKE ?", like).
				Or("LOWER(a.unitvalue) LIKE ?", like).
				Or("LOWER(CAST(a.productcost AS CHAR)) LIKE ?", like),
		)
	}

	if err := query.Select("a.*").Find(&products).Error; err != nil {
		utils.Error("Error fetching products", "error", err)
		return nil, err
	}

	// Step 3: Grouping
	var grouped []models.SubcategoryProductResponse
	var uncategorized []models.Products

	for _, subcat := range subcategories {
		var matched []models.Products
		for _, prod := range products {
			if prod.Subcategoryid != nil && *prod.Subcategoryid == subcat.Subcategoryid {
				matched = append(matched, prod)
			}
		}
		if len(matched) > 0 {
			grouped = append(grouped, models.SubcategoryProductResponse{
				SubcategoryID:   subcat.Subcategoryid,
				SubcategoryName: subcat.Subcategoryname,
				Products:        matched,
			})
		}
	}

	// Add uncategorized
	for _, p := range products {
		if p.Subcategoryid == nil {
			uncategorized = append(uncategorized, p)
		}
	}
	if len(uncategorized) > 0 {
		grouped = append(grouped, models.SubcategoryProductResponse{
			SubcategoryID:   0,
			SubcategoryName: "Uncategorized",
			Products:        uncategorized,
		})
	}

	// Step 4: Tenant info
	var tenantInfo map[string]interface{}
	for _, p := range products {
		if p.Tenantid != nil {
			tenantInfo, err = fetchTenantDetails(*p.Tenantid, applocationID)
			if err != nil {
				utils.Error("Error fetching tenant details", "error", err)
			}
			break
		}
	}

	if tenantInfo == nil {
		return map[string]interface{}{}, nil
	}

	tenantInfo["details"] = grouped
	return tenantInfo, nil
}

func fetchTenantDetails(tenantID, applocationID int) (map[string]interface{}, error) {
	var tenant struct {
		Tenantname       string
		Address          string
		Licenseno        string
		Primaryemail     string
		Primarycontact   string
		Locationname     string
		Pickuplocationid int
		Suburb           string
		City             string
		Latitude         string
		Longitude        string
		Postcode         string
	}

	err := db.DB.Raw(`
		SELECT t.tenantname,t.address,t.licenseno,t.primaryemail,t.primarycontact,l.locationid AS pickuplocationid,l.suburb,l.city,l.latitude,l.longitude,l.postcode,a.locationname
		FROM tenants t
		LEFT JOIN tenantlocations l ON t.tenantid = l.tenantid
		LEFT JOIN app_location a ON l.applocationid = a.applocationid
		WHERE t.tenantid = ? AND t.applocationid = ?
		LIMIT 1
	`, tenantID, applocationID).Scan(&tenant).Error

	if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
		return nil, err
	}

	return map[string]interface{}{
		"tenantname":       tenant.Tenantname,
		"address":          tenant.Address,
		"licenseno":        tenant.Licenseno,
		"primaryemail":     tenant.Primaryemail,
		"primarycontact":   tenant.Primarycontact,
		"locationname":     tenant.Locationname,
		"pickuplocationid": tenant.Pickuplocationid,
		"suburb":           tenant.Suburb,
		"city":             tenant.City,
		"pickuplat":        tenant.Latitude,
		"pickuplong":       tenant.Longitude,
		"postcode":         tenant.Postcode,
	}, nil
}

func UpdateProductStock(stock *models.Productstock) error {
	// Ensure the record exists
	var existing models.Productstock
	if err := db.DB.First(&existing, "productstockid = ?", stock.Productstockid).Error; err != nil {
		return err
	}

	// Update fields
	return db.DB.Model(&existing).Updates(models.Productstock{
		Tenantid:   stock.Tenantid,
		Stockdate:  stock.Stockdate,
		Locationid: stock.Locationid,
		Productid:  stock.Productid,
		Quantity:   stock.Quantity,
		Stocktype:  stock.Stocktype,
		Status:     stock.Status,
	}).Error
}

func GetProductStocks(tenantID, locationID string) ([]models.Productstocks, error) {
	var stocks []models.Productstocks
	var params []interface{}
	var conditions []string

	query := `
		SELECT
			a.productid, a.tenantid, MAX(a.stockdate) AS stockdate, a.locationid, a.stocktype, a.maxquantity, a.minquantity, a.status,
			b.applocationid, b.categoryid, b.subcategoryid, b.catalogueid, b.addonid, b.discountid, b.pricingid,
			b.productname, b.productimage, b.productdesc, b.productsku, b.brandid, b.productbrand, b.productunit,
			b.unitvalue, b.toppicks, b.productcost, b.taxamount, b.taxpercent, b.producttax, b.productstock,
			b.productcombo, b.variants, b.retailprice, b.diffprice, b.diffpercent, b.othercost, b.approve,
			b.productstatus, b.created, b.updated, c.subcatname AS subcategoryname,
			SUM(CASE WHEN a.stocktype = 'in'  THEN a.quantity ELSE 0 END) -
			SUM(CASE WHEN a.stocktype = 'out' THEN a.quantity ELSE 0 END) AS quantity
		FROM productstocks a
		JOIN products b ON a.productid = b.productid
		INNER JOIN productsubcategories c ON c.subcatid = b.subcategoryid
	`

	if tenantID != "" {
		conditions = append(conditions, "a.tenantid = ?")
		params = append(params, tenantID)
	}

	if locationID != "" {
		conditions = append(conditions, "a.locationid = ?")
		params = append(params, locationID)
	}

	if len(conditions) > 0 {
		query += " WHERE " + strings.Join(conditions, " AND ")
	}

	query += " GROUP BY a.productid"

	if err := db.DB.Raw(query, params...).Scan(&stocks).Error; err != nil {
		return nil, err
	}

	return stocks, nil
}

func GetSubCategoryWiseSummary(tenantId, locationid, subcategoryid int) ([]models.SubCategorySummary, error) {
	var data []models.SubCategorySummary

	query := `
		SELECT a.subcategoryid AS subcategoryid, c.subcatname AS subcatname, COUNT(a.productid) AS productcount
		FROM products a
		LEFT JOIN productlocations b ON a.productid = b.productid AND b.locationid = ? AND b.tenantid = a.tenantid
		LEFT JOIN productsubcategories c ON a.subcategoryid = c.subcatid
		WHERE a.approve = 1 AND a.tenantid = ? AND b.productid IS NULL
	`

	var params []interface{}
	params = append(params, locationid, tenantId)

	if subcategoryid > 0 {
		query += " AND a.subcategoryid = ?"
		params = append(params, subcategoryid)
	}

	query += `
		GROUP BY a.subcategoryid, c.subcatname
		ORDER BY a.subcategoryid ASC
	`

	if err := db.DB.Raw(query, params...).Scan(&data).Error; err != nil {
		return nil, err
	}

	return data, nil
}

func GetLocationProductSummary(tenantid, locationid int) []models.ProductSummary {
	data := make([]models.ProductSummary, 0)

	params := []interface{}{tenantid, locationid}

	query := `
		SELECT a.subcatid AS subcategoryid, a.subcatname AS subcategroyname, a.image, COUNT(DISTINCT b.productid) AS productcount
		FROM productsubcategories a
		LEFT JOIN products b ON a.subcatid = b.subcategoryid AND b.approve = 1 AND b.tenantid = ?
		LEFT JOIN productlocations c ON b.productid = c.productid AND b.tenantid = c.tenantid AND c.locationid = ?
		WHERE a.categoryid = 2
		GROUP BY a.subcatid, a.subcatname
		ORDER BY a.subcatid;
	`

	db.DB.Raw(query, params...).Scan(&data)

	total := 0
	for _, d := range data {
		total += d.Productcount
	}

	all := models.ProductSummary{
		Subcategoryid:   0,
		Subcategroyname: "All",
		Productcount:    total,
	}
	data = append([]models.ProductSummary{all}, data...)

	return data
}

func GetStockStatementSummary(tenantid, locationid int) []models.ProductSummary {
	data := make([]models.ProductSummary, 0)

	params := []interface{}{tenantid, locationid}

	query := `
		SELECT a.subcatid AS subcategoryid, a.subcatname AS subcategroyname, a.image, COUNT(DISTINCT b.productid) AS productcount
		FROM productsubcategories a
		LEFT JOIN products b ON a.subcatid = b.subcategoryid AND b.tenantid = ?
		LEFT JOIN productlocations c ON b.productid = c.productid AND b.tenantid = c.tenantid AND c.locationid = ?
		WHERE a.categoryid = 2
		GROUP BY a.subcatid, a.subcatname
		ORDER BY a.subcatid;
	`

	db.DB.Raw(query, params...).Scan(&data)

	utils.Logger.Debugf("Query: %s", query)

	// Add "All" row
	total := models.ProductSummary{
		Subcategoryid:   0,
		Subcategroyname: "All",
	}
	for _, d := range data {
		total.Productcount += d.Productcount
	}
	data = append([]models.ProductSummary{total}, data...)

	return data
}

func CreateProductDiscount(discount *models.ProductDiscount) error {

	// convert []string to comma-separated string
	if len(discount.Locationid) > 0 {
		discount.LocationidStr = strings.Join(discount.Locationid, ",")
	}

	tx := db.DB.Begin()

	if err := tx.Table("productdiscounts").Create(discount).Error; err != nil {
		tx.Rollback()
		return err
	}

	return tx.Commit().Error
}

func GetProductDiscounts(tid int, lid string) []models.ProductDiscount {

	var result []models.ProductDiscount

	query := `
        SELECT 
            discountid, discounttypeid, tenantid, productid,  moduleid,
            locationid, discountname, discountcode,
            discountterms, discountvalue, startdate, enddate, status
        FROM productdiscounts
        WHERE tenantid = ?
          AND moduleid = 2
          AND FIND_IN_SET(?, locationid)
    `

	db.DB.Raw(query, tid, lid).Scan(&result)

	// convert comma separated location ids to []string
	for i := range result {
		if result[i].LocationidStr != "" {
			result[i].Locationid = strings.Split(result[i].LocationidStr, ",")
		} else {
			result[i].Locationid = []string{}
		}
	}

	return result
}
