package cmd

import (
	"bufio"
	"cursor-api-proxy/internal/agent"
	"cursor-api-proxy/internal/env"
	"fmt"
	"os"
	"os/exec"
	"os/signal"
	"path/filepath"
	"regexp"
	"syscall"
	"time"
)

var loginURLRe = regexp.MustCompile(`https://cursor\.com/loginDeepControl.*?redirectTarget=cli`)

func HandleLogin(accountName string, proxies []string) error {
	e := env.OsEnvToMap()
	loaded := env.LoadEnvConfig(e, "")
	agentBin := loaded.AgentBin

	if accountName == "" {
		accountName = fmt.Sprintf("account-%d", time.Now().UnixMilli()%10000)
	}

	accountsDir := agent.AccountsDir()
	configDir := filepath.Join(accountsDir, accountName)
	dirWasNew := !fileExists(configDir)

	if err := os.MkdirAll(accountsDir, 0755); err != nil {
		return fmt.Errorf("failed to create accounts dir: %w", err)
	}
	if err := os.MkdirAll(configDir, 0755); err != nil {
		return fmt.Errorf("failed to create config dir: %w", err)
	}

	fmt.Printf("Logging into Cursor account: %s\n", accountName)
	fmt.Printf("Config: %s\n\n", configDir)
	fmt.Println("Run the login command — complete the login in your browser.")
	fmt.Println("")

	cleanupDir := func() {
		if dirWasNew {
			_ = os.RemoveAll(configDir)
		}
	}

	cmdEnv := make([]string, 0, len(e)+2)
	for k, v := range e {
		cmdEnv = append(cmdEnv, k+"="+v)
	}
	cmdEnv = append(cmdEnv, "CURSOR_CONFIG_DIR="+configDir)
	cmdEnv = append(cmdEnv, "NO_OPEN_BROWSER=1")

	child := exec.Command(agentBin, "login")
	child.Env = cmdEnv
	child.Stdin = os.Stdin
	child.Stderr = os.Stderr

	stdoutPipe, err := child.StdoutPipe()
	if err != nil {
		return fmt.Errorf("failed to create stdout pipe: %w", err)
	}

	if err := child.Start(); err != nil {
		cleanupDir()
		if os.IsNotExist(err) {
			return fmt.Errorf("could not find '%s'. Make sure the Cursor CLI is installed", agentBin)
		}
		return fmt.Errorf("error launching agent login: %w", err)
	}

	// Handle cancellation signals
	sigCh := make(chan os.Signal, 1)
	signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP)
	go func() {
		sig := <-sigCh
		_ = child.Process.Kill()
		cleanupDir()
		if sig == syscall.SIGINT {
			fmt.Println("\n\nLogin cancelled.")
		}
		os.Exit(0)
	}()
	defer signal.Stop(sigCh)

	var stdoutBuf string
	scanner := bufio.NewScanner(stdoutPipe)
	for scanner.Scan() {
		line := scanner.Text()
		fmt.Println(line)
		stdoutBuf += line + "\n"

		if loginURLRe.MatchString(stdoutBuf) {
			match := loginURLRe.FindString(stdoutBuf)
			if match != "" {
				fmt.Printf("\nOpen this URL in your browser (incognito recommended):\n%s\n\n", match)
			}
		}
	}

	if err := child.Wait(); err != nil {
		if exitErr, ok := err.(*exec.ExitError); ok {
			cleanupDir()
			return fmt.Errorf("login failed with code %d", exitErr.ExitCode())
		}
		return err
	}

	// Cache keychain token for this account
	token := agent.ReadKeychainToken()
	if token != "" {
		agent.WriteCachedToken(configDir, token)
	}

	fmt.Printf("\nAccount '%s' saved — it will be auto-discovered when you start the proxy.\n", accountName)
	return nil
}

func fileExists(path string) bool {
	_, err := os.Stat(path)
	return err == nil
}
