package org

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

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

func Shortcuts() []*common.Shortcut {
	shortcuts := []*common.Shortcut{
		{
			Name:        "list",
			Description: "List organizations",
			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 {
				q := url.Values{}
				q.Set("page", ctx.Arg("page"))
				q.Set("limit", ctx.Arg("limit"))
				env, err := ctx.CallAPIWithQuery("GET", "/organizations", q)
				if err != nil {
					return fmt.Errorf("获取组织列表失败: %w", err)
				}
				return ctx.Output(env)
			},
		},
		{
			Name:        "info",
			Description: "Show organization details",
			Flags: []common.Flag{
				{Name: "id", Short: "i", Usage: "Organization ID or login", Required: true},
			},
			Run: func(ctx *common.RuntimeContext) error {
				id, err := ctx.RequireArg("id", "--id my-org")
				if err != nil {
					return err
				}
				env, err := ctx.CallAPI("GET", fmt.Sprintf("/organizations/%s", id), nil)
				if err != nil {
					return fmt.Errorf("查看组织失败: %w", err)
				}
				return ctx.Output(env)
			},
		},
		{
			Name:        "members",
			Description: "List organization members",
			Flags: []common.Flag{
				{Name: "id", Short: "i", Usage: "Organization ID", Required: true},
				{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 {
				id, err := ctx.RequireArg("id", "--id my-org")
				if err != nil {
					return err
				}
				q := url.Values{}
				q.Set("page", ctx.Arg("page"))
				q.Set("limit", ctx.Arg("limit"))
				env, err := ctx.CallAPIWithQuery("GET", fmt.Sprintf("/organizations/%s/organization_users", id), q)
				if err != nil {
					return fmt.Errorf("获取组织成员失败: %w", err)
				}
				return ctx.Output(env)
			},
		},
		{
			Name:        "create",
			Description: "Create an organization",
			DryRun:      true,
			DryRunHint: func(ctx *common.RuntimeContext) (string, error) {
				name := ctx.Arg("name")
				return fmt.Sprintf("Create organization: %s", name), nil
			},
			Flags: []common.Flag{
				{Name: "name", Short: "n", Usage: "Organization name", Required: true},
				{Name: "description", Short: "d", Usage: "Description"},
			},
			Run: func(ctx *common.RuntimeContext) error {
				name, err := ctx.RequireArg("name", `--name "My Organization"`)
				if err != nil {
					return err
				}
				payload := map[string]interface{}{
					"name": name,
				}
				if d := ctx.Arg("description"); d != "" {
					payload["description"] = d
				}
				env, err := ctx.CallAPI("POST", "/organizations", payload)
				if err != nil {
					return fmt.Errorf("创建组织失败: %w", err)
				}
				return ctx.Output(env)
			},
		},
		{
			Name:        "update",
			Description: "Update an organization",
			Flags: []common.Flag{
				{Name: "id", Short: "i", Usage: "Organization ID", Required: true},
				{Name: "name", Short: "n", Usage: "New name"},
				{Name: "description", Short: "d", Usage: "New description"},
			},
			Run: func(ctx *common.RuntimeContext) error {
				id, _ := ctx.RequireArg("id", "--id my-org")
				body := map[string]interface{}{}
				if n := ctx.Arg("name"); n != "" {
					body["name"] = n
				}
				if d := ctx.Arg("description"); d != "" {
					body["description"] = d
				}
				if len(body) == 0 {
					return fmt.Errorf("at least one of --name, --description is required")
				}
				env, err := ctx.CallAPI("PATCH", fmt.Sprintf("/organizations/%s", id), body)
				if err != nil {
					return err
				}
				return ctx.Output(env)
			},
		},
		{
			Name:        "delete",
			Description: "Delete an organization",
			Flags: []common.Flag{
				{Name: "id", Short: "i", Usage: "Organization ID", Required: true},
			},
			Run: func(ctx *common.RuntimeContext) error {
				id, _ := ctx.RequireArg("id", "--id my-org")
				env, err := ctx.CallAPI("DELETE", fmt.Sprintf("/organizations/%s", id), nil)
				if err != nil {
					return err
				}
				return ctx.Output(env)
			},
		},
		{
			Name:        "invite",
			Description: "Invite a member to a project",
			DryRun:      true,
			DryRunHint: func(ctx *common.RuntimeContext) (string, error) {
				userID := ctx.Arg("user-id")
				owner := ctx.Arg("owner")
				repo := ctx.Arg("repo")
				return fmt.Sprintf("Invite user %s to %s/%s", userID, owner, repo), nil
			},
			Flags: []common.Flag{
				{Name: "user-id", Usage: "User ID to invite (required)", Required: true},
				{Name: "owner", Short: "o", Usage: "Project owner (e.g., zzx-coder)", Required: true},
				{Name: "repo", Short: "r", Usage: "Project repo name (e.g., gitlink-cli)", Required: true},
			},
			Run: func(ctx *common.RuntimeContext) error {
				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)
				}

				return inviteToOrgProjects(ctx, []int{uid}, false)
			},
		},
		{
			Name:        "remove-member",
			Description: "Remove a member from a project",
			DryRun:      true,
			DryRunHint: func(ctx *common.RuntimeContext) (string, error) {
				userID := ctx.Arg("user-id")
				owner := ctx.Arg("owner")
				repo := ctx.Arg("repo")
				return fmt.Sprintf("Remove user %s from %s/%s", userID, owner, repo), nil
			},
			Flags: []common.Flag{
				{Name: "user-id", Usage: "User ID to remove (required)", Required: true},
				{Name: "owner", Short: "o", Usage: "Project owner (e.g., zzx-coder)", Required: true},
				{Name: "repo", Short: "r", Usage: "Project repo name (e.g., gitlink-cli)", Required: true},
			},
			Run: func(ctx *common.RuntimeContext) error {
				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)
				}

				return removeFromOrgProjects(ctx, []int{uid}, false)
			},
		},
	}

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

	return shortcuts
}

// inviteToOrgProjects 向指定项目邀请用户
func inviteToOrgProjects(ctx *common.RuntimeContext, userIDs []int, dryRun bool) error {
	owner, repo, err := resolveOrgProject(ctx)
	if err != nil {
		return err
	}

	results := make([]map[string]interface{}, 0, len(userIDs))
	for _, uid := range userIDs {
		if dryRun {
			results = append(results, map[string]interface{}{
				"user_id": uid,
				"project": fmt.Sprintf("%s/%s", owner, repo),
				"action":  "invite",
				"status":  "would execute (dry-run)",
			})
			continue
		}

		body := map[string]interface{}{"user_id": uid}
		_, err := ctx.CallAPI("POST", fmt.Sprintf("/%s/%s/collaborators", owner, repo), body)
		status := "success"
		msg := ""
		if err != nil {
			status = "failed"
			msg = err.Error()
		}
		results = append(results, map[string]interface{}{
			"user_id": uid,
			"project": fmt.Sprintf("%s/%s", owner, repo),
			"action":  "invite",
			"status":  status,
			"message": msg,
		})
	}

	return ctx.OutputData(results)
}

// removeFromOrgProjects 从指定项目移除用户
func removeFromOrgProjects(ctx *common.RuntimeContext, userIDs []int, dryRun bool) error {
	owner, repo, err := resolveOrgProject(ctx)
	if err != nil {
		return err
	}

	results := make([]map[string]interface{}, 0, len(userIDs))
	for _, uid := range userIDs {
		if dryRun {
			results = append(results, map[string]interface{}{
				"user_id": uid,
				"project": fmt.Sprintf("%s/%s", owner, repo),
				"action":  "remove",
				"status":  "would execute (dry-run)",
			})
			continue
		}

		body := map[string]interface{}{"user_id": uid}
		_, err := ctx.CallAPI("DELETE", fmt.Sprintf("/%s/%s/collaborators/remove", owner, repo), body)
		status := "success"
		msg := ""
		if err != nil {
			status = "failed"
			msg = err.Error()
		}
		results = append(results, map[string]interface{}{
			"user_id": uid,
			"project": fmt.Sprintf("%s/%s", owner, repo),
			"action":  "remove",
			"status":  status,
			"message": msg,
		})
	}

	return ctx.OutputData(results)
}

// resolveOrgProject 从 --owner/--repo 解析目标项目
func resolveOrgProject(ctx *common.RuntimeContext) (owner, repo string, err error) {
	owner = ctx.Arg("owner")
	repo = ctx.Arg("repo")
	if owner == "" || repo == "" {
		return "", "", fmt.Errorf("must specify --owner and --repo (e.g., --owner zzx-coder --repo gitlink-cli)")
	}
	return owner, repo, nil
}

// parseUserIDList 解析逗号分隔的用户ID字符串
func parseUserIDList(input string) ([]int, error) {
	var ids []int
	for _, s := range strings.Split(input, ",") {
		s = strings.TrimSpace(s)
		if s == "" {
			continue
		}
		uid, err := strconv.Atoi(s)
		if err != nil {
			return nil, fmt.Errorf("invalid user ID: %s", s)
		}
		ids = append(ids, uid)
	}
	if len(ids) == 0 {
		return nil, fmt.Errorf("no valid user IDs found")
	}
	return ids, nil
}
