package dispute

import (
	"context"
	"encoding/json"
	"errors"
	"sort"
	"strconv"
	"time"

	"juwan-backend/app/dispute/api/internal/svc"
	"juwan-backend/app/dispute/api/internal/types"
	"juwan-backend/app/dispute/rpc/disputeservice"
	"juwan-backend/app/order/rpc/orderservice"
	"juwan-backend/app/player/rpc/playerservice"
)

func formatUnix(ts int64) string {
	if ts <= 0 {
		return ""
	}
	return time.Unix(ts, 0).UTC().Format(time.RFC3339)
}

func toAPIDispute(d *disputeservice.Disputes) types.Dispute {
	return types.Dispute{
		Id:                 d.GetId(),
		OrderId:            d.GetOrderId(),
		InitiatorId:        d.GetInitiatorId(),
		InitiatorName:      d.GetInitiatorName(),
		RespondentId:       d.GetRespondentId(),
		Reason:             d.GetReason(),
		Evidence:           d.GetEvidence(),
		Status:             d.GetStatus(),
		Result:             d.GetResult(),
		RespondentReason:   d.GetRespondentReason(),
		RespondentEvidence: d.GetRespondentEvidence(),
		AppealReason:       d.GetAppealReason(),
		AppealedAt:         formatUnix(d.GetAppealedAt()),
		ResolvedBy:         d.GetResolvedBy(),
		ResolvedAt:         formatUnix(d.GetResolvedAt()),
		CreatedAt:          formatUnix(d.GetCreatedAt()),
		UpdatedAt:          formatUnix(d.GetUpdatedAt()),
	}
}

func mergeDisputes(groups ...[]*disputeservice.Disputes) []*disputeservice.Disputes {
	seen := make(map[int64]struct{})
	items := make([]*disputeservice.Disputes, 0)
	for _, group := range groups {
		for _, item := range group {
			if item == nil {
				continue
			}
			if _, ok := seen[item.GetId()]; ok {
				continue
			}
			seen[item.GetId()] = struct{}{}
			items = append(items, item)
		}
	}
	sort.Slice(items, func(i, j int) bool {
		if items[i].GetCreatedAt() == items[j].GetCreatedAt() {
			return items[i].GetId() > items[j].GetId()
		}
		return items[i].GetCreatedAt() > items[j].GetCreatedAt()
	})
	return items
}

func paginateDisputes(items []*disputeservice.Disputes, offset int64, limit int64) []*disputeservice.Disputes {
	if offset < 0 {
		offset = 0
	}
	if limit <= 0 {
		limit = 20
	}
	start := int(offset)
	if start >= len(items) {
		return []*disputeservice.Disputes{}
	}
	end := start + int(limit)
	if end > len(items) {
		end = len(items)
	}
	return items[start:end]
}

func actorName(uid int64) string {
	return strconv.FormatInt(uid, 10)
}

func detailsJSON(values map[string]any) string {
	if len(values) == 0 {
		return "{}"
	}
	b, err := json.Marshal(values)
	if err != nil {
		return "{}"
	}
	return string(b)
}

func orderParticipantUserIDs(ctx context.Context, svcCtx *svc.ServiceContext, order *orderservice.Orders) (int64, int64, error) {
	if order == nil {
		return 0, 0, errors.New("order not found")
	}
	playerResp, err := svcCtx.PlayerRpc.GetPlayersById(ctx, &playerservice.GetPlayersByIdReq{Id: order.GetPlayerId()})
	if err != nil {
		return 0, 0, err
	}
	player := playerResp.GetPlayers()
	if player == nil || player.GetUserId() <= 0 {
		return 0, 0, errors.New("player not found")
	}
	return order.GetConsumerId(), player.GetUserId(), nil
}
