package users_service

import (
	"fmt"
	"html"
	"strings"
)

// Шаблоны писем сервиса. Структура по базе знаний копирайтера (email.md):
// приветствие → контекст («почему это письмо») → ценность (данные для входа)
// → CTA → подпись → P.S. Письма транзакционные, но по форме — «человек
// человеку»: Gmail и другие почтовики агрессивнее фильтруют короткие
// «роботные» письма без структуры.
//
// Каждое письмо формируется в двух версиях: text/plain (для старых клиентов
// и фильтров) и text/html (для отображения); sender собирает их в
// multipart/alternative.

const (
	// welcomeSubject — тема письма о регистрации: конкретика без КАПСА и
	// кликбейта, до 50 символов (видно на мобильных целиком).
	welcomeSubject = "Твой доступ к «Вечернему детективу»"
	// resetSubject — тема письма о сбросе пароля.
	resetSubject = "Новый пароль для «Вечернего детектива»"
)

// welcomePlain возвращает текстовую версию письма о регистрации.
func welcomePlain(username, email, password, loginURL string) string {
	var b strings.Builder
	b.WriteString(greeting(username))
	b.WriteString("\n\n")
	b.WriteString("Твоя регистрация в «Вечернем детективе» прошла. Данные для входа:\n\n")
	b.WriteString("  Логин: ")
	b.WriteString(email)
	b.WriteString("\n")
	b.WriteString("  Пароль: ")
	b.WriteString(password)
	b.WriteString("\n\n")
	if loginURL != "" {
		b.WriteString("Войти в игру: ")
		b.WriteString(loginURL)
		b.WriteString("\n\n")
	}
	b.WriteString("Если ты не регистрировался — просто проигнорируй это письмо.\n\n")
	b.WriteString("— Команда «Вечернего детектива»\n")
	b.WriteString("P.S. Сохрани это письмо: пароль понадобится для входа.")
	return sanitizeLine(b.String())
}

// welcomeHTML возвращает HTML-версию письма о регистрации.
func welcomeHTML(username, email, password, loginURL string) string {
	var content strings.Builder
	content.WriteString("<p>Привет, <strong>")
	content.WriteString(html.EscapeString(username))
	content.WriteString("</strong>!</p>\n")
	content.WriteString("<p>Твоя регистрация в «Вечернем детективе» прошла. Данные для входа:</p>\n")
	content.WriteString(credentialsBlockHTML(email, password))
	if loginURL != "" {
		content.WriteString(buttonHTML(loginURL, "Войти в игру"))
	}
	content.WriteString("<p style=\"color:#777777; font-size:13px;\">Если ты не регистрировался — просто проигнорируй это письмо.</p>")
	return wrapHTML(content.String())
}

// resetPlain возвращает текстовую версию письма о сбросе пароля.
func resetPlain(username, email, password, loginURL string) string {
	var b strings.Builder
	b.WriteString(greeting(username))
	b.WriteString("\n\n")
	b.WriteString("Ты запросил сброс пароля в «Вечернем детективе». Новый пароль для входа:\n\n")
	b.WriteString("  Логин: ")
	b.WriteString(email)
	b.WriteString("\n")
	b.WriteString("  Пароль: ")
	b.WriteString(password)
	b.WriteString("\n\n")
	if loginURL != "" {
		b.WriteString("Войти в игру: ")
		b.WriteString(loginURL)
		b.WriteString("\n\n")
	}
	b.WriteString("Никому не сообщай пароль и не пересылай это письмо.\n")
	b.WriteString("Если это был не ты — ответь на это письмо: мы поможем защитить аккаунт.\n\n")
	b.WriteString("— Команда «Вечернего детектива»\n")
	return sanitizeLine(b.String())
}

// resetHTML возвращает HTML-версию письма о сбросе пароля.
func resetHTML(username, email, password, loginURL string) string {
	var content strings.Builder
	content.WriteString("<p>Привет, <strong>")
	content.WriteString(html.EscapeString(username))
	content.WriteString("</strong>!</p>\n")
	content.WriteString("<p>Ты запросил сброс пароля в «Вечернем детективе». Новый пароль для входа:</p>\n")
	content.WriteString(credentialsBlockHTML(email, password))
	if loginURL != "" {
		content.WriteString(buttonHTML(loginURL, "Войти в игру"))
	}
	content.WriteString("<p>Никому не сообщай пароль и не пересылай это письмо.</p>\n")
	content.WriteString("<p style=\"color:#777777; font-size:13px;\">Если это был не ты — ответь на это письмо: мы поможем защитить аккаунт.</p>")
	return wrapHTML(content.String())
}

// greeting возвращает приветствие с именем пользователя; при пустом имени —
// без обращения, чтобы не было «Привет, !».
func greeting(username string) string {
	username = sanitizeLine(strings.TrimSpace(username))
	if username == "" {
		return "Привет!"
	}
	return fmt.Sprintf("Привет, %s!", username)
}

// credentialsBlockHTML — блок «Логин / Пароль» в табличной вёрстке,
// совместимой с Gmail.
func credentialsBlockHTML(email, password string) string {
	return `<table role="presentation" cellpadding="0" cellspacing="0" style="margin:16px 0; border:1px solid #e3ddd2; border-radius:6px; background-color:#faf8f5; width:100%;">
<tr>
<td style="padding:12px 16px; font-size:14px; color:#555555; width:120px;">Логин</td>
<td style="padding:12px 16px; font-size:14px; color:#222222;"><strong>` + html.EscapeString(email) + `</strong></td>
</tr>
<tr>
<td style="padding:12px 16px; font-size:14px; color:#555555; width:120px; border-top:1px solid #e3ddd2;">Пароль</td>
<td style="padding:12px 16px; font-size:14px; color:#1a1a2e; border-top:1px solid #e3ddd2;"><strong>` + html.EscapeString(password) + `</strong></td>
</tr>
</table>`
}

// buttonHTML — CTA-кнопка табличной вёрсткой (Gmail не поддерживает
// margin/padding на <a>, поэтому отступы — на ячейке <td>).
func buttonHTML(link, label string) string {
	return `<table role="presentation" cellpadding="0" cellspacing="0" style="margin:20px 0;">
<tr>
<td style="border-radius:6px; background-color:#c9a227;">
<a href="` + html.EscapeString(link) + `" style="display:inline-block; padding:12px 28px; color:#1a1a2e; font-weight:bold; text-decoration:none; font-size:15px; border-radius:6px;">` + html.EscapeString(label) + `</a>
</td>
</tr>
</table>`
}

// wrapHTML — каркас письма: тёмная шапка с названием сервиса, контент,
// подвал с дисклеймером. Только табличная вёрстка и inline-стили: внешние
// таблицы стилей Gmail вырезает.
func wrapHTML(content string) string {
	return `<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body style="margin:0; padding:0; background-color:#f4f1ec; font-family:Arial, Helvetica, sans-serif;">
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" style="background-color:#f4f1ec; padding:24px 0;">
<tr><td align="center">
<table role="presentation" width="600" cellpadding="0" cellspacing="0" style="max-width:600px; width:100%; background-color:#ffffff; border-radius:8px; overflow:hidden;">
<tr>
<td style="background-color:#1a1a2e; padding:20px 28px;">
<span style="color:#ffffff; font-size:20px; font-weight:bold; letter-spacing:1px;">ВЕЧЕРНИЙ ДЕТЕКТИВ</span>
</td>
</tr>
<tr>
<td style="padding:28px; color:#222222; font-size:15px; line-height:1.6;">
` + content + `
</td>
</tr>
<tr>
<td style="padding:20px 28px; background-color:#faf8f5; color:#777777; font-size:12px; line-height:1.5;">
Это автоматическое письмо сервиса «Вечерний детектив».<br>
Если ты получил его по ошибке — просто ответь на это письмо.
</td>
</tr>
</table>
</td></tr>
</table>
</body>
</html>`
}

// sanitizeLine убирает переносы строк из пользовательского ввода,
// вставляемого в тело письма (защита от инъекции строк в DATA-фазу SMTP).
func sanitizeLine(s string) string {
	return strings.NewReplacer("\r", "", "\n", "").Replace(s)
}

// loginURL нормализует адрес фронтенда для ссылки в письме: срезает
// завершающий слэш и допускает только http(s). Пустое или некорректное
// значение — ссылка в письма не добавляется.
func loginURL(baseURL string) string {
	baseURL = strings.TrimSpace(baseURL)
	baseURL = strings.TrimRight(baseURL, "/")
	if baseURL == "" {
		return ""
	}
	if !strings.HasPrefix(baseURL, "http://") && !strings.HasPrefix(baseURL, "https://") {
		return ""
	}
	return baseURL
}
