package main

import (
	"database/sql"
	"fmt"
	"net/http"
	"strconv"
	"strings"
	"time"

	"github.com/labstack/echo/v4"
)

func (a *App) handleScoreAdvice(c echo.Context) error {
	stage, err := validateStage(c.Param("stage"))
	if err != nil {
		return writeError(c, http.StatusBadRequest, err.Error())
	}

	playerID, err := strconv.Atoi(c.Param("id"))
	if err != nil {
		return writeError(c, http.StatusBadRequest, "invalid player id")
	}

	if strings.TrimSpace(a.cfg.GeminiAPIKey) == "" {
		return writeError(c, http.StatusServiceUnavailable, "gemini api key is not configured")
	}

	proofImageData, err := a.loadScoreProofImage(stage, playerID)
	if err != nil {
		if err == sql.ErrNoRows {
			return writeError(c, http.StatusBadRequest, "no proof image found for this score")
		}
		return writeError(c, http.StatusInternalServerError, fmt.Sprintf("load proof image: %v", err))
	}
	if strings.TrimSpace(proofImageData) == "" {
		return writeError(c, http.StatusBadRequest, "no proof image found for this score")
	}

	currentScore, _ := a.loadCurrentScore(stage, playerID)

	advice, err := a.generateScoreAdvice(stage, playerID, proofImageData, currentScore)
	if err != nil {
		return writeError(c, http.StatusBadGateway, err.Error())
	}

	return c.JSON(http.StatusOK, advice)
}

func (a *App) loadScoreProofImage(stage string, playerID int) (string, error) {
	var imageData string
	err := a.db.QueryRow(`SELECT image_data FROM score_attachments WHERE stage = ? AND player_id = ?`, stage, playerID).Scan(&imageData)
	if err != nil {
		return "", err
	}
	return imageData, nil
}

func (a *App) loadCurrentScore(stage string, playerID int) (int, error) {
	var score int
	err := a.db.QueryRow(`SELECT score FROM scores WHERE stage = ? AND player_id = ?`, stage, playerID).Scan(&score)
	if err != nil {
		if err == sql.ErrNoRows {
			return 0, nil
		}
		return 0, err
	}
	return score, nil
}

func (a *App) buildAdviceResponse(stage string, playerID int, raw scoreAdviceModelResponse) ScoreAdviceResponse {
	advised := clampInt(raw.AdvisedScore, 0, 9999)
	reason := strings.TrimSpace(raw.Reason)
	if reason == "" {
		reason = "AI estimated the score from visible impacts."
	}

	return ScoreAdviceResponse{
		Stage:        stage,
		PlayerID:     playerID,
		AdvisedScore: advised,
		Reason:       reason,
		GeneratedAt:  time.Now().UTC().Format(time.RFC3339),
	}
}

func clampInt(value, min, max int) int {
	if value < min {
		return min
	}
	if value > max {
		return max
	}
	return value
}
