package server

import (
	"bytes"
	"context"
	"encoding/json"
	"fmt"
	"log/slog"
	"net"
	"net/http"
	"net/url"
	"os"
	"strings"
	"time"
)

const (
	seedDefaultUserEnv     = "AGENTTEAM_DEV_SEED_DEFAULT_USER"
	defaultDevUserEmail    = "agentteamer@agentteam.local"
	defaultDevUserName     = "agentteamer"
	defaultDevUserPassword = "test123456"
)

func seedDefaultUserIfEnabled(ctx context.Context, serverURL string) (bool, error) {
	enabled, err := seedDefaultUserEnabled(os.Getenv(seedDefaultUserEnv))
	if err != nil || !enabled {
		return false, err
	}
	if err := requireLoopbackServerURL(serverURL); err != nil {
		return false, err
	}
	return true, seedDefaultUser(ctx, serverURL)
}

func seedDefaultUserEnabled(raw string) (bool, error) {
	switch strings.ToLower(strings.TrimSpace(raw)) {
	case "":
		return false, nil
	case "1", "true", "yes", "on":
		return true, nil
	case "0", "false", "no", "off":
		return false, nil
	default:
		return false, fmt.Errorf("%s must be an explicit boolean", seedDefaultUserEnv)
	}
}

func requireLoopbackServerURL(raw string) error {
	raw = strings.TrimSpace(raw)
	if raw == "" || strings.HasPrefix(raw, ":") {
		return fmt.Errorf("%s requires an explicit loopback agentteam-server URL, got %q", seedDefaultUserEnv, raw)
	}
	if !strings.Contains(raw, "://") {
		raw = "http://" + raw
	}
	parsed, err := url.Parse(raw)
	if err != nil {
		return fmt.Errorf("parse agentteam-server URL for %s: %w", seedDefaultUserEnv, err)
	}
	host := strings.TrimSpace(parsed.Hostname())
	ip := net.ParseIP(host)
	if !strings.EqualFold(host, "localhost") && (ip == nil || !ip.IsLoopback()) {
		return fmt.Errorf("%s refuses non-loopback agentteam-server host %q", seedDefaultUserEnv, host)
	}
	return nil
}

// seedDefaultUser creates the default dev user (agentteamer@agentteam.local) against the
// running agentteam-server. Idempotent: a 409 Conflict is treated as success.
// Callers must enforce the explicit opt-in and loopback-only boundary first.
func seedDefaultUser(ctx context.Context, serverURL string) error {
	endpoint := strings.TrimRight(normalizeServerURL(serverURL), "/") + "/api/v1/auth/register"

	body, err := json.Marshal(map[string]string{
		"email":    defaultDevUserEmail,
		"name":     defaultDevUserName,
		"password": defaultDevUserPassword,
	})
	if err != nil {
		return fmt.Errorf("seed default user: %w", err)
	}

	reqCtx, cancel := context.WithTimeout(ctx, 10*time.Second)
	defer cancel()

	req, err := http.NewRequestWithContext(reqCtx, http.MethodPost, endpoint, bytes.NewReader(body))
	if err != nil {
		return fmt.Errorf("seed default user: %w", err)
	}
	req.Header.Set("Content-Type", "application/json")

	client := &http.Client{Timeout: 10 * time.Second}
	resp, err := client.Do(req)
	if err != nil {
		return fmt.Errorf("seed default user: %w", err)
	}
	defer resp.Body.Close()

	switch {
	case resp.StatusCode >= 200 && resp.StatusCode < 300:
		slog.Info("seeded default dev user", "email", defaultDevUserEmail, "endpoint", endpoint)
		return nil
	case resp.StatusCode == http.StatusConflict:
		slog.Info("default dev user already exists", "email", defaultDevUserEmail)
		return nil
	default:
		return fmt.Errorf("seed default user: HTTP %s at %s", resp.Status, endpoint)
	}
}

func normalizeServerURL(raw string) string {
	raw = strings.TrimSpace(raw)
	if raw == "" {
		return "http://127.0.0.1:3001"
	}
	if strings.HasPrefix(raw, "http://") || strings.HasPrefix(raw, "https://") {
		return raw
	}
	if strings.HasPrefix(raw, ":") {
		return "http://127.0.0.1" + raw
	}
	return "http://" + raw
}
