package order_repository

import (
	_const "chonho/const"
	"chonho/internal/api-v1/entity"
	"chonho/pkg/model"
	"errors"
	"gorm.io/gorm"
)

func (r *repository) SellerOrderList(sellerId int64, filter SellerOrderFilter) ([]entity.SellerOrder, error) {
	var result []entity.SellerOrder
	builder := r.db.Table("orders as od").
		Joins("JOIN stores AS st ON od.store_id = st.id").
		Joins("JOIN users AS seller ON st.user_id = seller.id").
		Joins("JOIN users AS buyer ON od.user_id = buyer.id").
		Joins("JOIN user_shipping_addresses AS a ON a.id = od.shipping_address_id").
		Select(`
			od.id,
			od.code,
			od.status,
			od.payment_status,
			od.payment_proof,
			od.shipping_address_string,
			od.note,
			od.price,
			od.total_items,
			od.total_delivered,
			od.canceled_reason,
			od.created_at,
			od.is_quote_after_ordering,
			buyer.id AS buyer_id,
			buyer.name AS buyer_name,
			buyer.phone AS buyer_phone,
			a.receiver_name,
			a.receiver_phone,
			a.apartment_house_number,
			st.id AS store_id,
			st.name AS store_name,
			seller.id AS seller_id,
			seller.name AS seller_name
		`).Where("seller.id = ?", sellerId)

	if filter.StoreId != 0 {
		builder.Where("st.id = ?", filter.StoreId)
	}

	if len(filter.PaymentStatus) > 0 {
		builder.Where("od.status IN (?)", filter.Status)
	}

	if len(filter.PaymentStatus) > 0 {
		builder.Where("od.payment_status IN (?)", filter.PaymentStatus)
	}

	if len(filter.OrderIds) > 0 {
		builder.Where("od.id IN (?)", filter.OrderIds)
	}

	if filter.CreatedFrom != nil {
		builder.Where("od.created_at >= ?", filter.CreatedFrom)
	}

	if filter.CreatedTo != nil {
		builder.Where("od.created_at <= ?", filter.CreatedTo)
	}

	if filter.GroupStatus != 0 {
		switch filter.GroupStatus {
		case _const.OrderGroupStatusPending:
			builder.Where("od.status IN (?)", []int{
				_const.OrderStatusNew,
				_const.OrderStatusRequestCancel,
			}).Order("od.created_at DESC")

		case _const.OrderGroupStatusDelivering:
			builder.Where("od.status IN (?)", []int{
				_const.OrderStatusConfirmed,
				_const.OrderStatusReadyToShip,
				_const.OrderStatusInTransit,
			}).Order("od.updated_at DESC")
			// TODO change updated_at to status_updated_at
		case _const.OrderGroupStatusCompleted:
			builder.Where("od.status IN (?)", []int{
				_const.OrderStatusDelivered,
				_const.OrderStatusReceived,
			}).Order("od.updated_at DESC")
		}
	} else {
		builder.Order("od.created_at DESC")
	}

	lim := 100
	offset := 0

	if filter.Limit != 0 {
		lim = filter.Limit
	}
	if filter.Page != 0 {
		offset = lim * (filter.Page - 1)
	}
	err := builder.Limit(lim).Offset(offset).Find(&result).Error
	if err != nil {
		return nil, err
	}
	return result, nil

}

func (r *repository) SellerOrderDetail(orderID int64) ([]entity.SellerOrderItem, error) {
	var items []entity.SellerOrderItem
	err := r.db.Table("order_items AS odi").
		Joins("LEFT JOIN products AS p ON odi.product_id = p.id").
		Where("order_id = ?", orderID).
		Select(`odi.*, p.unit`).
		Find(&items).Error
	return items, err
}

func (r *repository) UpdateOrderItem(filter OrderItemFilter, data map[string]interface{}) (int64, error) {
	builder := r.db.Model(&model.OrderItem{})
	hasFilter := false

	if filter.Id > 0 {
		builder.Where("id = ?", filter.Id)
		hasFilter = true
	}

	if filter.OrderId != 0 {
		builder.Where("order_id = ?", filter.OrderId)
		hasFilter = true
	}
	if len(filter.ProductIds) > 0 {
		builder.Where("product_id IN (?)", filter.ProductIds)
		hasFilter = true
	}
	if len(filter.Status) > 0 {
		builder.Where("status IN (?)", filter.Status)
		hasFilter = true
	}
	if !hasFilter {
		return 0, errors.New("no filter available on update order item")
	}

	db := builder.Updates(data)
	return db.RowsAffected, db.Error
}

func (r *repository) QueryOrderItem(filter OrderItemFilter) ([]model.OrderItem, error) {
	var result []model.OrderItem
	builder := r.db.Model(&model.OrderItem{})
	hasFilter := false

	if filter.Id > 0 {
		builder.Where("id = ?", filter.Id)
	}

	if filter.OrderId != 0 {
		builder.Where("order_id = ?", filter.OrderId)
		hasFilter = true
	}
	if len(filter.ProductIds) > 0 {
		builder.Where("product_id IN (?)", filter.ProductIds)
		hasFilter = true
	}
	if len(filter.Status) > 0 {
		builder.Where("status IN (?)", filter.Status)
		hasFilter = true
	}
	if !hasFilter {
		return nil, errors.New("no filter available on update order item")
	}

	err := builder.Find(&result).Error
	return result, err
}

func (r *repository) FirstOrders(filter OrderFilter) (*model.Order, error) {
	orders, err := r.GetOrders(filter)
	if err != nil {
		return nil, err
	}
	if len(orders) == 0 {
		return nil, gorm.ErrRecordNotFound
	}
	return &orders[0], nil
}

func (r *repository) UpdateDeliveredItem(orderId int64) error {
	subQuery := r.db.Model(&model.OrderItem{}).Select("sum(quantity)").Where("order_id = ? and status = ?", orderId, _const.OrderItemStatusDelivered)
	return r.db.Model(&model.Order{}).Where("id = ?", orderId).Update("total_delivered", subQuery).Error
}
