package user

import (
	"context"
	"encoding/json"
	"errors"
	"io/ioutil"
	"log"
	"net/http"
	detaildoEntity "refund/internal/entity/user/detaildo"
	paymentmethodEntity "refund/internal/entity/user/paymentmethod"
	pelapakEntity "refund/internal/entity/user/pelapak"
	refundEntity "refund/internal/entity/user/refund"
	shopeeEntity "refund/internal/entity/user/shopee"

	"refund/pkg/response"
	"strings"
)

// IUserSvc is an interface to User Service
type IUserSvc interface {
	GetListPelapak(ctx context.Context, orderidecommerce string) ([]pelapakEntity.Pelapak, error)
	GetDetailDo(ctx context.Context, TransfH_NoTransf string) (map[string][]detaildoEntity.DetailDo, error)
	GetEcommerceId(ctx context.Context, OrderIDEcommerce string, rh_orderIdEcommerce string) (map[string]interface{}, error)
	InsertRefundH(ctx context.Context, user refundEntity.RefundH) error
	InsertRefundD(ctx context.Context, user []refundEntity.RefundD) error
	UpdateRefundD(ctx context.Context, OrderID string, refundd refundEntity.RefundD) error
	GetShopeeResult(Ordersn string) (shopeeEntity.ShopeeResult, error)
	GetRefundD(ctx context.Context, ID string) (map[string][]refundEntity.RefundD, error)
	GetPaymentMethod(ctx context.Context, ID string) ([]paymentmethodEntity.PaymentMethod, error)
	InsertPaymentMethod(ctx context.Context, pay paymentmethodEntity.PaymentMethod) error
}

type (
	// Handler ...
	Handler struct {
		userSvc IUserSvc
	}
)

// New for user domain handler initialization
func New(is IUserSvc) *Handler {
	return &Handler{
		userSvc: is,
	}
}

// UserHandler will return user data
func (h *Handler) UserHandler(w http.ResponseWriter, r *http.Request) {
	var (
		resp     *response.Response
		metadata interface{}
		result   interface{}
		err      error
		errRes   response.Error
		refundh  refundEntity.RefundH
		// refundd  refundEntity.RefundD
		refunddList []refundEntity.RefundD
		refundd     refundEntity.RefundD
		pay         paymentmethodEntity.PaymentMethod
	)
	// Make new response object
	resp = &response.Response{}
	body, _ := ioutil.ReadAll(r.Body)
	// Defer will be run at the end after method finishes
	defer resp.RenderJSON(w, r)

	switch r.Method {
	// Check if request method is GET
	case http.MethodGet:
		if _, x := r.URL.Query()["typeGet"]; x {
			_typeGet := r.FormValue("typeGet")
			switch _typeGet {
			case "ListPelapak":
				result, err = h.userSvc.GetListPelapak(context.Background(), r.FormValue("orderidecommerce"))

			case "DetailDO":
				result, err = h.userSvc.GetDetailDo(context.Background(), r.FormValue("TransfH_NoTransf"))

			case "EcomID":
				result, err = h.userSvc.GetEcommerceId(context.Background(), r.FormValue("OrderIDEcommerce"), r.FormValue("rh_orderIdEcommerce"))
			case "ShopeeResult":
				result, err = h.userSvc.GetShopeeResult(r.FormValue("Ordersn"))
			case "DetailRefundD":
				result, err = h.userSvc.GetRefundD(context.Background(), r.FormValue("ID"))
			case "PaymentMethod":
				result, err = h.userSvc.GetPaymentMethod(context.Background(), r.FormValue("ID"))
			}

		}
	case http.MethodPost:
		if _, x := r.URL.Query()["typePost"]; x {
			_typePost := r.FormValue("typePost")
			switch _typePost {

			case "RefundH":
				json.Unmarshal(body, &refundh)
				err = h.userSvc.InsertRefundH(context.Background(), refundh)

			case "RefundD":
				err = json.Unmarshal(body, &refunddList)
				err = h.userSvc.InsertRefundD(context.Background(), refunddList)
			case "PaymentMethod":
				err = json.Unmarshal(body, &pay)
				err = h.userSvc.InsertPaymentMethod(context.Background(), pay)
			}
		}

	case http.MethodPut:
		json.Unmarshal(body, &refundd)

		if _, x := r.URL.Query()["typePut"]; x {
			_typePut := r.FormValue("typePut")
			switch _typePut {

			case "UpdateRefundD":
				err = h.userSvc.UpdateRefundD(context.Background(), r.FormValue("OrderID"), refundd)

			}
		}

	default:
		err = errors.New("400")
	}

	// If anything from service or data return an error
	if err != nil {
		// Error response handling
		errRes = response.Error{
			Code:   101,
			Msg:    "Data Not Found",
			Status: true,
		}
		// If service returns an error
		if strings.Contains(err.Error(), "service") {
			// Replace error with server error
			errRes = response.Error{
				Code:   201,
				Msg:    "Failed to process request due to server error",
				Status: true,
			}
		}

		// Logging
		log.Printf("[ERROR] %s %s - %v\n", r.Method, r.URL, err)
		resp.Error = errRes
		return
	}

	// Inserting data to response
	resp.Data = result
	resp.Metadata = metadata
	// Logging
	log.Printf("[INFO] %s %s\n", r.Method, r.URL)
}
