package handler

import (
	"net/http"
	"path/filepath"
	"strings"

	"u-desk/internal/agent/model"
	"u-desk/internal/filesystem"

	"github.com/labstack/echo/v4"
)

type writeFileReq struct {
	Content string `json:"content"`
}

type createReq struct {
	Type string `json:"type"` // "file" or "dir"
	Name string `json:"name"`
}

type renameReq struct {
	NewPath string `json:"new_path"`
}

type uploadReq struct {
	Content string `json:"content"` // base64 编码内容
}

// ListOrStat 列出目录或获取文件信息（?get=stat 时返回单文件信息）
func (h *Handler) ListOrStat(c echo.Context) error {
	path := getPath(c)
	action := c.QueryParam("get")

	if action == "stat" {
		info, err := h.fsSvc.GetFileInfo(path)
		if err != nil {
			return c.JSON(http.StatusOK, model.NotFound(err.Error()))
		}
		return c.JSON(http.StatusOK, model.OK(info))
	}

	files, err := h.fsSvc.ListDir(path)
	if err != nil {
		return c.JSON(http.StatusOK, model.InternalError(err.Error()))
	}
	// 限制返回数量，避免大目录导致前端卡顿
	limit := c.QueryParam("limit")
	if limit != "" {
		n := 0
		for i, f := range files {
			if n >= 500 { // 硬限制 500 条
				break
			}
			files[i] = f
			n++
		}
		files = files[:n]
	}
	return c.JSON(http.StatusOK, model.OK(files))
}

// ReadFile 读取文件文本内容
func (h *Handler) ReadFile(c echo.Context) error {
	path := getPath(c)
	content, err := h.fsSvc.ReadFile(path)
	if err != nil {
		return c.JSON(http.StatusOK, model.InternalError(err.Error()))
	}
	return c.JSON(http.StatusOK, model.OK(map[string]string{
		"content": content,
	}))
}

// WriteFile 写入文件文本内容
func (h *Handler) WriteFile(c echo.Context) error {
	path := getPath(c)
	var req writeFileReq
	if err := c.Bind(&req); err != nil {
		return c.JSON(http.StatusBadRequest, model.BadRequest("无效请求体"))
	}
	if err := h.fsSvc.WriteFile(path, req.Content); err != nil {
		return c.JSON(http.StatusInternalServerError, model.InternalError(err.Error()))
	}
	return c.JSON(http.StatusOK, model.NoContent())
}

// Create 创建文件或目录
func (h *Handler) Create(c echo.Context) error {
	parentPath := getPath(c)
	var req createReq
	if err := c.Bind(&req); err != nil {
		return c.JSON(http.StatusBadRequest, model.BadRequest("无效请求体"))
	}

	req.Name = strings.TrimSpace(req.Name)
	if req.Name == "" {
		return c.JSON(http.StatusBadRequest, model.BadRequest("名称不能为空"))
	}

	var result *filesystem.FileOperationResult
	var err error

	fullPath := filepath.Join(parentPath, req.Name)

	switch req.Type {
	case "dir":
		result, err = h.fsSvc.CreateDir(fullPath)
	default:
		result, err = h.fsSvc.CreateFile(fullPath)
	}

	if err != nil {
		return c.JSON(http.StatusInternalServerError, model.InternalError(err.Error()))
	}
	return c.JSON(http.StatusCreated, model.OK(result))
}

// Delete 删除文件或目录
func (h *Handler) Delete(c echo.Context) error {
	path := getPath(c)
	result, err := h.fsSvc.DeletePath(path)
	if err != nil {
		return c.JSON(http.StatusInternalServerError, model.InternalError(err.Error()))
	}
	return c.JSON(http.StatusOK, model.OK(result))
}

// Rename 重命名文件或目录
func (h *Handler) Rename(c echo.Context) error {
	oldPath := getPath(c)
	var req renameReq
	if err := c.Bind(&req); err != nil {
		return c.JSON(http.StatusBadRequest, model.BadRequest("无效请求体"))
	}
	req.NewPath = strings.TrimSpace(req.NewPath)
	if req.NewPath == "" {
		return c.JSON(http.StatusBadRequest, model.BadRequest("新路径不能为空"))
	}
	cleanNew := filepath.Clean(req.NewPath)
	if strings.Contains(cleanNew, "..") {
		return c.JSON(http.StatusBadRequest, model.BadRequest("新路径不允许包含 .."))
	}
	result, err := h.fsSvc.RenamePath(oldPath, cleanNew)
	if err != nil {
		return c.JSON(http.StatusInternalServerError, model.InternalError(err.Error()))
	}
	return c.JSON(http.StatusOK, model.OK(result))
}

// Upload 上传 Base64 编码的二进制文件
func (h *Handler) Upload(c echo.Context) error {
	path := getPath(c)
	var req uploadReq
	if err := c.Bind(&req); err != nil {
		return c.JSON(http.StatusBadRequest, model.BadRequest("无效请求体"))
	}
	if req.Content == "" {
		return c.JSON(http.StatusBadRequest, model.BadRequest("内容不能为空"))
	}
	if err := h.fsSvc.SaveBase64File(path, req.Content); err != nil {
		return c.JSON(http.StatusInternalServerError, model.InternalError(err.Error()))
	}
	return c.JSON(http.StatusOK, model.NoContent())
}

// DetectType 通过文件内容检测类型
func (h *Handler) DetectType(c echo.Context) error {
	path := getPath(c)
	info, err := h.fsSvc.DetectFileTypeByContent(path)
	if err != nil {
		return c.JSON(http.StatusOK, model.InternalError(err.Error()))
	}
	return c.JSON(http.StatusOK, model.OK(info))
}
