package transform

import (
	"fmt"
	"github.com/UpmeshLTD/urus-aio/infrastructure/enums"
	"log"
	"strconv"
	"strings"
	"time"

	"github.com/UpmeshLTD/urus-aio/infrastructure/db/entities"
	"github.com/UpmeshLTD/urus-aio/shipment/server/http/dto"
)

func NotifyCourierFlashExpressTHRequestToCourierLogParamsEntity(req *dto.NotifyCourierFlashExpressRequest) *entities.FlashExpressUpdateCourierWebhookParams {
	result := &entities.FlashExpressUpdateCourierWebhookParams{
		TicketPickupID:        req.Data.TicketPickupID,
		CurrentTicketPickupID: req.Data.CurrentTicketPickupID,
		State:                 req.Data.State,
		StateText:             req.Data.StateText,
		CancelReasonText:      req.Data.CancelReasonText,
		CancelOperatorID:      req.Data.CancelOperatorID,
		CancelReasonCode:      req.Data.CancelReasonCode,
	}
	i, err := strconv.ParseInt(req.Data.UpdateAt, 10, 64)
	if err == nil {
		result.StateDate = time.Unix(i, 0)
	}
	return result
}

func NotifyStatusJTExpressTHRequestToShipmentStatusLogEntity(shipment *entities.Shipment, req *dto.NotifyStatusJTExpressTHRequestData) *entities.ShipmentStatusLog {
	var (
		scanType string
		scanTime time.Time
		status   entities.ShipmentStatus
	)

	if len(req.Traces) > 0 {
		traceItem := req.Traces[len(req.Traces)-1]

		scanType = traceItem.ScanType

		t, err := time.Parse(enums.TimeFormatYMDHIS, traceItem.ScanTime)
		if err == nil {
			scanTime = t
		}

		sts, ok := entities.MappingJTExpressTHStatusToShipmentStatus[strings.ToUpper(scanType)]
		if !ok {
			fmt.Println("[JTExpressUpdateStatusWebhookDTOToEntity]", fmt.Sprintf("status %s not exist in mapping", scanType))
		}
		status = sts
	}

	return &entities.ShipmentStatusLog{
		CourierTrackingID: req.BillCode,
		CourierID:         shipment.CourierID,
		CourierStatus:     scanType,
		StateText:         scanType,
		Status:            status,
		StateDate:         scanTime,
	}
}

func NotifyStatusJTExpressMYRequestToShipmentStatusLogEntity(shipment *entities.Shipment, req *dto.NotifyStatusJTExpressMYRequestData) *entities.ShipmentStatusLog {
	var (
		courierTrackingID string
		statusCode        string
		statusText        string
		stateDate         time.Time
	)

	if len(req.History) > 0 {
		item := req.History[len(req.History)-1]

		statusCode = strconv.Itoa(item.StatusCode)
		statusText = item.StatusText

		t, err := time.Parse(enums.TimeFormatYMDHIS, item.DateTime)
		if err == nil {
			stateDate = t
		}
	}

	status, ok := entities.MappingJTExpressMYStatusToShipmentStatus[statusCode]
	if ok {
		fmt.Println("[NotifyStatusJTExpressMYRequestToShipmentStatusLogEntity]", fmt.Sprintf("status code `%s` not exist in mapping", statusCode))
	}

	if shipment.CourierTrackingID != nil {
		courierTrackingID = *shipment.CourierTrackingID
	}

	return &entities.ShipmentStatusLog{
		CourierTrackingID: courierTrackingID,
		CourierID:         shipment.CourierID,
		CourierStatus:     statusCode,
		StateText:         statusText,
		StateDate:         stateDate,
		Status:            status,
	}
}

func NotifyStatusFlashExpressRequestToShipmentStatusLogEntity(shipment *entities.Shipment, req *dto.NotifyStatusFlashExpressRequestData) *entities.ShipmentStatusLog {
	result := &entities.ShipmentStatusLog{
		CourierID:         shipment.CourierID,
		CourierTrackingID: *shipment.CourierTrackingID,
		CourierStatus:     req.State,     // Courier status code: 1-9
		StateText:         req.StateText, // Courier status text: Picked up
	}
	if i, err := strconv.ParseInt(req.StateDate, 10, 64); err == nil {
		result.StateDate = time.Unix(i, 0)
	}
	if status, ok := entities.MappingFlashExpressWebhookStatusToShipmentStatus[req.State]; ok {
		result.Status = status
	}
	return result
}

func NotifyStatusJTExpressSGRequestToShipmentStatusLogEntity(shipment *entities.Shipment, req *dto.NotifyStatusJTExpressSGRequest) *entities.ShipmentStatusLog {
	stateDate, err := time.Parse("2006-01-02T15:04:05-07:00", req.Timestamp)
	if err != nil {
		log.Printf("[NotifyStatusJTExpressSGRequestToShipmentStatusLogEntity] Parse time %s failed: %s\n", req.Timestamp, err)
		stateDate = time.Now()
	}
	result := &entities.ShipmentStatusLog{
		CourierID:         shipment.CourierID,
		CourierTrackingID: *shipment.CourierTrackingID,
		CourierStatus:     req.Status, // Courier status code: PENDING_PICKUP, ACCEPTED_PICKUP
		StateText:         req.Status,
		StateDate:         stateDate,
	}
	if status, ok := entities.MappingJTExpressSGStatusToShipmentStatus[req.Status]; ok {
		// Upmesh status code: picked_up, on_delivery
		result.Status = status
	}
	return result
}

func NotifyStatusKerryExpressTHRequestToShipmentStatusLogEntity(shipment *entities.Shipment, req *dto.NotifyStatusKerryExpressTHRequest) *entities.ShipmentStatusLog {
	stateDate, err := time.Parse(enums.TimeFormatYMDHIS, req.StatusDate)
	if err != nil {
		log.Printf("[NotifyStatusKerryExpressTHRequestToShipmentStatusLogEntity] Parse time %s failed: %s\n", req.StatusDate, err)
		stateDate = time.Now()
	}
	result := &entities.ShipmentStatusLog{
		CourierID:         shipment.CourierID,
		CourierTrackingID: *shipment.CourierTrackingID,
		CourierStatus:     req.StatusCode, // Courier status code: "Your parcel has been received", "Your parcel has been picked up"
		StateText:         req.StatusCode,
		StateDate:         stateDate,
	}
	if status, ok := entities.MappingKerryExpressTHStatusToShipmentStatus[strings.ToUpper(req.StatusCode)]; ok {
		// Upmesh status code: picked_up, on_delivery
		result.Status = status
	}
	return result
}
