package cmd

import (
	"cursor-api-proxy/internal/agent"
	"encoding/json"
	"fmt"
	"os"
	"path/filepath"
)

type AccountInfo struct {
	Name               string
	ConfigDir          string
	Authenticated      bool
	Email              string
	DisplayName        string
	AuthID             string
	Plan               string
	SubscriptionStatus string
	ExpiresAt          string
}

func ReadAccountInfo(name, configDir string) AccountInfo {
	info := AccountInfo{Name: name, ConfigDir: configDir}

	configFile := filepath.Join(configDir, "cli-config.json")
	data, err := os.ReadFile(configFile)
	if err != nil {
		return info
	}

	var raw struct {
		AuthInfo *struct {
			Email       string `json:"email"`
			DisplayName string `json:"displayName"`
			AuthID      string `json:"authId"`
		} `json:"authInfo"`
	}
	if err := json.Unmarshal(data, &raw); err == nil && raw.AuthInfo != nil {
		info.Authenticated = true
		info.Email = raw.AuthInfo.Email
		info.DisplayName = raw.AuthInfo.DisplayName
		info.AuthID = raw.AuthInfo.AuthID
	}

	statsigFile := filepath.Join(configDir, "statsig-cache.json")
	statsigData, err := os.ReadFile(statsigFile)
	if err != nil {
		return info
	}

	var statsigWrapper struct {
		Data string `json:"data"`
	}
	if err := json.Unmarshal(statsigData, &statsigWrapper); err != nil || statsigWrapper.Data == "" {
		return info
	}

	var statsig struct {
		User *struct {
			Custom *struct {
				IsEnterpriseUser           bool   `json:"isEnterpriseUser"`
				StripeSubscriptionStatus   string `json:"stripeSubscriptionStatus"`
				StripeMembershipExpiration string `json:"stripeMembershipExpiration"`
			} `json:"custom"`
		} `json:"user"`
	}
	if err := json.Unmarshal([]byte(statsigWrapper.Data), &statsig); err != nil {
		return info
	}

	if statsig.User != nil && statsig.User.Custom != nil {
		c := statsig.User.Custom
		if c.IsEnterpriseUser {
			info.Plan = "Enterprise"
		} else if c.StripeSubscriptionStatus == "active" {
			info.Plan = "Pro"
		} else {
			info.Plan = "Free"
		}
		info.SubscriptionStatus = c.StripeSubscriptionStatus
		info.ExpiresAt = c.StripeMembershipExpiration
	}

	return info
}

func HandleAccountsList() error {
	accountsDir := agent.AccountsDir()

	entries, err := os.ReadDir(accountsDir)
	if err != nil {
		fmt.Println("No accounts found. Use 'cursor-api-proxy login' to add one.")
		return nil
	}

	var names []string
	for _, e := range entries {
		if e.IsDir() {
			names = append(names, e.Name())
		}
	}

	if len(names) == 0 {
		fmt.Println("No accounts found. Use 'cursor-api-proxy login' to add one.")
		return nil
	}

	fmt.Print("Cursor Accounts:\n\n")

	keychainToken := agent.ReadKeychainToken()

	for i, name := range names {
		configDir := filepath.Join(accountsDir, name)
		info := ReadAccountInfo(name, configDir)

		fmt.Printf("  %d. %s\n", i+1, name)

		if info.Authenticated {
			cachedToken := agent.ReadCachedToken(configDir)
			keychainMatchesAccount := keychainToken != "" && info.AuthID != "" && TokenSub(keychainToken) == info.AuthID
			token := cachedToken
			if token == "" && keychainMatchesAccount {
				token = keychainToken
			}

			var liveProfile *StripeProfile
			var liveUsage *UsageData
			if token != "" {
				liveUsage, _ = FetchAccountUsage(token)
				liveProfile, _ = FetchStripeProfile(token)
			}

			if info.Email != "" {
				display := ""
				if info.DisplayName != "" {
					display = " (" + info.DisplayName + ")"
				}
				fmt.Printf("     %s%s\n", info.Email, display)
			}

			if info.Plan != "" && liveProfile == nil {
				canceled := ""
				if info.SubscriptionStatus == "canceled" {
					canceled = " · canceled"
				}
				expiry := ""
				if info.ExpiresAt != "" {
					expiry = " · expires " + info.ExpiresAt
				}
				fmt.Printf("     %s%s%s\n", info.Plan, canceled, expiry)
			}
			fmt.Println("     Authenticated")

			if liveProfile != nil {
				fmt.Printf("     %s\n", DescribePlan(liveProfile))
			}
			if liveUsage != nil {
				for _, line := range FormatUsageSummary(liveUsage) {
					fmt.Println(line)
				}
			}
		} else {
			fmt.Println("     Not authenticated")
		}

		fmt.Println("")
	}

	fmt.Println("Tip: run 'cursor-api-proxy logout <name>' to remove an account.")
	return nil
}

func HandleLogout(accountName string) error {
	if accountName == "" {
		fmt.Fprintln(os.Stderr, "Error: Please specify the account name to remove.")
		fmt.Fprintln(os.Stderr, "Usage: cursor-api-proxy logout <account-name>")
		os.Exit(1)
	}

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

	if _, err := os.Stat(configDir); os.IsNotExist(err) {
		fmt.Fprintf(os.Stderr, "Account '%s' not found.\n", accountName)
		os.Exit(1)
	}

	if err := os.RemoveAll(configDir); err != nil {
		fmt.Fprintf(os.Stderr, "Error removing account: %v\n", err)
		os.Exit(1)
	}

	fmt.Printf("Account '%s' removed.\n", accountName)
	return nil
}
