package webhook

import (
	"context"
	"fmt"
	"log/slog"
	"strings"

	"github.com/alexei/docker-watcher/internal/docker"
	"github.com/alexei/docker-watcher/internal/store"
)

// AutoCreateProject creates a new project and a default "dev" stage from an
// unknown image. It inspects the Docker image to extract defaults (EXPOSE port,
// healthcheck, labels).
//
// The auto-created project uses:
//   - Name: derived from image name (e.g. "web-app-launcher")
//   - Image: full owner/name path
//   - Port: first EXPOSE port from the image, or 0 if none
//   - Healthcheck: from image HEALTHCHECK instruction, if present
//   - A single "dev" stage with auto_deploy=true and tag_pattern="*"
func AutoCreateProject(
	ctx context.Context,
	st *store.Store,
	inspector ImageInspector,
	parsed ParsedImage,
) (store.Project, store.Stage, error) {
	// Build the full image ref for inspection (registry/owner/name:tag).
	imageRef := buildImageRef(parsed)

	var port int
	var healthcheck string

	// Attempt to inspect the image for metadata. If inspection fails (image
	// not pulled locally), proceed with zero defaults.
	if inspector != nil {
		info, err := inspector.InspectImage(ctx, imageRef)
		if err != nil {
			slog.Warn("webhook: image inspection failed, using defaults", "image", imageRef, "error", err)
		} else {
			port = docker.ExtractPort(info.ExposedPorts)
			healthcheck = info.Healthcheck
		}
	}

	project, err := st.CreateProject(store.Project{
		Name:        parsed.Name,
		Registry:    parsed.Registry,
		Image:       parsed.FullName(),
		Port:        port,
		Healthcheck: healthcheck,
		Env:         "{}",
		Volumes:     "{}",
	})
	if err != nil {
		return store.Project{}, store.Stage{}, fmt.Errorf("create project: %w", err)
	}

	stage, err := st.CreateStage(store.Stage{
		ProjectID:    project.ID,
		Name:         "dev",
		TagPattern:   "*",
		AutoDeploy:   true,
		MaxInstances: 1,
	})
	if err != nil {
		return store.Project{}, store.Stage{}, fmt.Errorf("create default stage: %w", err)
	}

	return project, stage, nil
}

// buildImageRef reconstructs a pullable image reference from parsed components.
func buildImageRef(parsed ParsedImage) string {
	var parts []string
	if parsed.Registry != "" {
		parts = append(parts, parsed.Registry)
	}
	if parsed.Owner != "" {
		parts = append(parts, parsed.Owner)
	}
	parts = append(parts, parsed.Name)

	ref := strings.Join(parts, "/")
	if parsed.Tag != "" {
		ref += ":" + parsed.Tag
	}
	return ref
}

