package handlers

import (
	"net/http"

	"github.com/labstack/echo/v4"
	"github.com/rs/zerolog/log"

	"github.com/treytartt/honeydue-api/internal/apperrors"
	"github.com/treytartt/honeydue-api/internal/dto/responses"
	"github.com/treytartt/honeydue-api/internal/i18n"
	"github.com/treytartt/honeydue-api/internal/middleware"
	"github.com/treytartt/honeydue-api/internal/services"
)

// FileOwnershipChecker verifies whether a user owns a file referenced by URL.
// Implementations should check associated records (e.g., task completion images,
// document files, document images) to determine ownership.
type FileOwnershipChecker interface {
	IsFileOwnedByUser(fileURL string, userID uint) (bool, error)
}

// UploadHandler handles file upload endpoints
type UploadHandler struct {
	storageService      *services.StorageService
	fileOwnershipChecker FileOwnershipChecker
}

// NewUploadHandler creates a new upload handler
func NewUploadHandler(storageService *services.StorageService, fileOwnershipChecker FileOwnershipChecker) *UploadHandler {
	return &UploadHandler{
		storageService:      storageService,
		fileOwnershipChecker: fileOwnershipChecker,
	}
}

// UploadImage handles POST /api/uploads/image
// Accepts multipart/form-data with "file" field
func (h *UploadHandler) UploadImage(c echo.Context) error {
	file, err := c.FormFile("file")
	if err != nil {
		return apperrors.BadRequest("error.no_file_provided")
	}

	// Get category from query param (default: images)
	category := c.QueryParam("category")
	if category == "" {
		category = "images"
	}

	result, err := h.storageService.Upload(file, category)
	if err != nil {
		return err
	}

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

// UploadDocument handles POST /api/uploads/document
// Accepts multipart/form-data with "file" field
func (h *UploadHandler) UploadDocument(c echo.Context) error {
	file, err := c.FormFile("file")
	if err != nil {
		return apperrors.BadRequest("error.no_file_provided")
	}

	result, err := h.storageService.Upload(file, "documents")
	if err != nil {
		return err
	}

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

// UploadCompletion handles POST /api/uploads/completion
// For task completion photos
func (h *UploadHandler) UploadCompletion(c echo.Context) error {
	file, err := c.FormFile("file")
	if err != nil {
		return apperrors.BadRequest("error.no_file_provided")
	}

	result, err := h.storageService.Upload(file, "completions")
	if err != nil {
		return err
	}

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

// DeleteFileRequest is the request body for deleting a file.
type DeleteFileRequest struct {
	URL string `json:"url" validate:"required"`
}

// DeleteFile handles DELETE /api/uploads
// Expects JSON body with "url" field.
// Verifies that the requesting user owns the file by checking associated records
// (task completion images, document files/images) before allowing deletion.
func (h *UploadHandler) DeleteFile(c echo.Context) error {
	user, err := middleware.MustGetAuthUser(c)
	if err != nil {
		return err
	}

	var req DeleteFileRequest

	if err := c.Bind(&req); err != nil {
		return apperrors.BadRequest("error.invalid_request")
	}

	if err := c.Validate(&req); err != nil {
		return apperrors.BadRequest("error.url_required")
	}

	// Verify ownership: the user must own a record that references this file URL
	if h.fileOwnershipChecker != nil {
		owned, err := h.fileOwnershipChecker.IsFileOwnedByUser(req.URL, user.ID)
		if err != nil {
			log.Error().Err(err).Uint("user_id", user.ID).Str("file_url", req.URL).Msg("Failed to check file ownership")
			return apperrors.Internal(err)
		}
		if !owned {
			log.Warn().Uint("user_id", user.ID).Str("file_url", req.URL).Msg("Unauthorized file deletion attempt")
			return apperrors.Forbidden("error.file_access_denied")
		}
	}

	// Log the deletion with user ID for audit trail
	log.Info().
		Uint("user_id", user.ID).
		Str("file_url", req.URL).
		Msg("File deletion requested")

	if err := h.storageService.Delete(req.URL); err != nil {
		return err
	}

	return c.JSON(http.StatusOK, responses.MessageResponse{Message: i18n.LocalizedMessage(c, "message.file_deleted")})
}
