package usecase

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

	app "haixun-backend/internal/library/errors"
	"haixun-backend/internal/library/errors/code"
	libthreads "haixun-backend/internal/library/threadsapi"
	domusecase "haixun-backend/internal/model/threads_account/domain/usecase"
)

func (u *threadsAccountUseCase) RunAPIPlayground(
	ctx context.Context,
	tenantID, ownerUID, accountID string,
	req domusecase.APIPlaygroundRequest,
) (*domusecase.APIPlaygroundResult, error) {
	account, err := u.assertOwned(ctx, tenantID, ownerUID, accountID)
	if err != nil {
		return nil, err
	}
	token, err := u.ResolveAccountAPIAccessToken(ctx, tenantID, ownerUID, accountID)
	if err != nil {
		return nil, err
	}
	client := libthreads.NewClient(token)
	if !client.Enabled() {
		return nil, app.For(code.ThreadsAccount).InputMissingRequired("Threads API 未連線")
	}

	action := strings.TrimSpace(strings.ToLower(req.Action))
	if action == "" {
		return nil, app.For(code.ThreadsAccount).InputMissingRequired("action 為必填")
	}

	userID := strings.TrimSpace(account.ThreadsUserID)
	if userID == "" {
		if profile, perr := libthreads.GetMeProfile(ctx, token); perr == nil && profile != nil {
			userID = profile.ID.String()
		}
	}

	limit := req.Limit
	if limit <= 0 {
		limit = 10
	}
	if limit > 50 {
		limit = 50
	}

	result := &domusecase.APIPlaygroundResult{Action: action}
	var payload any
	var runErr error

	switch action {
	case "me":
		payload, runErr = libthreads.GetMeProfile(ctx, token)
	case "user_threads":
		if userID == "" {
			runErr = fmt.Errorf("缺少 threads_user_id")
		} else {
			payload, runErr = client.UserThreads(ctx, userID, limit)
		}
	case "keyword_search":
		q := strings.TrimSpace(req.Query)
		if q == "" {
			runErr = fmt.Errorf("query 為必填")
		} else {
			searchType := strings.TrimSpace(req.SearchType)
			if searchType == "" {
				searchType = "TOP"
			}
			payload, runErr = client.KeywordSearch(ctx, libthreads.KeywordSearchOptions{
				Query: q, Limit: limit, SearchType: searchType,
			})
		}
	case "profile_lookup":
		u := strings.TrimPrefix(strings.TrimSpace(req.Username), "@")
		if u == "" {
			runErr = fmt.Errorf("username 為必填")
		} else {
			payload, runErr = client.ProfileLookup(ctx, u)
		}
	case "mentions":
		if userID == "" {
			runErr = fmt.Errorf("缺少 threads_user_id")
		} else {
			payload, runErr = client.UserMentions(ctx, userID, limit)
		}
	case "insights":
		if userID == "" {
			runErr = fmt.Errorf("缺少 threads_user_id")
		} else {
			payload, runErr = client.UserInsights(ctx, userID, nil)
		}
	case "location_search":
		q := strings.TrimSpace(req.LocationQuery)
		if q == "" {
			q = strings.TrimSpace(req.Query)
		}
		if q == "" {
			runErr = fmt.Errorf("location 查詢字串為必填")
		} else {
			payload, runErr = client.LocationSearch(ctx, q, limit)
		}
	case "media_replies", "media_conversation":
		mid := strings.TrimSpace(req.MediaID)
		if mid == "" {
			runErr = fmt.Errorf("media_id 為必填")
		} else {
			if limit < 30 {
				limit = 30
			}
			payload, runErr = client.MediaConversation(ctx, mid, limit)
		}
	case "media_stats":
		mid := strings.TrimSpace(req.MediaID)
		if mid == "" {
			runErr = fmt.Errorf("media_id 為必填")
		} else {
			payload, runErr = client.GetMediaStats(ctx, mid)
		}
	case "media_detail":
		mid := strings.TrimSpace(req.MediaID)
		if mid == "" {
			runErr = fmt.Errorf("media_id 為必填")
		} else {
			payload, runErr = client.GetMediaDetail(ctx, mid)
		}
	case "media_insights":
		mid := strings.TrimSpace(req.MediaID)
		if mid == "" {
			runErr = fmt.Errorf("media_id 為必填")
		} else {
			payload, runErr = client.MediaInsights(ctx, mid, nil)
		}
	case "publish_text":
		text := strings.TrimSpace(req.Text)
		if userID == "" || text == "" {
			runErr = fmt.Errorf("threads_user_id 與 text 為必填")
		} else {
			payload, runErr = libthreads.PublishText(ctx, libthreads.PublishTextInput{
				ThreadsUserID: userID, AccessToken: token, Text: text,
			})
		}
	case "prime_reply_target":
		replyTo := strings.TrimSpace(req.ReplyToID)
		permalink := strings.TrimSpace(req.Permalink)
		if replyTo == "" || permalink == "" {
			runErr = fmt.Errorf("reply_to_id 與 permalink 為必填")
		} else {
			hint := strings.TrimSpace(req.HintText)
			if hint == "" {
				hint = strings.TrimSpace(req.Query)
			}
			if primeErr := client.PrimeReplyTargetForPublish(ctx, libthreads.ResolveReplyMediaInput{
				ExternalID: replyTo,
				Permalink:  permalink,
				HintText:   hint,
			}, replyTo); primeErr != nil {
				runErr = primeErr
			} else {
				payload = map[string]string{"primed": replyTo}
			}
		}
	case "publish_reply":
		text := strings.TrimSpace(req.Text)
		replyTo := strings.TrimSpace(req.ReplyToID)
		if userID == "" || text == "" || replyTo == "" {
			runErr = fmt.Errorf("threads_user_id、reply_to_id、text 為必填")
		} else {
			permalink := strings.TrimSpace(req.Permalink)
			if permalink != "" && !req.SkipPrime {
				hint := strings.TrimSpace(req.HintText)
				if hint == "" {
					hint = strings.TrimSpace(req.Query)
				}
				if primeErr := client.PrimeReplyTargetForPublish(ctx, libthreads.ResolveReplyMediaInput{
					ExternalID: replyTo,
					Permalink:  permalink,
					HintText:   hint,
				}, replyTo); primeErr != nil {
					runErr = fmt.Errorf("回覆他人貼文前需先透過 keyword_search 註冊目標：%w", primeErr)
				}
			}
			if runErr == nil {
				payload, runErr = libthreads.PublishReply(ctx, libthreads.PublishReplyInput{
					ThreadsUserID: userID, AccessToken: token, ReplyToID: replyTo, Text: text,
				})
			}
		}
	case "delete_media":
		mid := strings.TrimSpace(req.MediaID)
		if mid == "" {
			runErr = fmt.Errorf("media_id 為必填")
		} else {
			runErr = client.DeleteMedia(ctx, mid)
			if runErr == nil {
				payload = map[string]string{"deleted": mid}
			}
		}
	case "hide_reply":
		rid := strings.TrimSpace(req.ReplyID)
		if rid == "" {
			runErr = fmt.Errorf("reply_id 為必填")
		} else {
			runErr = client.HideReply(ctx, rid, req.Hide)
			if runErr == nil {
				payload = map[string]any{"reply_id": rid, "hide": req.Hide}
			}
		}
	case "share_to_instagram":
		mid := strings.TrimSpace(req.MediaID)
		if mid == "" {
			runErr = fmt.Errorf("media_id 為必填")
		} else {
			runErr = client.ShareToInstagram(ctx, mid)
			if runErr == nil {
				payload = map[string]string{"crossposted": mid}
			}
		}
	case "refresh_token":
		refreshed, rerr := libthreads.RefreshAccessToken(ctx, token)
		if rerr != nil {
			runErr = rerr
		} else {
			expiresAt := int64(0)
			if refreshed.ExpiresIn >= 300 {
				expiresAt = libthreads.NsFromNow(refreshed.ExpiresIn)
			}
			if _, serr := u.secretsRepo.SaveAPIAccessToken(ctx, account.ID, refreshed.AccessToken, expiresAt); serr != nil {
				runErr = serr
			} else {
				payload = map[string]any{
					"expires_in": refreshed.ExpiresIn,
					"saved":      true,
				}
			}
		}
	default:
		return nil, app.For(code.ThreadsAccount).InputInvalidFormat("不支援的 action: " + action)
	}

	if runErr != nil {
		result.Ok = false
		result.Message = runErr.Error()
		if libthreads.IsPermissionError(runErr) {
			result.Message += "（請確認 Meta App 已授權此 scope，且帳號在測試人員名單）"
		}
		return result, nil
	}

	raw, err := json.Marshal(payload)
	if err != nil {
		return nil, err
	}
	result.Ok = true
	result.Message = "ok"
	result.Data = raw
	return result, nil
}
