package web

import (
	"encoding/json"
	"net/http"
	"strings"
)

func withSecurity(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("X-Content-Type-Options", "nosniff")
		w.Header().Set("Referrer-Policy", "same-origin")
		next.ServeHTTP(w, r)
	})
}

func writeJSON(w http.ResponseWriter, status int, payload any) {
	w.Header().Set("Content-Type", "application/json; charset=utf-8")
	w.WriteHeader(status)
	_ = json.NewEncoder(w).Encode(payload)
}

func writeSSE(w http.ResponseWriter, event string, payload any) {
	data, _ := json.Marshal(payload)
	_, _ = w.Write([]byte("event: " + event + "\n"))
	_, _ = w.Write([]byte("data: " + string(data) + "\n\n"))
}

func writeError(w http.ResponseWriter, status int, code string, err error) {
	message := ""
	if err != nil {
		message = err.Error()
	}
	writeJSON(w, status, map[string]any{"ok": false, "error": code, "message": localizedErrorMessage(code, message)})
}

func localizedErrorMessage(code, message string) string {
	raw := strings.TrimSpace(message)
	lower := strings.ToLower(raw)
	exact := map[string]string{
		"current password is invalid":                          "当前密码不正确",
		"new password is required":                             "新密码不能为空",
		"new password must be at least 8 characters":           "新密码至少需要 8 位",
		"new password cannot be admin":                         "新密码不能为 admin",
		"new password must be different from current password": "新密码不能与当前密码相同",
		"invalid password or captcha":                          "密码或验证码不正确",
		"login required":                                       "需要登录后继续操作",
		"csrf token required":                                  "页面安全令牌已失效，请刷新后重试",
		"csrf token invalid":                                   "页面安全令牌无效，请刷新后重试",
		"code is required":                                     "缺少反馈编号",
		"revisionid is required":                               "请选择要恢复的历史版本",
		"post required":                                        "该操作需要使用 POST 请求",
		"get required":                                         "该操作需要使用 GET 请求",
		"file is required":                                     "请选择要上传的文件",
		"invalid filename":                                     "文件名不合法",
		"path escape rejected":                                 "文件路径不合法",
		"check job not found":                                  "未找到心跳检测任务",
		"streaming is not supported":                           "当前运行环境不支持实时事件流",
		"source api_url is empty":                              "接口地址不能为空",
		"database is not available":                            "数据库当前不可用",
		"provider must be sqlite or mysql":                     "数据库类型必须是 SQLite 或 MySQL",
		"mysql connection is required":                         "请填写 MySQL 连接信息",
		"mysql database is required":                           "请填写 MySQL 数据库名",
		"mysql username is required":                           "请填写 MySQL 数据库用户",
		"sqlite path is required":                              "请填写 SQLite 路径",
		"mysql_dsn is required":                                "请填写 MySQL DSN",
		"remote database is not configured":                    "远端 MySQL 未配置",
		"database sync is already running":                     "数据库同步正在执行，请稍后再试",
		"mail is not configured":                               "邮件通知尚未配置完整",
		"release notices are not configured":                   "版本日志功能尚未配置",
		"legacy sync service is not configured":                "旧项目同步服务尚未配置",
		"update-info requires app_version or title":            "更新 JSON 需要填写 app_version 或 title",
		"media-types requires categories array":                "媒体源 JSON 需要包含 categories 数组",
		"version or app_version is required":                   "版本日志需要填写 version 或 app_version",
	}
	if translated, ok := exact[lower]; ok {
		return translated
	}
	byCode := map[string]string{
		"UNAUTHORIZED":              "需要登录后继续操作",
		"LOGIN_FAILED":              "登录失败，请检查密码和验证码",
		"PASSWORD_CHANGE_FAILED":    "密码修改失败",
		"INVALID_PAYLOAD":           "提交内容格式不正确",
		"DATABASE_TEST_FAILED":      "数据库连接测试失败",
		"DATABASE_SAVE_FAILED":      "数据库配置保存失败",
		"DATABASE_IMPORT_FAILED":    "SQLite 导入远端库失败",
		"DATABASE_SYNC_FAILED":      "远端库同步回本地失败",
		"LEGACY_SAVE_FAILED":        "兼容 JSON 保存失败",
		"LEGACY_VALIDATE_FAILED":    "兼容 JSON 校验失败",
		"LEGACY_RESTORE_FAILED":     "兼容 JSON 恢复失败",
		"NOTICE_SAVE_FAILED":        "版本日志保存失败",
		"NOTICE_VALIDATE_FAILED":    "版本日志校验失败",
		"NOTICE_RESTORE_FAILED":     "版本日志恢复失败",
		"PACKAGE_UPLOAD_FAILED":     "发布包上传失败",
		"SOURCE_SAVE_FAILED":        "接口源保存失败",
		"CHECK_FAILED":              "接口健康检测失败",
		"SYNC_FAILED":               "同步操作失败",
		"FORBIDDEN":                 "没有权限执行该操作",
		"METHOD_NOT_ALLOWED":        "请求方法不正确",
		"FILE_REQUIRED":             "请选择要上传的文件",
		"CHECK_JOB_NOT_FOUND":       "未找到心跳检测任务",
		"SSE_UNSUPPORTED":           "当前运行环境不支持实时事件流",
		"SOURCES_FAILED":            "接口源数据加载失败",
		"ENDPOINTS_FAILED":          "客户端接口数据加载失败",
		"DASHBOARD_FAILED":          "仪表盘数据加载失败",
		"AUDIT_FAILED":              "审计日志加载失败",
		"FEEDBACK_LIST_FAILED":      "反馈列表加载失败",
		"FEEDBACK_UPDATE_FAILED":    "反馈工单更新失败",
		"MAIL_CONFIG_FAILED":        "邮件配置保存失败",
		"MAIL_TEST_FAILED":          "测试邮件发送失败",
		"MAIL_RETRY_FAILED":         "反馈邮件重试失败",
		"NOTICE_NOT_FOUND":          "未找到版本日志",
		"NOTICES_FAILED":            "版本日志加载失败",
		"MEDIA_TYPES_FAILED":        "媒体源 JSON 加载失败",
		"SOURCE_CALL_FAILED":        "接口调用状态上报失败",
		"IMPORT_FAILED":             "导入失败",
		"PATH_FAILED":               "路径解析失败",
		"INVALID_UPLOAD":            "上传内容不正确",
		"BOOTSTRAP_FAILED":          "后台初始化信息加载失败",
		"CAPTCHA_FAILED":            "验证码加载失败",
		"TOO_LARGE":                 "反馈包过大",
		"MISSING_FIELD":             "缺少旧反馈提交字段",
		"INVALID_TIMESTAMP":         "反馈提交时间已过期",
		"INVALID_SIGNATURE":         "反馈签名校验失败",
		"INVALID_PACKAGE":           "反馈包格式不正确",
		"INVALID_ENCRYPTED_PACKAGE": "反馈加密包格式不正确",
		"DECRYPT_FAILED":            "反馈包解密失败",
		"HASH_MISMATCH":             "反馈包哈希校验失败",
		"SERVER_CONFIG":             "反馈服务配置异常",
	}
	if translated, ok := byCode[code]; ok {
		if raw == "" || strings.EqualFold(raw, code) {
			return translated
		}
		return translated + "：" + raw
	}
	if raw == "" {
		return "操作失败"
	}
	return raw
}

func cleanPath(path string) string {
	if path == "" {
		return "/"
	}
	if path != "/" {
		path = strings.TrimRight(path, "/")
	}
	if path == "" {
		return "/"
	}
	return path
}

func requestBaseURL(r *http.Request, fallback string) string {
	scheme := r.Header.Get("X-Forwarded-Proto")
	if scheme == "" {
		if r.TLS != nil {
			scheme = "https"
		} else {
			scheme = "http"
		}
	}
	if r.Host != "" {
		return scheme + "://" + r.Host
	}
	return strings.TrimRight(fallback, "/")
}

func firstNonEmpty(values ...string) string {
	for _, value := range values {
		if strings.TrimSpace(value) != "" {
			return strings.TrimSpace(value)
		}
	}
	return ""
}
