package cmd

import (
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"os"
	"strings"

	"github.com/spf13/cobra"
)

func authCmd() *cobra.Command {
	cmd := &cobra.Command{
		Use:   "auth",
		Short: "Authenticate with LLM providers via OAuth",
		Long:  "Manage OAuth authentication via the running gateway. Requires the gateway to be running.",
	}
	cmd.AddCommand(authStatusCmd())
	cmd.AddCommand(authLogoutCmd())
	return cmd
}

// gatewayURL returns the base URL for the running gateway.
func gatewayURL() string {
	if u := os.Getenv("GOCLAW_GATEWAY_URL"); u != "" {
		return strings.TrimRight(u, "/")
	}
	host := os.Getenv("GOCLAW_HOST")
	if host == "" {
		host = "127.0.0.1"
	}
	port := os.Getenv("GOCLAW_PORT")
	if port == "" {
		port = "3577"
	}
	return fmt.Sprintf("http://%s:%s", host, port)
}

// gatewayRequest sends an authenticated request to the running gateway.
func gatewayRequest(method, path string) (map[string]any, error) {
	url := gatewayURL() + path
	req, err := http.NewRequest(method, url, nil)
	if err != nil {
		return nil, err
	}

	if token := os.Getenv("GOCLAW_TOKEN"); token != "" {
		req.Header.Set("Authorization", "Bearer "+token)
	}

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		return nil, fmt.Errorf("cannot reach gateway at %s: %w", gatewayURL(), err)
	}
	defer resp.Body.Close()

	body, _ := io.ReadAll(io.LimitReader(resp.Body, 1<<20))
	var result map[string]any
	if err := json.Unmarshal(body, &result); err != nil {
		return nil, fmt.Errorf("invalid response from gateway: %s", string(body))
	}

	if resp.StatusCode >= 400 {
		if msg, ok := result["error"].(string); ok {
			return nil, fmt.Errorf("gateway error: %s", msg)
		}
		return nil, fmt.Errorf("gateway returned status %d", resp.StatusCode)
	}

	return result, nil
}

func authStatusCmd() *cobra.Command {
	return &cobra.Command{
		Use:   "status",
		Short: "Show OAuth authentication status",
		Long:  "Check if ChatGPT OAuth is configured on the running gateway.",
		RunE: func(cmd *cobra.Command, args []string) error {
			result, err := gatewayRequest("GET", "/v1/auth/openai/status")
			if err != nil {
				return err
			}

			if auth, _ := result["authenticated"].(bool); auth {
				name, _ := result["provider_name"].(string)
				fmt.Printf("OpenAI OAuth: active (provider: %s)\n", name)
				fmt.Println("Use model prefix 'openai-codex/' in agent config (e.g. openai-codex/gpt-4o).")
			} else {
				fmt.Println("No OAuth tokens found.")
				fmt.Println("Use the web UI to authenticate with ChatGPT OAuth.")
			}
			return nil
		},
	}
}

func authLogoutCmd() *cobra.Command {
	return &cobra.Command{
		Use:   "logout [provider]",
		Short: "Remove stored OAuth tokens",
		Args:  cobra.MaximumNArgs(1),
		RunE: func(cmd *cobra.Command, args []string) error {
			provider := "openai"
			if len(args) > 0 {
				provider = args[0]
			}

			if provider != "openai" {
				return fmt.Errorf("unknown provider: %s (supported: openai)", provider)
			}

			_, err := gatewayRequest("POST", "/v1/auth/openai/logout")
			if err != nil {
				return err
			}

			fmt.Println("OpenAI OAuth token removed.")
			return nil
		},
	}
}
