package policies

import (
	"fmt"
	"io"
	"os"

	"github.com/spf13/cobra"
	"github.com/stephnangue/warden/cmd/helpers"
)

var WriteCmd = &cobra.Command{
	Use:           "write <name> <policy_file>",
	SilenceUsage:  true,
	SilenceErrors: true,
	Short:         "Write a policy",
	Long: `
Usage: warden policy write <name> <policy_file>

  Writes a capability-based policy. The policy can be read from a file
  or from stdin by using "-" as the filename.

  Examples:

    Write a policy from stdin:

      $ warden policy write my-policy - <<EOF
      path "secret/data/myapp/*" {
        capabilities = ["create", "read", "update", "delete", "list"]
      }

      path "secret/metadata/myapp/*" {
        capabilities = ["list", "read", "delete"]
      }
      EOF

    Write a policy from a file:

      $ warden policy write my-policy ./policy.hcl
`,
	Args: cobra.ExactArgs(2),
	RunE: runWrite,
}

func runWrite(cmd *cobra.Command, args []string) error {
	name := args[0]
	policyPath := args[1]
	if err := helpers.ValidatePath(name); err != nil {
		return err
	}

	// Read policy content
	var policyContent string
	if policyPath == "-" {
		// Read from stdin
		bytes, err := io.ReadAll(os.Stdin)
		if err != nil {
			return fmt.Errorf("failed to read from stdin: %w", err)
		}
		policyContent = string(bytes)
	} else {
		// Read from file
		bytes, err := os.ReadFile(policyPath)
		if err != nil {
			return fmt.Errorf("failed to read policy file: %w", err)
		}
		policyContent = string(bytes)
	}

	if policyContent == "" {
		return fmt.Errorf("policy content cannot be empty: %w", helpers.ErrInvalidInput)
	}

	// Create the client
	c, err := helpers.Client()
	if err != nil {
		return err
	}

	if helpers.ResolveDryRun() {
		payload := map[string]any{"policy": policyContent}
		return helpers.DryRun(c, "PUT", "sys/policies/{name}", payload)
	}

	// Write the policy
	err = c.Sys().PutPolicy(name, policyContent)
	if err != nil {
		return fmt.Errorf("error writing policy: %w", err)
	}

	return helpers.RenderMap(map[string]any{"name": name, "written": true}, func() {
		fmt.Printf("Success! Uploaded policy: %s\n", name)
	})
}
