package repo

import (
	"fmt"
	"net/url"
	"strconv"

	"github.com/gitlink-org/gitlink-cli/shortcuts/common"
)

func Shortcuts() []*common.Shortcut {
		shortcuts := []*common.Shortcut{
			newBatchCreateShortcut(),
			newBatchUpdateShortcut(),
		{
			Name:        "list",
			Description: "List repositories for a user or organization",
			Flags: []common.Flag{
				{Name: "user", Short: "u", Usage: "User login (default: current user)"},
				{Name: "category", Short: "c", Usage: "Filter: manage/mirror/sync/fork/all (default: manage)", Default: "manage"},
				{Name: "page", Short: "p", Usage: "Page number", Default: "1"},
				{Name: "limit", Short: "l", Usage: "Items per page", Default: "20"},
			},
			Run: func(ctx *common.RuntimeContext) error {
				user := ctx.Arg("user")
				q := url.Values{}
				q.Set("page", ctx.Arg("page"))
				q.Set("limit", ctx.Arg("limit"))
				if cat := ctx.Arg("category"); cat != "" && cat != "all" {
					q.Set("category", cat)
				}

				path := "/projects"
				if user != "" {
					path = fmt.Sprintf("/users/%s/projects", user)
				}
				env, err := ctx.CallAPIWithQuery("GET", path, q)
				if err != nil {
					return fmt.Errorf("获取仓库列表失败: %w", err)
				}
				return ctx.Output(env)
			},
		},
		{
			Name:        "info",
			Description: "Show repository details",
			Run: func(ctx *common.RuntimeContext) error {
				if err := ctx.ResolveOwnerRepo(); err != nil {
					return err
				}
				env, err := ctx.CallAPI("GET", ctx.RepoPath(), nil)
				if err != nil {
					return fmt.Errorf("查看仓库失败: %w", err)
				}
				return ctx.Output(env)
			},
		},
		{
			Name:        "create",
			Description: "Create a new repository",
			DryRun:      true,
			DryRunHint: func(ctx *common.RuntimeContext) (string, error) {
				name := ctx.Arg("name")
				return fmt.Sprintf("Create repository: %s", name), nil
			},
			Flags: []common.Flag{
				{Name: "name", Short: "n", Usage: "Repository name", Required: true},
				{Name: "description", Short: "d", Usage: "Repository description"},
				{Name: "private", Usage: "Make repository private (true/false)", Default: "false"},
			},
			Run: func(ctx *common.RuntimeContext) error {
				name, err := ctx.RequireArg("name", `--name "my-project"`)
				if err != nil {
					return err
				}
				// Get current user login for the create path
				userEnv, err := ctx.CallAPI("GET", "/users/me", nil)
				if err != nil {
					return fmt.Errorf("获取当前用户信息失败: %w", err)
				}
				userData, _ := userEnv.Data.(map[string]interface{})
				login, _ := userData["login"].(string)
				if login == "" {
					return fmt.Errorf("cannot determine current user login")
				}
				userID, _ := userData["user_id"].(float64)
				body := map[string]interface{}{
					"name":            name,
					"repository_name": name,
					"user_id":         int(userID),
				}
				if desc := ctx.Arg("description"); desc != "" {
					body["description"] = desc
				}
				if ctx.Arg("private") == "true" {
					body["private"] = true
				}
				env, err := ctx.CallAPI("POST", fmt.Sprintf("/%s/%s", login, name), body)
				if err != nil {
					return fmt.Errorf("创建仓库失败: %w", err)
				}
				return ctx.Output(env)
			},
		},
		{
			Name:        "fork",
			Description: "Fork a repository",
			DryRun:      true,
			DryRunHint: func(ctx *common.RuntimeContext) (string, error) {
				if err := ctx.ResolveOwnerRepo(); err != nil {
					return "", err
				}
				return fmt.Sprintf("Fork repository %s/%s", ctx.Owner, ctx.Repo), nil
			},
			Run: func(ctx *common.RuntimeContext) error {
				if err := ctx.ResolveOwnerRepo(); err != nil {
					return err
				}
				env, err := ctx.CallAPI("POST", ctx.RepoPath()+"/forks", nil)
				if err != nil {
					return fmt.Errorf("Fork 仓库失败: %w", err)
				}
				return ctx.Output(env)
			},
		},
		{
			Name:        "delete",
			Description: "Delete a repository",
			DryRun:      true,
			DryRunHint: func(ctx *common.RuntimeContext) (string, error) {
				if err := ctx.ResolveOwnerRepo(); err != nil {
					return "", err
				}
				return fmt.Sprintf("DELETE repository %s/%s", ctx.Owner, ctx.Repo), nil
			},
			Run: func(ctx *common.RuntimeContext) error {
				if err := ctx.ResolveOwnerRepo(); err != nil {
					return err
				}
				env, err := ctx.CallAPI("DELETE", ctx.RepoPath(), nil)
				if err != nil {
					return fmt.Errorf("删除仓库失败: %w", err)
				}
				return ctx.Output(env)
			},
		},
		{
			Name:        "update",
			Description: "Update repository settings",
			Flags: []common.Flag{
				{Name: "description", Short: "d", Usage: "New description"},
				{Name: "private", Usage: "Set private (true/false)"},
			},
			Run: func(ctx *common.RuntimeContext) error {
				if err := ctx.ResolveOwnerRepo(); err != nil {
					return err
				}
				body := map[string]interface{}{}
				if d := ctx.Arg("description"); d != "" {
					body["description"] = d
				}
				if p := ctx.Arg("private"); p != "" {
					body["private"] = p == "true"
				}
				if len(body) == 0 {
					return fmt.Errorf("at least one of --description, --private is required")
				}
				env, err := ctx.CallAPI("PATCH", ctx.RepoPath(), body)
				if err != nil {
					return err
				}
				return ctx.Output(env)
			},
		},
		{
			Name:        "members",
			Description: "List repository members (collaborators)",
			Flags: []common.Flag{
				{Name: "page", Short: "p", Usage: "Page number", Default: "1"},
				{Name: "limit", Short: "l", Usage: "Items per page", Default: "20"},
			},
			Run: func(ctx *common.RuntimeContext) error {
				if err := ctx.ResolveOwnerRepo(); err != nil {
					return err
				}
				q := url.Values{}
				q.Set("page", ctx.Arg("page"))
				q.Set("limit", ctx.Arg("limit"))
				env, err := ctx.CallAPIWithQuery("GET", ctx.RepoPath()+"/collaborators", q)
				if err != nil {
					return fmt.Errorf("failed to list members for %s/%s: %w", ctx.Owner, ctx.Repo, err)
				}
				return ctx.Output(env)
			},
		},
		{
			Name:        "invite",
			Description: "Invite a member to a repository",
			DryRun:      true,
			DryRunHint: func(ctx *common.RuntimeContext) (string, error) {
				if err := ctx.ResolveOwnerRepo(); err != nil {
					return "", err
				}
				userID := ctx.Arg("user-id")
				return fmt.Sprintf("Invite user %s to %s/%s", userID, ctx.Owner, ctx.Repo), nil
			},
			Flags: []common.Flag{
				{Name: "user-id", Usage: "User ID to invite (required)", Required: true},
			},
			Run: func(ctx *common.RuntimeContext) error {
				if err := ctx.ResolveOwnerRepo(); err != nil {
					return err
				}
				userID, err := ctx.RequireArg("user-id", "--user-id 42")
				if err != nil {
					return err
				}
				uid, err := strconv.Atoi(userID)
				if err != nil {
					return fmt.Errorf("invalid user-id: %s (must be an integer)", userID)
				}
				body := map[string]interface{}{"user_id": uid}
				env, err := ctx.CallAPI("POST", ctx.RepoPath()+"/collaborators", body)
				if err != nil {
					return fmt.Errorf("failed to invite user %d to %s/%s: %w", uid, ctx.Owner, ctx.Repo, err)
				}
				return ctx.Output(env)
			},
		},
		{
			Name:        "remove-member",
			Description: "Remove a member from a repository",
			DryRun:      true,
			DryRunHint: func(ctx *common.RuntimeContext) (string, error) {
				if err := ctx.ResolveOwnerRepo(); err != nil {
					return "", err
				}
				userID := ctx.Arg("user-id")
				return fmt.Sprintf("Remove user %s from %s/%s", userID, ctx.Owner, ctx.Repo), nil
			},
			Flags: []common.Flag{
				{Name: "user-id", Usage: "User ID to remove (required)", Required: true},
			},
			Run: func(ctx *common.RuntimeContext) error {
				if err := ctx.ResolveOwnerRepo(); err != nil {
					return err
				}
				userID, err := ctx.RequireArg("user-id", "--user-id 42")
				if err != nil {
					return err
				}
				uid, err := strconv.Atoi(userID)
				if err != nil {
					return fmt.Errorf("invalid user-id: %s (must be an integer)", userID)
				}
				body := map[string]interface{}{"user_id": uid}
				env, err := ctx.CallAPI("DELETE", ctx.RepoPath()+"/collaborators/remove", body)
				if err != nil {
					return fmt.Errorf("failed to remove user %d from %s/%s: %w", uid, ctx.Owner, ctx.Repo, err)
				}
				return ctx.Output(env)
			},
		},
	}

	// 合并批量成员管理命令
	shortcuts = append(shortcuts, BatchMemberShortcuts()...)

	return shortcuts
}
