// handlers/avatar.go
package handlers

import (
	"net/http"
	"strings"
	"time"

	"api_bb/internal/service"
	"api_bb/pkg/logger"
	"api_bb/pkg/middleware"
	"api_bb/pkg/utils"

	"github.com/go-chi/chi/v5"
	"go.uber.org/zap"
)

type AvatarHandler struct {
	logger        logger.LoggerInterface
	avatarService service.AvatarService
}

func NewAvatarHandler(avatarService service.AvatarService) *AvatarHandler {
	return &AvatarHandler{
		logger:        logger.NewWrapper(logger.Get().With(zap.String("handler", "avatar"))),
		avatarService: avatarService,
	}
}

func (h *AvatarHandler) UploadAvatar(w http.ResponseWriter, r *http.Request) {
	h.logger.Debug("UploadAvatar START",
		zap.String("method", r.Method),
		zap.String("path", r.URL.Path),
		zap.String("remote_addr", r.RemoteAddr),
	)

	defer func() {
		h.logger.Debug("UploadAvatar END",
			zap.String("method", r.Method),
			zap.String("path", r.URL.Path),
		)
	}()

	user, ok := middleware.GetUserFromContext(r.Context())
	if !ok {
		h.logger.Warn("UploadAvatar: authentication required")
		utils.RespondWithError(w, http.StatusUnauthorized, "Authentication required")
		return
	}

	h.logger.Debug("UploadAvatar: user authenticated",
		zap.Int64("user_id", int64(user.ID)),
		zap.String("username", user.FirstName+user.LastName),
	)

	// Парсим multipart форму
	h.logger.Debug("UploadAvatar: parsing multipart form")
	if err := r.ParseMultipartForm(10 << 20); err != nil { // 10MB limit
		h.logger.Error("UploadAvatar: failed to parse form", zap.Error(err))
		utils.RespondWithError(w, http.StatusBadRequest, "Failed to parse form: "+err.Error())
		return
	}

	h.logger.Debug("UploadAvatar: getting file from form")
	file, header, err := r.FormFile("avatar")
	if err != nil {
		h.logger.Error("UploadAvatar: failed to get file from form", zap.Error(err))
		utils.RespondWithError(w, http.StatusBadRequest, "Failed to get file: "+err.Error())
		return
	}
	defer file.Close()

	h.logger.Debug("UploadAvatar: file received",
		zap.String("filename", header.Filename),
		zap.Int64("size", header.Size),
		zap.String("content_type", header.Header.Get("Content-Type")),
	)

	// Проверяем тип файла
	allowedTypes := map[string]bool{
		"image/jpeg": true,
		"image/jpg":  true,
		"image/png":  true,
		"image/gif":  true,
	}
	contentType := header.Header.Get("Content-Type")
	if !allowedTypes[contentType] {
		h.logger.Warn("UploadAvatar: invalid file type",
			zap.String("content_type", contentType),
			zap.String("filename", header.Filename),
		)
		utils.RespondWithError(w, http.StatusBadRequest, "Only JPEG, PNG and GIF images are allowed")
		return
	}

	h.logger.Debug("UploadAvatar: file type validated successfully")

	// Загружаем аватар
	h.logger.Debug("UploadAvatar: calling avatarService.UploadAvatar",
		zap.Int64("user_id", int64(user.ID)),
	)
	avatarPath, err := h.avatarService.UploadAvatar(user.ID, file, header)
	if err != nil {
		h.logger.Error("UploadAvatar: failed to upload avatar", zap.Error(err))
		utils.RespondWithError(w, http.StatusInternalServerError, "Failed to upload avatar: "+err.Error())
		return
	}

	h.logger.Info("UploadAvatar: avatar uploaded successfully",
		zap.Int64("user_id", int64(user.ID)),
		zap.String("avatar_path", avatarPath),
	)

	// Возвращаем ответ с полем success
	utils.RespondWithJSON(w, http.StatusOK, map[string]interface{}{
		"success": true,
		"message": "Avatar uploaded successfully",
		"avatar":  avatarPath,
	})
}

func (h *AvatarHandler) DeleteAvatar(w http.ResponseWriter, r *http.Request) {
	h.logger.Debug("DeleteAvatar START",
		zap.String("method", r.Method),
		zap.String("path", r.URL.Path),
		zap.String("remote_addr", r.RemoteAddr),
	)

	defer func() {
		h.logger.Debug("DeleteAvatar END",
			zap.String("method", r.Method),
			zap.String("path", r.URL.Path),
		)
	}()

	user, ok := middleware.GetUserFromContext(r.Context())
	if !ok {
		h.logger.Warn("DeleteAvatar: authentication required")
		utils.RespondWithError(w, http.StatusUnauthorized, "Authentication required")
		return
	}

	h.logger.Debug("DeleteAvatar: user authenticated",
		zap.Int64("user_id", int64(user.ID)),
		zap.String("username", user.FirstName+user.LastName),
	)

	h.logger.Debug("DeleteAvatar: calling avatarService.DeleteAvatar",
		zap.Int64("user_id", int64(user.ID)),
	)
	if err := h.avatarService.DeleteAvatar(user.ID); err != nil {
		h.logger.Error("DeleteAvatar: failed to delete avatar", zap.Error(err))
		utils.RespondWithError(w, http.StatusInternalServerError, "Failed to delete avatar: "+err.Error())
		return
	}

	h.logger.Info("DeleteAvatar: avatar deleted successfully",
		zap.Int64("user_id", int64(user.ID)),
	)

	// Возвращаем ответ с полем success
	utils.RespondWithJSON(w, http.StatusOK, map[string]interface{}{
		"success": true,
		"message": "Avatar deleted successfully",
	})
}

// GET /v1/user/avatars/{filename}
func (h *AvatarHandler) GetAvatar(w http.ResponseWriter, r *http.Request) {
	filename := chi.URLParam(r, "filename")

	h.logger.Debug("GetAvatar START",
		zap.String("method", r.Method),
		zap.String("filename", filename),
		zap.String("remote_addr", r.RemoteAddr),
		zap.String("url", r.URL.String()),
	)

	defer func() {
		h.logger.Debug("GetAvatar END",
			zap.String("method", r.Method),
			zap.String("filename", filename),
		)
	}()

	// Валидация имени файла
	if filename == "" || strings.Contains(filename, "..") || strings.Contains(filename, "/") {
		h.logger.Warn("GetAvatar: invalid filename", zap.String("filename", filename))
		utils.RespondWithError(w, http.StatusBadRequest, "Invalid filename")
		return
	}

	h.logger.Info("GetAvatar: handling get avatar request",
		zap.String("method", r.Method),
		zap.String("filename", filename),
		zap.String("remote_addr", r.RemoteAddr),
	)

	// Используем ServeAvatarFile для обслуживания файла
	h.logger.Debug("GetAvatar: calling avatarService.ServeAvatarFile",
		zap.String("filename", filename),
	)
	contentType, err := h.avatarService.ServeAvatarFile(w, filename)
	if err != nil {
		h.logger.Warn("GetAvatar: failed to serve avatar file",
			zap.String("filename", filename),
			zap.Error(err),
		)

		switch {
		case err.Error() == "avatar file not found":
			h.logger.Warn("GetAvatar: avatar file not found", zap.String("filename", filename))
			utils.RespondWithError(w, http.StatusNotFound, "Avatar not found")
		case err.Error() == "invalid filename" || err.Error() == "unsupported file format":
			h.logger.Warn("GetAvatar: invalid filename or format",
				zap.String("filename", filename),
				zap.Error(err),
			)
			utils.RespondWithError(w, http.StatusBadRequest, err.Error())
		default:
			h.logger.Error("GetAvatar: internal server error", zap.Error(err))
			utils.RespondWithError(w, http.StatusInternalServerError, "Failed to serve avatar")
		}
		return
	}

	// Устанавливаем заголовки для кэширования
	h.logger.Debug("GetAvatar: setting response headers",
		zap.String("content_type", contentType),
	)
	w.Header().Set("Content-Type", contentType)
	w.Header().Set("Cache-Control", "public, max-age=31536000") // Кэш на 1 год
	w.Header().Set("Expires", time.Now().Add(365*24*time.Hour).Format(http.TimeFormat))

	h.logger.Info("GetAvatar: avatar served successfully",
		zap.String("filename", filename),
		zap.String("content_type", contentType),
	)
}