package mysql

import (
	entity "git.gocasts.ir/ebhomengo/niki/domain/order/entity"
	richerror "git.gocasts.ir/ebhomengo/niki/pkg/rich_error"
	"git.gocasts.ir/ebhomengo/niki/types"
)

func (d *DB) CreateOrder(order entity.Order, orderItems []entity.OrderItem) (types.ID, error) {

	const Op = "domain.repository.mysql.order.create-order"
	tx, err := d.conn.Conn().Begin()

	if err != nil {
		return 0, richerror.New(Op).WithErr(err)
	}

	defer tx.Rollback()

	query := "insert into orders(user_id, address_id, shipping_id," +
		" payment_method, payment_status, process_status," +
		" total_amount, total_discount) values (?, ?, ?, ?, ?, ?, ?, ?);"
	res, oErr := tx.Exec(query, order.UserID, order.AddressID, order.ShippingID,
		order.PaymentMethod, order.PaymentStatus, order.ProcessStatus,
		order.TotalAmount, order.TotalDiscount)

	if oErr != nil {
		return 0, richerror.New(Op).WithErr(oErr)
	}
	orderID, insertIDErr := res.LastInsertId()
	if insertIDErr != nil {
		return 0, richerror.New(Op).WithErr(insertIDErr)
	}

	orderItemQuery := "insert into order_items(order_id, product_id, quantity, price, price_with_discount) values(?, ?, ?, ?, ?);"
	for _, item := range orderItems {
		_, iErr := tx.Exec(orderItemQuery, orderID, item.ProductID, item.Quantity, item.Price, item.PriceWithDiscount)
		if iErr != nil {
			return 0, richerror.New(Op).WithErr(iErr)
		}
	}

	if err := tx.Commit(); err != nil {
		return 0, richerror.New(Op).WithErr(err)
	}

	return types.ID(orderID), nil
}

func (d *DB) UpdateOrderProcessStatus(orderID types.ID, status string) (bool, error) {
	const Op = "domain.repository.mysql.order.update-order-process-status"
	_, err := d.conn.Conn().Exec("update orders set process_status=? where id=?;", status, orderID)

	if err != nil {
		return false, richerror.New(Op).WithErr(err)
	}

	return true, nil

}

func (d *DB) GetShipping() ([]entity.Shipping, error) {
	const Op = "domain.repository.mysql.order.get-shipping"
	rows, err := d.conn.Conn().Query("select * from shippings where is_active=1")

	if err != nil {
		return []entity.Shipping{}, richerror.New(Op).WithErr(err)
	}

	defer rows.Close()

	var shippings []entity.Shipping

	for rows.Next() {
		var s entity.Shipping

		err := rows.Scan(
			&s.ID,
			&s.Name,
			&s.Price,
			&s.IsActive,
		)
		if err != nil {
			return nil, richerror.New(Op).WithErr(err)
		}

		shippings = append(shippings, s)
	}

	return shippings, nil

}
