package resource

import (
	"context"
	"encoding/json"
	"fmt"
	"strings"

	activityv1 "hyapp.local/api/proto/activity/v1"
	walletv1 "hyapp.local/api/proto/wallet/v1"
)

const (
	resourceGrantNoticeTitle = "System Gift"
	resourceGrantNoticeBody  = "You received the following system-granted resources."
)

type resourceNoticeSnapshot struct {
	ResourceType string
	Name         string
	AssetURL     string
	PreviewURL   string
	MetadataJSON string
}

func (h *Handler) createResourceGrantNotice(ctx context.Context, requestID string, appCode string, grant *walletv1.ResourceGrant) error {
	if grant == nil {
		return fmt.Errorf("resource grant response is empty")
	}
	return h.createResourceBatchGrantNotice(ctx, requestID, appCode, grant.GetGrantId(), grant.GetTargetUserId(), []*walletv1.ResourceGrant{grant})
}

func (h *Handler) createResourceBatchGrantNotice(ctx context.Context, requestID string, appCode string, commandID string, targetUserID int64, grants []*walletv1.ResourceGrant) error {
	if h.activity == nil {
		// Tests and isolated local handlers may omit integrations; the production constructor always wires activity-service.
		return nil
	}
	snapshots, err := resourceNoticeSnapshots(grants)
	if err != nil {
		return err
	}
	body := resourceGrantNoticeBody
	imageURLs := resourceNoticeImageURLs(snapshots)
	if len(grants) == 1 && len(snapshots) == 1 && strings.EqualFold(strings.TrimSpace(snapshots[0].ResourceType), resourceTypeVIPTrialCard) {
		level := vipTrialLevel(snapshots[0].MetadataJSON)
		body = "You received a VIP trial card."
		if level > 0 {
			body = fmt.Sprintf("You received a VIP%d trial card.", level)
		}
		imageURLs = nil
	}
	producerEventID := "resource_grant:" + strings.TrimSpace(commandID)
	_, err = h.activity.CreateInboxMessage(ctx, &activityv1.CreateInboxMessageRequest{
		Meta:              &activityv1.RequestMeta{RequestId: strings.TrimSpace(requestID), Caller: "admin-server", AppCode: strings.TrimSpace(appCode)},
		TargetUserId:      targetUserID,
		Producer:          "admin-server",
		ProducerEventId:   producerEventID,
		ProducerEventType: "AdminResourceGranted",
		MessageType:       "system",
		AggregateType:     "resource_grant",
		AggregateId:       strings.TrimSpace(commandID),
		Title:             resourceGrantNoticeTitle,
		Summary:           body,
		Body:              body,
		ImageUrl:          firstNoticeImageURL(imageURLs),
		ImageUrls:         imageURLs,
	})
	return err
}

func resourceNoticeSnapshots(grants []*walletv1.ResourceGrant) ([]resourceNoticeSnapshot, error) {
	result := make([]resourceNoticeSnapshot, 0)
	for _, grant := range grants {
		if grant == nil {
			continue
		}
		for _, item := range grant.GetItems() {
			raw := strings.TrimSpace(item.GetResourceSnapshotJson())
			if raw == "" || raw == "{}" {
				continue
			}
			var snapshot resourceNoticeSnapshot
			if err := json.Unmarshal([]byte(raw), &snapshot); err != nil {
				return nil, fmt.Errorf("decode granted resource snapshot: %w", err)
			}
			result = append(result, snapshot)
		}
	}
	return result, nil
}

func resourceNoticeImageURLs(snapshots []resourceNoticeSnapshot) []string {
	result := make([]string, 0, len(snapshots))
	for _, snapshot := range snapshots {
		url := strings.TrimSpace(snapshot.PreviewURL)
		if url == "" {
			url = strings.TrimSpace(snapshot.AssetURL)
		}
		if url == "" {
			continue
		}
		result = append(result, url)
	}
	return result
}

func vipTrialLevel(metadataJSON string) int32 {
	var metadata struct {
		VIPLevel int32 `json:"vip_level"`
	}
	if err := json.Unmarshal([]byte(strings.TrimSpace(metadataJSON)), &metadata); err != nil {
		return 0
	}
	return metadata.VIPLevel
}

func firstNoticeImageURL(imageURLs []string) string {
	if len(imageURLs) == 0 {
		return ""
	}
	return imageURLs[0]
}
