// Copyright 2026 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT

package cmd

import (
	"bufio"
	"fmt"
	"os"
	"path/filepath"
	"strings"
	"syscall"

	"github.com/spf13/cobra"
	"github.com/spf13/viper"
	"golang.org/x/term"
	"gopkg.in/yaml.v3"
)

var authCmd = &cobra.Command{
	Use:   "auth",
	Short: "Manage authentication",
	Long:  `Manage authentication to Gitea servers.`,
}

var loginCmd = &cobra.Command{
	Use:   "login",
	Short: "Login to a Gitea server",
	Long: `Login to a Gitea server and save credentials.

The credentials are stored in ~/.gitea-cli.yaml and used for subsequent commands.`,
	RunE: runLogin,
}

var logoutCmd = &cobra.Command{
	Use:   "logout",
	Short: "Logout from the current server",
	RunE:  runLogout,
}

var statusCmd = &cobra.Command{
	Use:   "status",
	Short: "Show authentication status",
	RunE:  runStatus,
}

func init() {
	loginCmd.Flags().String("server", "", "Gitea server URL (required)")
	loginCmd.Flags().String("token", "", "API token (if not provided, will prompt)")
	loginCmd.MarkFlagRequired("server")

	authCmd.AddCommand(loginCmd)
	authCmd.AddCommand(logoutCmd)
	authCmd.AddCommand(statusCmd)
}

func runLogin(cmd *cobra.Command, args []string) error {
	server, _ := cmd.Flags().GetString("server")
	tokenFlag, _ := cmd.Flags().GetString("token")

	// Normalize server URL
	server = strings.TrimSuffix(server, "/")
	if !strings.HasPrefix(server, "http://") && !strings.HasPrefix(server, "https://") {
		server = "https://" + server
	}

	var apiToken string
	if tokenFlag != "" {
		apiToken = tokenFlag
	} else {
		// Prompt for token
		fmt.Print("API Token: ")
		byteToken, err := term.ReadPassword(int(syscall.Stdin))
		if err != nil {
			// Fallback if terminal not available
			reader := bufio.NewReader(os.Stdin)
			apiToken, _ = reader.ReadString('\n')
			apiToken = strings.TrimSpace(apiToken)
		} else {
			apiToken = string(byteToken)
			fmt.Println() // New line after password
		}
	}

	if apiToken == "" {
		return fmt.Errorf("token is required")
	}

	// Verify the token works
	fmt.Printf("Verifying credentials with %s...\n", server)

	// TODO: Make actual API call to verify token
	// For now, just save the config

	// Save configuration
	config := map[string]string{
		"server": server,
		"token":  apiToken,
	}

	home, err := os.UserHomeDir()
	if err != nil {
		return fmt.Errorf("failed to get home directory: %w", err)
	}

	configPath := filepath.Join(home, ".gitea-cli.yaml")
	data, err := yaml.Marshal(config)
	if err != nil {
		return fmt.Errorf("failed to marshal config: %w", err)
	}

	if err := os.WriteFile(configPath, data, 0600); err != nil {
		return fmt.Errorf("failed to write config: %w", err)
	}

	fmt.Printf("✓ Logged in to %s\n", server)
	fmt.Printf("  Configuration saved to %s\n", configPath)

	return nil
}

func runLogout(cmd *cobra.Command, args []string) error {
	home, err := os.UserHomeDir()
	if err != nil {
		return fmt.Errorf("failed to get home directory: %w", err)
	}

	configPath := filepath.Join(home, ".gitea-cli.yaml")

	if _, err := os.Stat(configPath); os.IsNotExist(err) {
		fmt.Println("Not currently logged in")
		return nil
	}

	if err := os.Remove(configPath); err != nil {
		return fmt.Errorf("failed to remove config: %w", err)
	}

	fmt.Println("✓ Logged out successfully")
	return nil
}

func runStatus(cmd *cobra.Command, args []string) error {
	server := viper.GetString("server")
	token := viper.GetString("token")

	if server == "" || token == "" {
		fmt.Println("Not logged in")
		fmt.Println("\nUse 'gitea-cli auth login --server <url>' to authenticate")
		return nil
	}

	// Mask token for display
	maskedToken := token
	if len(token) > 8 {
		maskedToken = token[:4] + "..." + token[len(token)-4:]
	}

	fmt.Printf("Server: %s\n", server)
	fmt.Printf("Token:  %s\n", maskedToken)

	// TODO: Verify token is still valid with API call

	return nil
}
