package wrapper

import (
	"encoding/json"
	"fmt"
	"ipa/IPAGo/constants"
	"os/exec"
	"strings"
)

func Auth(user, pswd, code string) bool {
	command := ""
	if code == "" {
		command = fmt.Sprintf("auth login -e %s -p %s", user, pswd)
	} else {
		command = fmt.Sprintf("auth login -e %s -p %s --auth-code %s", user, pswd, code)
	}
	command += " " + constants.GlobalFlags
	out, err := run(command)
	if err != nil {
		fmt.Printf("error: %v\n", err)
		return false
	}
	result, ok := out["success"].(bool)
	if !ok {
		return false
	}
	return result
}

func AuthInfo(user, pswd string) bool {
	command := fmt.Sprintf("%s auth info", constants.GlobalFlags)
	out, err := run(command)
	if err != nil {
		return false
	}
	result, ok := out["success"].(bool)
	if !ok {
		return false
	}
	return result
}

type App struct {
	BundleID string `json:"bundleID"`
	Version  string `json:"version"`
}

func Search(query string, limit int) ([]App, error) {
	command := fmt.Sprintf("%s search %s -l %d", constants.GlobalFlags, query, limit)
	out, err := run(command)
	if err != nil {
		return nil, err
	}
	apps, ok := out["apps"].([]any)
	fmt.Println("apps", apps)
	if !ok {
		return nil, fmt.Errorf("failed to get apps")
	}
	appsList := make([]App, len(apps))
	for i, app := range apps {
		app, ok := app.(map[string]any)
		if !ok {
			return nil, fmt.Errorf("failed to get app")
		}
		appsList[i] = App{
			BundleID: app["bundleID"].(string),
			Version:  app["version"].(string),
		}
	}
	return appsList, nil
}

func Download(bundleID string, outputPath string) bool {
	command := fmt.Sprintf(
		"download -b %s -o %s %s",
		bundleID, outputPath, constants.GlobalFlags,
	)
	out, err := run(command)
	if err != nil {
		return false
	}
	result, ok := out["success"].(bool)
	if !ok {
		return false
	}
	return result
}

func run(command string) (map[string]any, error) {
	fmt.Println("command", command)
	cmd := exec.Command(constants.IPAToolPath, strings.Split(command, " ")...)
	out, err := cmd.CombinedOutput()
	if err != nil {
		fmt.Println(string(out))
		return nil, err
	}
	if cmd.ProcessState.ExitCode() != 0 {
		fmt.Println(string(out))
		return nil, fmt.Errorf(
			"command failed with exit code %d: %s",
			cmd.ProcessState.ExitCode(), string(out),
		)
	}
	var result map[string]any
	err = json.Unmarshal(out, &result)
	if err != nil {
		fmt.Println(string(out))
		return nil, fmt.Errorf("failed to unmarshal output: %s", err)
	}
	fmt.Println("result", result)
	return result, nil
}
