// Package render turns a backend push event into a localized Telegram message with
// a Mini App deep-link. Only the out-of-app push set is rendered (your_turn, game_over,
// nudge, match_found, and the invitation / friend_request notify sub-kinds); every other
// kind returns ok=false so the connector skips it (the in-app stream still carries
// it).
package render

import (
	"fmt"

	"scrabble/pkg/fbs/scrabblefb"
	"scrabble/platform/telegram/internal/deeplink"
)

// Message is a rendered notification: the body text, the launch-button label and
// the deep-link start parameter (empty opens the lobby).
type Message struct {
	Text       string
	ButtonText string
	StartParam string
}

// Render builds the localized message for a backend push event of the given kind
// and FlatBuffers payload, in language lang ("ru" selects Russian; anything else
// is English). It returns ok=false for a kind that is not delivered out-of-app.
func Render(kind string, payload []byte, lang string) (Message, bool) {
	p := english
	if lang == "ru" {
		p = russian
	}
	switch kind {
	case "your_turn":
		ev := scrabblefb.GetRootAsYourTurnEvent(payload, 0)
		return Message{Text: yourTurnText(ev, p), ButtonText: p.openGame, StartParam: deeplink.Game(string(ev.GameId()))}, true
	case "game_over":
		ev := scrabblefb.GetRootAsGameOverEvent(payload, 0)
		return Message{Text: gameOverText(ev, p), ButtonText: p.openGame, StartParam: deeplink.Game(string(ev.GameId()))}, true
	case "nudge":
		ev := scrabblefb.GetRootAsNudgeEvent(payload, 0)
		return Message{Text: nudgeText(ev, p), ButtonText: p.openGame, StartParam: deeplink.Game(string(ev.GameId()))}, true
	case "match_found":
		ev := scrabblefb.GetRootAsMatchFoundEvent(payload, 0)
		return Message{Text: p.matchFound, ButtonText: p.openGame, StartParam: deeplink.Game(string(ev.GameId()))}, true
	case "notify":
		ev := scrabblefb.GetRootAsNotificationEvent(payload, 0)
		switch string(ev.Kind()) {
		case "invitation":
			return Message{Text: p.invitation, ButtonText: p.open}, true
		case "friend_request":
			return Message{Text: p.friendRequest, ButtonText: p.open}, true
		}
	}
	return Message{}, false
}

// yourTurnText renders the enriched "your turn" body, voiced as the opponent who
// just moved ("{name}: my move — «WORD». Score 120:95"). It falls back to the plain phrase when
// the opponent name is missing (an older backend, or an unresolved name).
func yourTurnText(ev *scrabblefb.YourTurnEvent, p phrases) string {
	name := string(ev.OpponentName())
	if name == "" {
		return p.yourTurn
	}
	switch string(ev.LastAction()) {
	case "play":
		if word := string(ev.LastWord()); word != "" {
			return fmt.Sprintf(p.yourTurnPlay, name, word, string(ev.ScoreLine()))
		}
		return fmt.Sprintf(p.yourTurnMoved, name)
	case "exchange":
		return fmt.Sprintf(p.yourTurnExchange, name)
	case "pass":
		return fmt.Sprintf(p.yourTurnPass, name)
	default:
		return p.yourTurn
	}
}

// nudgeText renders the nudge body, voiced as the sender who is waiting ("{name}: Waiting for
// your move 🤭"). It falls back to the plain phrase when the sender name is missing (an older
// backend, or an unresolved name).
func nudgeText(ev *scrabblefb.NudgeEvent, p phrases) string {
	if name := string(ev.SenderName()); name != "" {
		return fmt.Sprintf(p.nudgeBy, name)
	}
	return p.nudge
}

// gameOverText renders the "game over" body from the recipient's own perspective.
func gameOverText(ev *scrabblefb.GameOverEvent, p phrases) string {
	score := string(ev.ScoreLine())
	switch string(ev.Result()) {
	case "won":
		return fmt.Sprintf(p.gameOverWon, score)
	case "lost":
		return fmt.Sprintf(p.gameOverLost, score)
	default:
		return fmt.Sprintf(p.gameOverDraw, score)
	}
}

// phrases is one language's message catalog. The yourTurn*/gameOver*/nudgeBy entries are fmt
// format strings: yourTurnPlay takes (name, word, scoreLine); yourTurnExchange/Pass/Moved and
// nudgeBy take (name); the gameOver* entries take (scoreLine).
type phrases struct {
	yourTurn         string
	yourTurnPlay     string
	yourTurnExchange string
	yourTurnPass     string
	yourTurnMoved    string
	gameOverWon      string
	gameOverLost     string
	gameOverDraw     string
	nudge            string
	nudgeBy          string
	matchFound       string
	invitation       string
	friendRequest    string
	openGame         string
	open             string
}

var english = phrases{
	yourTurn:         "It's your turn.",
	yourTurnPlay:     "%s: my move — «%s». Score %s",
	yourTurnExchange: "%s: swapping tiles, your turn.",
	yourTurnPass:     "%s: passing, your turn.",
	yourTurnMoved:    "%s moved, your turn.",
	gameOverWon:      "Game over - 🏆 you won! Score %s",
	gameOverLost:     "Game over - you lost. Score %s",
	gameOverDraw:     "Game over - a draw. Score %s",
	nudge:            "You were nudged — it's your turn.",
	nudgeBy:          "%s: Waiting for your move 🤭",
	matchFound:       "Your game is ready.",
	invitation:       "You have a new game invitation.",
	friendRequest:    "You have a new friend request.",
	openGame:         "Open game",
	open:             "Open",
}

var russian = phrases{
	yourTurn:         "Ваш ход.",
	yourTurnPlay:     "%s: мой ход — «%s». Счёт %s",
	yourTurnExchange: "%s: меняю фишки, ваш ход.",
	yourTurnPass:     "%s: пропускаю ход, ваш ход.",
	yourTurnMoved:    "%s сходил(а), ваш ход.",
	gameOverWon:      "Игра окончена — 🏆 Вы выиграли! Счёт %s",
	gameOverLost:     "Игра окончена — Вы проиграли. Счёт %s",
	gameOverDraw:     "Игра окончена — ничья. Счёт %s",
	nudge:            "Вас поторопили — ваш ход.",
	nudgeBy:          "%s: Жду Вашего хода 🤭",
	matchFound:       "Игра найдена.",
	invitation:       "Вас пригласили в игру.",
	friendRequest:    "Вам пришла заявка в друзья.",
	openGame:         "Открыть игру",
	open:             "Открыть",
}
