package transform

import (
	"github.com/UpmeshLTD/urus-aio/infrastructure/db/entities"
	"github.com/UpmeshLTD/urus-aio/paid-order/service/dto"
	"gorm.io/gorm"
)

func CreateDeliveryAddressRequestToEntity(req *dto.CreateDeliveryAddressRequest, owner string) *entities.DeliveryAddress {
	return &entities.DeliveryAddress{
		Address: entities.Address{
			CountryID:         entities.CountryIdsMap[req.CountryCode],
			Address1:          req.Address1,
			Address2:          req.Address2,
			PostalCode:        req.PostalCode,
			UnitNumber:        req.UnitNumber,
			SubLevelLocations: *SubLevelLocationsDTOToEntity(&req.SubLevelLocationIDs),
		},
		RecipientName:        req.RecipientName,
		RecipientPhoneNumber: req.RecipientPhoneNumber,
		CartID:               req.CartID,
		Owner:                owner,
		Version:              1,
	}
}

func CreateDeliveryAddressOptionalRequestToEntity(req *dto.CreateDeliveryAddressOptionalRequest, owner string) *entities.DeliveryAddress {
	return &entities.DeliveryAddress{
		Address: entities.Address{
			CountryID:         entities.CountryIdsMap[req.CountryCode],
			Address1:          req.Address1,
			Address2:          req.Address2,
			PostalCode:        req.PostalCode,
			UnitNumber:        req.UnitNumber,
			SubLevelLocations: *SubLevelLocationsDTOToEntity(&req.SubLevelLocationIDs),
		},
		RecipientName:        req.RecipientName,
		RecipientPhoneNumber: req.RecipientPhoneNumber,
		CartID:               req.CartID,
		Owner:                owner,
		Version:              1,
	}
}

func DeliveryAddressEntityToDTO(entity *entities.DeliveryAddress) *dto.DeliveryAddress {
	if entity == nil {
		return nil
	}

	locations := make([]*dto.SubLevelLocation, 0)
	for _, v := range entity.Address.SortSubLevelLocations() {
		locations = append(locations, &dto.SubLevelLocation{
			ID:                v.ID.ToInt64(),
			InternationalName: v.InternationalName,
			LocalizedName:     v.LocalizedName,
			ParentID:          v.ParentID,
		})
	}
	return &dto.DeliveryAddress{
		Address1:          entity.Address.Address1,
		Address2:          entity.Address.Address2,
		PostalCode:        entity.Address.PostalCode,
		UnitNumber:        entity.Address.UnitNumber,
		CountryCode:       entity.Address.Country.Code,
		Deactivate:        entity.Address.Deactivate,
		SubLevelLocations: locations,

		AddressID:            entity.AddressID,
		CartID:               entity.CartID,
		RecipientName:        entity.RecipientName,
		RecipientPhoneNumber: entity.RecipientPhoneNumber,
		Version:              entity.Version,
	}
}

func SubLevelLocationsDTOToEntity(subLevelLocations *[]int64) *[]entities.Location {
	if subLevelLocations == nil {
		return nil
	}
	var locations []entities.Location
	for _, v := range *subLevelLocations {
		locations = append(locations, entities.Location{
			BaseEntity: entities.BaseEntity{
				ID: entities.ID{
					ID: v,
				},
			},
		})
	}
	return &locations
}

func DeliveryAddressParamsToAddressMaps(params *entities.SaveDeliveryAddressParams) map[string]interface{} {
	addressMaps := map[string]interface{}{}

	if params.Address1 != nil {
		addressMaps["Address1"] = *params.Address1
	}
	if params.Address2 != nil {
		addressMaps["Address2"] = *params.Address2
	}
	if params.PostalCode != nil {
		addressMaps["PostalCode"] = *params.PostalCode
	}
	if params.SubLevelLocations != nil {
		addressMaps["SubLevelLocations"] = *params.SubLevelLocations
	}
	if params.UnitNumber != nil {
		addressMaps["UnitNumber"] = *params.UnitNumber
	}

	return addressMaps
}

func DeliveryAddressParamsToDeliveryAddressMaps(params *entities.SaveDeliveryAddressParams) map[string]interface{} {
	maps := map[string]interface{}{
		"Version": gorm.Expr("version + 1"),
	}

	if params.RecipientPhoneNumber != nil {
		maps["RecipientPhoneNumber"] = params.RecipientPhoneNumber
	}
	if params.RecipientName != nil {
		maps["RecipientName"] = params.RecipientName
	}

	return maps
}

func DeliveryAddressEntityToAddressMaps(entity *entities.DeliveryAddress) map[string]interface{} {
	return map[string]interface{}{
		"Address1":          entity.Address.Address1,
		"Address2":          entity.Address.Address2,
		"PostalCode":        entity.Address.PostalCode,
		"UnitNumber":        entity.Address.UnitNumber,
		"SubLevelLocations": entity.Address.SubLevelLocations,
	}
}

func DeliveryAddressEntityToDeliveryAddressMaps(entity *entities.DeliveryAddress) map[string]interface{} {
	return map[string]interface{}{
		"Version":              entity.Version,
		"RecipientPhoneNumber": entity.RecipientPhoneNumber,
		"RecipientName":        entity.RecipientName,
	}
}

func DeliveryAddressEntityToDeliveryAddressLogEntity(entity *entities.DeliveryAddress) *entities.DeliveryAddressLog {
	subLocations := make([]entities.SubLocationLog, 0)
	for _, sll := range entity.Address.SortSubLevelLocations() {
		subLocations = append(subLocations, entities.SubLocationLog{
			ID:                sll.ID.ToInt64(),
			InternationalName: sll.InternationalName,
			LocalizedName:     sll.LocalizedName,
			ParentID:          sll.ParentID,
		})
	}
	return &entities.DeliveryAddressLog{
		CartID: entity.CartID,
		Address: entities.AddressJson{
			Address1:          entity.Address.Address1,
			Address2:          entity.Address.Address2,
			PostalCode:        entity.Address.PostalCode,
			UnitNumber:        entity.Address.UnitNumber,
			SubLevelLocations: subLocations,
		},
		RecipientName:        entity.RecipientName,
		RecipientPhoneNumber: entity.RecipientPhoneNumber,
		Version:              entity.Version,
		Deactivate:           false,
	}
}

func UpdateRecipientNameRequestToDeliveryAddressParams(req *dto.UpdateRecipientNameRequest) *entities.SaveDeliveryAddressParams {
	return &entities.SaveDeliveryAddressParams{
		CartID:        req.CartID,
		RecipientName: &req.RecipientName,
	}
}

func UpdateRecipientNameRequestToDeliveryAddressEntity(req *dto.UpdateRecipientNameRequest) *entities.DeliveryAddress {
	return &entities.DeliveryAddress{
		CartID:        req.CartID,
		Address:       entities.Address{CountryID: entities.CountryIdsMap[req.CountryCode]},
		RecipientName: req.RecipientName,
		Version:       1,
	}
}

func UpdateRecipientPhoneNumberRequestToDeliveryAddressParams(req *dto.UpdateRecipientPhoneNumberRequest) *entities.SaveDeliveryAddressParams {
	return &entities.SaveDeliveryAddressParams{
		CartID:               req.CartID,
		RecipientPhoneNumber: &req.RecipientPhoneNumber,
	}
}

func UpdateRecipientPhoneNumberRequestToDeliveryAddressEntity(req *dto.UpdateRecipientPhoneNumberRequest) *entities.DeliveryAddress {
	return &entities.DeliveryAddress{
		CartID:               req.CartID,
		Address:              entities.Address{CountryID: entities.CountryIdsMap[req.CountryCode]},
		RecipientPhoneNumber: req.RecipientPhoneNumber,
		Version:              1,
	}
}

func UpdateAddressRequestToDeliveryAddressParams(req *dto.UpdateAddressRequest) *entities.SaveDeliveryAddressParams {
	return &entities.SaveDeliveryAddressParams{
		CartID:            req.CartID,
		CountryID:         entities.CountryIdsMap[req.CountryCode],
		Address1:          &req.Address1,
		Address2:          &req.Address2,
		PostalCode:        &req.PostalCode,
		UnitNumber:        &req.UnitNumber,
		RecipientName:     &req.RecipientName,
		SubLevelLocations: SubLevelLocationsDTOToEntity(&req.SubLevelLocationIDs),
	}
}

func UpdateAddressRequestToDeliveryAddressEntity(req *dto.UpdateAddressRequest) *entities.DeliveryAddress {
	return &entities.DeliveryAddress{
		Address: entities.Address{
			CountryID:         entities.CountryIdsMap[req.CountryCode],
			Address1:          req.Address1,
			Address2:          req.Address2,
			PostalCode:        req.PostalCode,
			UnitNumber:        req.UnitNumber,
			SubLevelLocations: *SubLevelLocationsDTOToEntity(&req.SubLevelLocationIDs),
		},
		RecipientName: req.RecipientName,
		CartID:        req.CartID,
		Owner:         "",
		Version:       1,
	}
}

func DeliveryAddressLogEntitiesToDTOs(logs []*entities.DeliveryAddressLog) []*dto.DeliveryAddressLog {
	res := make([]*dto.DeliveryAddressLog, 0)
	for _, log := range logs {
		locations := make([]*dto.SubLevelLocation, 0)
		for _, v := range log.Address.SubLevelLocations {
			locations = append(locations, &dto.SubLevelLocation{
				ID:                v.ID,
				InternationalName: v.InternationalName,
				LocalizedName:     v.LocalizedName,
				ParentID:          v.ParentID,
			})
		}
		res = append(res, &dto.DeliveryAddressLog{
			ID:                   log.ID.String(),
			CartID:               log.CartID,
			Address1:             log.Address.Address1,
			Address2:             log.Address.Address2,
			PostalCode:           log.Address.PostalCode,
			UnitNumber:           log.Address.UnitNumber,
			SubLevelLocations:    locations,
			RecipientName:        log.RecipientName,
			RecipientPhoneNumber: log.RecipientPhoneNumber,
			CreatedAt:            log.CreatedAt,
			Version:              log.Version,
		})
	}
	return res
}
