package nofxos

import (
	"encoding/json"
	"fmt"
	"log"
	"strings"
	"time"
)

// NetFlowPosition represents fund flow data for a single coin
type NetFlowPosition struct {
	Rank   int     `json:"rank"`
	Symbol string  `json:"symbol"`
	Amount float64 `json:"amount"` // Fund flow amount in USDT (positive=inflow, negative=outflow)
	Price  float64 `json:"price"`
}

// NetFlowResponse is the API response structure
type NetFlowResponse struct {
	Success bool `json:"success"`
	Data    struct {
		Netflows  []NetFlowPosition `json:"netflows"`
		Count     int               `json:"count"`
		Type      string            `json:"type"`  // institution or personal
		Trade     string            `json:"trade"` // futures or spot
		TimeRange string            `json:"time_range"`
		RankType  string            `json:"rank_type"` // top or low
		Limit     int               `json:"limit"`
	} `json:"data"`
}

// NetFlowRankingData contains institution and personal fund flow rankings
type NetFlowRankingData struct {
	Duration             string            `json:"duration"`
	TimeRange            string            `json:"time_range"`
	InstitutionFutureTop []NetFlowPosition `json:"institution_future_top"`
	InstitutionFutureLow []NetFlowPosition `json:"institution_future_low"`
	PersonalFutureTop    []NetFlowPosition `json:"personal_future_top"`
	PersonalFutureLow    []NetFlowPosition `json:"personal_future_low"`
	FetchedAt            time.Time         `json:"fetched_at"`
}

// GetNetFlowRanking retrieves NetFlow ranking data (institution/personal, top/low)
func (c *Client) GetNetFlowRanking(duration string, limit int) (*NetFlowRankingData, error) {
	if duration == "" {
		duration = "1h"
	}
	if limit <= 0 {
		limit = 10
	}

	result := &NetFlowRankingData{
		Duration:  duration,
		FetchedAt: time.Now(),
	}

	// Fetch institution futures top (inflow)
	positions, timeRange, err := c.fetchNetFlowRanking("top", duration, limit, "institution", "future")
	if err != nil {
		log.Printf("⚠️  Failed to fetch institution future inflow ranking: %v", err)
	} else {
		result.InstitutionFutureTop = positions
		result.TimeRange = timeRange
	}

	// Fetch institution futures low (outflow)
	positions, _, err = c.fetchNetFlowRanking("low", duration, limit, "institution", "future")
	if err != nil {
		log.Printf("⚠️  Failed to fetch institution future outflow ranking: %v", err)
	} else {
		result.InstitutionFutureLow = positions
	}

	// Fetch personal futures top (retail inflow)
	positions, _, err = c.fetchNetFlowRanking("top", duration, limit, "personal", "future")
	if err != nil {
		log.Printf("⚠️  Failed to fetch personal future inflow ranking: %v", err)
	} else {
		result.PersonalFutureTop = positions
	}

	// Fetch personal futures low (retail outflow)
	positions, _, err = c.fetchNetFlowRanking("low", duration, limit, "personal", "future")
	if err != nil {
		log.Printf("⚠️  Failed to fetch personal future outflow ranking: %v", err)
	} else {
		result.PersonalFutureLow = positions
	}

	log.Printf("✓ Fetched NetFlow ranking data: inst_in=%d, inst_out=%d, retail_in=%d, retail_out=%d (duration: %s)",
		len(result.InstitutionFutureTop), len(result.InstitutionFutureLow),
		len(result.PersonalFutureTop), len(result.PersonalFutureLow), duration)

	return result, nil
}

func (c *Client) fetchNetFlowRanking(rankType, duration string, limit int, flowType, trade string) ([]NetFlowPosition, string, error) {
	endpoint := fmt.Sprintf("/api/netflow/%s-ranking?limit=%d&duration=%s&type=%s&trade=%s",
		rankType, limit, duration, flowType, trade)

	body, err := c.doRequest(endpoint)
	if err != nil {
		return nil, "", fmt.Errorf("request failed: %w", err)
	}

	var response NetFlowResponse
	if err := json.Unmarshal(body, &response); err != nil {
		return nil, "", fmt.Errorf("JSON parsing failed: %w", err)
	}

	if !response.Success {
		return nil, "", fmt.Errorf("API returned failure status")
	}

	return response.Data.Netflows, response.Data.TimeRange, nil
}

// FormatNetFlowRankingForAI formats NetFlow ranking data for AI consumption
func FormatNetFlowRankingForAI(data *NetFlowRankingData, lang Language) string {
	if data == nil {
		return ""
	}

	if lang == LangChinese {
		return formatNetFlowRankingZH(data)
	}
	return formatNetFlowRankingEN(data)
}

func formatNetFlowRankingZH(data *NetFlowRankingData) string {
	var sb strings.Builder

	sb.WriteString(fmt.Sprintf("## Net Flow Ranking (%s)\n\n", data.Duration))

	// Institution inflow
	if len(data.InstitutionFutureTop) > 0 {
		sb.WriteString("### Institution Inflow Ranking\n")
		sb.WriteString("Smart Money buy signal:\n\n")
		sb.WriteString("| Rank | Symbol | Inflow Amount(USDT) | Price |\n")
		sb.WriteString("|------|------|----------------|------|\n")
		for _, pos := range data.InstitutionFutureTop {
			sb.WriteString(fmt.Sprintf("| %d | %s | %s | $%.4f |\n",
				pos.Rank, pos.Symbol, formatValue(pos.Amount), pos.Price))
		}
		sb.WriteString("\n")
	}

	// Institution outflow
	if len(data.InstitutionFutureLow) > 0 {
		sb.WriteString("### Institution Outflow Ranking\n")
		sb.WriteString("Smart Money sell signal:\n\n")
		sb.WriteString("| Rank | Symbol | Outflow Amount(USDT) | Price |\n")
		sb.WriteString("|------|------|----------------|------|\n")
		for _, pos := range data.InstitutionFutureLow {
			sb.WriteString(fmt.Sprintf("| %d | %s | %s | $%.4f |\n",
				pos.Rank, pos.Symbol, formatValue(pos.Amount), pos.Price))
		}
		sb.WriteString("\n")
	}

	// Retail flow summary
	if len(data.PersonalFutureTop) > 0 || len(data.PersonalFutureLow) > 0 {
		sb.WriteString("### Retail Capital Movement\n")
		if len(data.PersonalFutureTop) > 0 {
			sb.WriteString("Retail buy: ")
			for i, pos := range data.PersonalFutureTop {
				if i >= 3 {
					break
				}
				if i > 0 {
					sb.WriteString(", ")
				}
				sb.WriteString(fmt.Sprintf("%s(%s)", pos.Symbol, formatValue(pos.Amount)))
			}
			sb.WriteString("\n")
		}
		if len(data.PersonalFutureLow) > 0 {
			sb.WriteString("Retail sell: ")
			for i, pos := range data.PersonalFutureLow {
				if i >= 3 {
					break
				}
				if i > 0 {
					sb.WriteString(", ")
				}
				sb.WriteString(fmt.Sprintf("%s(%s)", pos.Symbol, formatValue(pos.Amount)))
			}
			sb.WriteString("\n")
		}
		sb.WriteString("\n")
	}

	sb.WriteString("**Interpretation**: Institution buy + Retail sell = strongly bullish | Institution sell + Retail buy = strongly bearish\n\n")
	return sb.String()
}

func formatNetFlowRankingEN(data *NetFlowRankingData) string {
	var sb strings.Builder

	sb.WriteString(fmt.Sprintf("## Fund Flow Ranking (%s)\n\n", data.Duration))

	// Institution inflow
	if len(data.InstitutionFutureTop) > 0 {
		sb.WriteString("### Institution Inflow\n")
		sb.WriteString("Smart Money buying signals:\n\n")
		sb.WriteString("| Rank | Symbol | Inflow (USDT) | Price |\n")
		sb.WriteString("|------|--------|---------------|-------|\n")
		for _, pos := range data.InstitutionFutureTop {
			sb.WriteString(fmt.Sprintf("| %d | %s | %s | $%.4f |\n",
				pos.Rank, pos.Symbol, formatValue(pos.Amount), pos.Price))
		}
		sb.WriteString("\n")
	}

	// Institution outflow
	if len(data.InstitutionFutureLow) > 0 {
		sb.WriteString("### Institution Outflow\n")
		sb.WriteString("Smart Money selling signals:\n\n")
		sb.WriteString("| Rank | Symbol | Outflow (USDT) | Price |\n")
		sb.WriteString("|------|--------|----------------|-------|\n")
		for _, pos := range data.InstitutionFutureLow {
			sb.WriteString(fmt.Sprintf("| %d | %s | %s | $%.4f |\n",
				pos.Rank, pos.Symbol, formatValue(pos.Amount), pos.Price))
		}
		sb.WriteString("\n")
	}

	// Retail flow summary
	if len(data.PersonalFutureTop) > 0 || len(data.PersonalFutureLow) > 0 {
		sb.WriteString("### Retail Flow\n")
		if len(data.PersonalFutureTop) > 0 {
			sb.WriteString("Retail buying: ")
			for i, pos := range data.PersonalFutureTop {
				if i >= 3 {
					break
				}
				if i > 0 {
					sb.WriteString(", ")
				}
				sb.WriteString(fmt.Sprintf("%s(%s)", pos.Symbol, formatValue(pos.Amount)))
			}
			sb.WriteString("\n")
		}
		if len(data.PersonalFutureLow) > 0 {
			sb.WriteString("Retail selling: ")
			for i, pos := range data.PersonalFutureLow {
				if i >= 3 {
					break
				}
				if i > 0 {
					sb.WriteString(", ")
				}
				sb.WriteString(fmt.Sprintf("%s(%s)", pos.Symbol, formatValue(pos.Amount)))
			}
			sb.WriteString("\n")
		}
		sb.WriteString("\n")
	}

	sb.WriteString("**Key**: Institution buy + Retail sell = Strong bullish | Institution sell + Retail buy = Strong bearish\n\n")
	return sb.String()
}
