package config

import (
	"encoding/json"
	"fmt"
	"os"
	"time"

	"github.com/fujin/anthropic-proxy/internal/auth"
	"gopkg.in/yaml.v3"
)

type Config struct {
	Port         int            `yaml:"port"`
	APIKeys      []string       `yaml:"api_keys"`
	ClaudeBinary string         `yaml:"claude_binary"`
	Sanitize     SanitizeConfig `yaml:"sanitize"`
	Logging      LoggingConfig  `yaml:"logging"`
}

type SanitizeConfig struct {
	Tools  []RenameRule  `yaml:"tools"`
	System []ReplaceRule `yaml:"system"`
	Body   []ReplaceRule `yaml:"body"`
}

type RenameRule struct {
	From string `yaml:"from"`
	To   string `yaml:"to"`
}

type ReplaceRule struct {
	Match   string `yaml:"match"`
	Replace string `yaml:"replace"`
}

type LoggingConfig struct {
	Level      string `yaml:"level"`
	File       string `yaml:"file"`
	MaxSizeMB  int    `yaml:"max_size_mb"`
	MaxBackups int    `yaml:"max_backups"`
	MaxAgeDays int    `yaml:"max_age_days"`
	Compress   bool   `yaml:"compress"`
}

type claudeCredentialsJSON struct {
	ClaudeAiOauth struct {
		AccessToken      string `json:"accessToken"`
		RefreshToken     string `json:"refreshToken"`
		ExpiresAt        int64  `json:"expiresAt"`
		SubscriptionType string `json:"subscriptionType"`
	} `json:"claudeAiOauth"`
}

func Load(path string) (*Config, error) {
	data, err := os.ReadFile(path)
	if err != nil {
		return nil, fmt.Errorf("read config %s: %w", path, err)
	}

	cfg := &Config{Port: 8080}
	if err := yaml.Unmarshal(data, cfg); err != nil {
		return nil, fmt.Errorf("parse config: %w", err)
	}

	if cfg.Logging.Level == "" {
		cfg.Logging.Level = "info"
	}
	if cfg.Logging.MaxSizeMB == 0 {
		cfg.Logging.MaxSizeMB = 100
	}
	if cfg.Logging.MaxBackups == 0 {
		cfg.Logging.MaxBackups = 5
	}
	if cfg.Logging.MaxAgeDays == 0 {
		cfg.Logging.MaxAgeDays = 30
	}

	// Check for deprecated claude_credentials field
	var rawCfg map[string]interface{}
	if err := yaml.Unmarshal(data, &rawCfg); err == nil {
		if _, exists := rawCfg["claude_credentials"]; exists {
			if val, ok := rawCfg["claude_credentials"].(string); ok && val != "" {
				return nil, fmt.Errorf("claude_credentials is no longer supported, remove it from config.yaml — the proxy now manages credentials at ~/.claude/.credentials.json")
			}
		}
	}

	return cfg, nil
}

func DefaultCredentialPath() string {
	home, err := os.UserHomeDir()
	if err != nil {
		return ""
	}
	return home + "/.claude/.credentials.json"
}

func LoadDefaultCredentials() ([]*auth.Credential, error) {
	path := DefaultCredentialPath()
	if path == "" {
		return nil, nil
	}

	data, err := os.ReadFile(path)
	if err != nil {
		if os.IsNotExist(err) {
			return nil, nil
		}
		return nil, err
	}

	var cf claudeCredentialsJSON
	if err := json.Unmarshal(data, &cf); err != nil {
		return nil, err
	}

	oauth := cf.ClaudeAiOauth
	if oauth.AccessToken == "" {
		return nil, fmt.Errorf("no access token in %s", path)
	}

	cred := &auth.Credential{
		ID:           "claude-native",
		Email:        oauth.SubscriptionType,
		AccessToken:  oauth.AccessToken,
		RefreshToken: oauth.RefreshToken,
		ExpiresAt:    time.UnixMilli(oauth.ExpiresAt),
		FilePath:     path,
	}

	return []*auth.Credential{cred}, nil
}
