package emailmonitor

import (
	"encoding/base64"
	"fmt"
	"os"
	"strings"
	"time"
)

const (
	defaultPollInterval  = 2 * time.Minute
	defaultHistoryWindow = 24 * time.Hour
	defaultStatePath     = "email_monitor_state.json"
	defaultMonitorMode   = "poll"
	defaultWatchRenewal  = 24 * time.Hour
)

// Config holds runtime configuration for email monitoring.
type Config struct {
	Enabled            bool
	Mode               string
	PollInterval       time.Duration
	HistoryWindow      time.Duration
	WatchRenewal       time.Duration
	GCPProject         string
	PubSubTopic        string
	PubSubSubscription string
	Mailbox            string
	Senders            []string
	ServiceJSON        []byte
	OAuthClientID      string
	OAuthClientSecret  string
	OAuthRefreshToken  string
	WebhookURL         string
	StatePath          string
}

// LoadConfigFromEnv builds configuration from environment variables.
func LoadConfigFromEnv() (*Config, error) {
	saJSONB64 := strings.TrimSpace(os.Getenv("EMAIL_MONITOR_SA_JSON_B64"))
	mailbox := strings.TrimSpace(os.Getenv("EMAIL_MONITOR_IMPERSONATE_USER"))
	oauthClientID := strings.TrimSpace(os.Getenv("EMAIL_MONITOR_OAUTH_CLIENT_ID"))
	oauthClientSecret := strings.TrimSpace(os.Getenv("EMAIL_MONITOR_OAUTH_CLIENT_SECRET"))
	oauthRefreshToken := strings.TrimSpace(os.Getenv("EMAIL_MONITOR_OAUTH_REFRESH_TOKEN"))
	sendersRaw := strings.TrimSpace(os.Getenv("EMAIL_MONITOR_SENDERS"))
	webhook := strings.TrimSpace(os.Getenv("FEISHU_WEBHOOK"))

	if saJSONB64 == "" && mailbox == "" && oauthClientID == "" && oauthClientSecret == "" && oauthRefreshToken == "" && sendersRaw == "" && webhook == "" {
		return &Config{Enabled: false}, nil
	}

	useOAuth := oauthClientID != "" || oauthClientSecret != "" || oauthRefreshToken != ""
	if useOAuth {
		if oauthClientID == "" {
			return nil, fmt.Errorf("EMAIL_MONITOR_OAUTH_CLIENT_ID is required when using OAuth")
		}
		if oauthClientSecret == "" {
			return nil, fmt.Errorf("EMAIL_MONITOR_OAUTH_CLIENT_SECRET is required when using OAuth")
		}
		if oauthRefreshToken == "" {
			return nil, fmt.Errorf("EMAIL_MONITOR_OAUTH_REFRESH_TOKEN is required when using OAuth")
		}
		if mailbox == "" {
			mailbox = "me"
		}
	} else {
		if saJSONB64 == "" {
			return nil, fmt.Errorf("EMAIL_MONITOR_SA_JSON_B64 is required")
		}
		if mailbox == "" {
			return nil, fmt.Errorf("EMAIL_MONITOR_IMPERSONATE_USER is required")
		}
	}
	if sendersRaw == "" {
		return nil, fmt.Errorf("EMAIL_MONITOR_SENDERS is required")
	}
	if webhook == "" {
		return nil, fmt.Errorf("FEISHU_WEBHOOK is required for email alerts")
	}

	var saJSON []byte
	if saJSONB64 != "" {
		decoded, err := decodeBase64(saJSONB64)
		if err != nil {
			return nil, fmt.Errorf("failed to decode EMAIL_MONITOR_SA_JSON_B64: %w", err)
		}
		saJSON = decoded
	}

	senders := parseSenders(sendersRaw)
	if len(senders) == 0 {
		return nil, fmt.Errorf("EMAIL_MONITOR_SENDERS must include at least one sender")
	}

	mode := strings.ToLower(strings.TrimSpace(os.Getenv("EMAIL_MONITOR_MODE")))
	if mode == "" {
		mode = defaultMonitorMode
	}
	if mode != "poll" && mode != "watch" {
		return nil, fmt.Errorf("EMAIL_MONITOR_MODE must be 'poll' or 'watch'")
	}

	pollInterval := defaultPollInterval
	if val := strings.TrimSpace(os.Getenv("EMAIL_MONITOR_POLL_INTERVAL")); val != "" {
		parsed, err := time.ParseDuration(val)
		if err != nil {
			return nil, fmt.Errorf("invalid EMAIL_MONITOR_POLL_INTERVAL: %w", err)
		}
		pollInterval = parsed
	}

	historyWindow := defaultHistoryWindow
	if val := strings.TrimSpace(os.Getenv("EMAIL_MONITOR_HISTORY_WINDOW")); val != "" {
		parsed, err := time.ParseDuration(val)
		if err != nil {
			return nil, fmt.Errorf("invalid EMAIL_MONITOR_HISTORY_WINDOW: %w", err)
		}
		historyWindow = parsed
	}

	watchRenewal := defaultWatchRenewal
	if val := strings.TrimSpace(os.Getenv("EMAIL_MONITOR_WATCH_RENEWAL")); val != "" {
		parsed, err := time.ParseDuration(val)
		if err != nil {
			return nil, fmt.Errorf("invalid EMAIL_MONITOR_WATCH_RENEWAL: %w", err)
		}
		watchRenewal = parsed
	}

	gcpProject := strings.TrimSpace(os.Getenv("EMAIL_MONITOR_GCP_PROJECT"))
	pubsubTopic := strings.TrimSpace(os.Getenv("EMAIL_MONITOR_PUBSUB_TOPIC"))
	pubsubSubscription := strings.TrimSpace(os.Getenv("EMAIL_MONITOR_PUBSUB_SUBSCRIPTION"))
	if mode == "watch" {
		if gcpProject == "" {
			return nil, fmt.Errorf("EMAIL_MONITOR_GCP_PROJECT is required for watch mode")
		}
		if pubsubTopic == "" {
			return nil, fmt.Errorf("EMAIL_MONITOR_PUBSUB_TOPIC is required for watch mode")
		}
		if pubsubSubscription == "" {
			return nil, fmt.Errorf("EMAIL_MONITOR_PUBSUB_SUBSCRIPTION is required for watch mode")
		}
		if saJSONB64 == "" {
			return nil, fmt.Errorf("EMAIL_MONITOR_SA_JSON_B64 is required for watch mode (Pub/Sub auth)")
		}
	}

	statePath := strings.TrimSpace(os.Getenv("EMAIL_MONITOR_STATE_PATH"))
	if statePath == "" {
		statePath = defaultStatePath
	}

	return &Config{
		Enabled:            true,
		Mode:               mode,
		PollInterval:       pollInterval,
		HistoryWindow:      historyWindow,
		WatchRenewal:       watchRenewal,
		GCPProject:         gcpProject,
		PubSubTopic:        pubsubTopic,
		PubSubSubscription: pubsubSubscription,
		Mailbox:            mailbox,
		Senders:            senders,
		ServiceJSON:        saJSON,
		OAuthClientID:      oauthClientID,
		OAuthClientSecret:  oauthClientSecret,
		OAuthRefreshToken:  oauthRefreshToken,
		WebhookURL:         webhook,
		StatePath:          statePath,
	}, nil
}

func parseSenders(raw string) []string {
	parts := strings.Split(raw, ",")
	senders := make([]string, 0, len(parts))
	for _, part := range parts {
		trimmed := strings.TrimSpace(part)
		if trimmed == "" {
			continue
		}
		senders = append(senders, strings.ToLower(trimmed))
	}
	return senders
}

func decodeBase64(value string) ([]byte, error) {
	decoded, err := base64.StdEncoding.DecodeString(value)
	if err == nil {
		return decoded, nil
	}
	return base64.RawStdEncoding.DecodeString(value)
}
