package serverruntime

import (
	"archive/tar"
	"bytes"
	"context"
	"encoding/json"
	"fmt"
	"io"
	"os"
	"os/exec"
	"path"
	"path/filepath"
	"strings"
	"sync"
)

const (
	connectorPushTrustedLocalPackRootEnv = "NEXUSCRM_RECOVERY_RELEASE_PACK_ROOT"
	connectorPushSnapshotMaxFileBytes    = 64 << 20
	connectorPushSnapshotMaxTotalBytes   = 256 << 20
	connectorPushSnapshotMaxPackCount    = 128
)

// materializeConnectorPushTrustedLocalPackSnapshot turns a release-bound
// local_path into a private snapshot read only from the installed Git commit.
// The current worktree is used only to prove active-release identity.
func materializeConnectorPushTrustedLocalPackSnapshot(
	ctx context.Context,
	trustedRoot string,
	sourceURI string,
	sourceRevision string,
	expectedName string,
	expectedCategory string,
	expectedManifestVersion string,
) (string, func(), error) {
	cleanup := func() {}
	trustedRoot = strings.TrimSpace(trustedRoot)
	sourceURI = strings.TrimSpace(sourceURI)
	sourceRevision = strings.TrimSpace(sourceRevision)
	expectedName = strings.TrimSpace(expectedName)
	expectedCategory = strings.TrimSpace(expectedCategory)
	expectedManifestVersion = strings.TrimSpace(expectedManifestVersion)
	if trustedRoot == "" {
		return "", cleanup, fmt.Errorf("strict recovery local_path source requires %s", connectorPushTrustedLocalPackRootEnv)
	}
	if sourceURI == "" {
		return "", cleanup, fmt.Errorf("strict recovery local_path source URI is empty")
	}
	// SourceURI is installed provenance, not a runtime locator. Relocate the
	// immutable pack identity inside the exact release checkout so install-time
	// and runtime mount paths may differ.
	if expectedName == "" || expectedCategory == "" || expectedManifestVersion == "" {
		return "", cleanup, fmt.Errorf("strict recovery local_path installed pack identity is incomplete")
	}
	if !IsImmutableConnectorPushSourceRevision(sourceRevision) {
		return "", cleanup, fmt.Errorf("strict recovery local_path source revision must be a 40-hex commit")
	}

	root, err := canonicalExistingConnectorPushPath(trustedRoot)
	if err != nil {
		return "", cleanup, fmt.Errorf("strict recovery release root: %w", err)
	}

	gitRoot, err := connectorPushGitOutput(ctx, root, "rev-parse", "--show-toplevel")
	if err != nil {
		return "", cleanup, fmt.Errorf("strict recovery release root is not a Git worktree: %w", err)
	}
	canonicalGitRoot, err := canonicalExistingConnectorPushPath(gitRoot)
	if err != nil || canonicalGitRoot != root {
		return "", cleanup, fmt.Errorf("strict recovery release root is not the Git worktree top level")
	}
	if err := validateConnectorPushReleaseRoot(ctx, root, sourceRevision); err != nil {
		return "", cleanup, err
	}

	rels, err := connectorPushPackCandidatePaths(ctx, root, sourceRevision)
	if err != nil {
		return "", cleanup, err
	}
	var selectedRel string
	for _, rel := range rels {
		manifestPath := "pack.json"
		if rel != "." {
			manifestPath = rel + "/pack.json"
		}
		manifest, err := connectorPushGitPathPayload(ctx, root, sourceRevision, manifestPath, 0)
		if err != nil {
			return "", cleanup, err
		}
		matches, err := connectorPushManifestMatchesInstalledPack(
			manifest,
			expectedName,
			expectedCategory,
			expectedManifestVersion,
		)
		if err != nil {
			return "", cleanup, err
		}
		if !matches {
			continue
		}
		if selectedRel != "" {
			return "", cleanup, fmt.Errorf("strict recovery release contains ambiguous installed pack identity %q", expectedName)
		}
		selectedRel = rel
	}
	if selectedRel == "" {
		return "", cleanup, fmt.Errorf("strict recovery release does not contain installed pack identity %q", expectedName)
	}
	if err := validateConnectorPushReleaseWorktree(ctx, root, selectedRel, sourceRevision); err != nil {
		return "", cleanup, err
	}
	tempRoot, err := os.MkdirTemp("", "nexuscrm-recovery-pack-")
	if err != nil {
		return "", cleanup, fmt.Errorf("create strict recovery source snapshot: %w", err)
	}
	var cleanupOnce sync.Once
	cleanup = func() {
		cleanupOnce.Do(func() { _ = os.RemoveAll(tempRoot) })
	}
	if err := extractConnectorPushGitArchive(ctx, root, sourceRevision, selectedRel, tempRoot); err != nil {
		cleanup()
		return "", func() {}, err
	}
	if err := validateConnectorPushReleaseWorktree(ctx, root, selectedRel, sourceRevision); err != nil {
		cleanup()
		return "", func() {}, fmt.Errorf("strict recovery release changed while snapshotting: %w", err)
	}
	snapshotPath := filepath.Join(tempRoot, filepath.FromSlash(selectedRel))
	if info, err := os.Stat(filepath.Join(snapshotPath, "pack.json")); err != nil || !info.Mode().IsRegular() {
		cleanup()
		return "", func() {}, fmt.Errorf("strict recovery source snapshot does not contain a regular pack.json")
	}
	return snapshotPath, cleanup, nil
}

func connectorPushPackCandidatePaths(ctx context.Context, root string, sourceRevision string) ([]string, error) {
	out, err := connectorPushGitOutput(ctx, root, "ls-tree", "-r", "--name-only", sourceRevision)
	if err != nil {
		return nil, fmt.Errorf("enumerate strict recovery release packs: %w", err)
	}
	candidates := make([]string, 0)
	for _, raw := range strings.Split(out, "\n") {
		name := path.Clean(strings.TrimSpace(raw))
		if name == "." || name == "" || path.IsAbs(name) || name == ".." || strings.HasPrefix(name, "../") || path.Base(name) != "pack.json" {
			continue
		}
		rel := path.Dir(name)
		candidates = append(candidates, rel)
		if len(candidates) > connectorPushSnapshotMaxPackCount {
			return nil, fmt.Errorf("strict recovery release exceeds the pack candidate limit")
		}
	}
	if len(candidates) == 0 {
		return nil, fmt.Errorf("strict recovery release does not contain a pack.json")
	}
	return candidates, nil
}

func connectorPushManifestMatchesInstalledPack(payload []byte, expectedName, expectedCategory, expectedManifestVersion string) (bool, error) {
	var manifest struct {
		ManifestFormatVersion string `json:"manifestFormatVersion"`
		Name                  string `json:"name"`
		Category              string `json:"category"`
	}
	if err := json.Unmarshal(payload, &manifest); err != nil {
		// Component payload paths may also end in pack.json. They are not pack
		// roots and must not prevent discovery of the installed manifest.
		return false, nil
	}
	return strings.EqualFold(strings.TrimSpace(manifest.Name), expectedName) &&
		strings.EqualFold(strings.TrimSpace(manifest.Category), expectedCategory) &&
		strings.TrimSpace(manifest.ManifestFormatVersion) == expectedManifestVersion, nil
}

func connectorPushGitPathPayload(ctx context.Context, root, sourceRevision, name string, depth int) ([]byte, error) {
	if depth > 16 {
		return nil, fmt.Errorf("strict recovery source pack.json symlink chain is too deep")
	}
	name = path.Clean(strings.TrimSpace(name))
	if name == "." || name == "" || path.IsAbs(name) || name == ".." || strings.HasPrefix(name, "../") {
		return nil, fmt.Errorf("strict recovery source pack.json has an unsafe Git path")
	}
	entry, err := connectorPushGitOutput(ctx, root, "ls-tree", sourceRevision, "--", name)
	if err != nil {
		return nil, fmt.Errorf("inspect strict recovery source pack.json: %w", err)
	}
	metadata, _, found := strings.Cut(entry, "\t")
	fields := strings.Fields(metadata)
	if !found || len(fields) != 3 || fields[1] != "blob" {
		return nil, fmt.Errorf("strict recovery source pack.json is not a Git blob")
	}
	payload, err := connectorPushGitOutput(ctx, root, "show", sourceRevision+":"+name)
	if err != nil {
		return nil, fmt.Errorf("read strict recovery source pack.json: %w", err)
	}
	if fields[0] != "120000" {
		if fields[0] != "100644" && fields[0] != "100755" {
			return nil, fmt.Errorf("strict recovery source pack.json has unsupported Git mode %s", fields[0])
		}
		return []byte(payload), nil
	}
	linkname := strings.TrimSpace(payload)
	resolved := path.Clean(path.Join(path.Dir(name), linkname))
	if linkname == "" || path.IsAbs(linkname) || resolved == "." || resolved == ".." || strings.HasPrefix(resolved, "../") {
		return nil, fmt.Errorf("strict recovery source pack.json symlink escapes the release root")
	}
	return connectorPushGitPathPayload(ctx, root, sourceRevision, resolved, depth+1)
}

func canonicalExistingConnectorPushPath(raw string) (string, error) {
	abs, err := filepath.Abs(strings.TrimSpace(raw))
	if err != nil {
		return "", err
	}
	resolved, err := filepath.EvalSymlinks(abs)
	if err != nil {
		return "", err
	}
	info, err := os.Stat(resolved)
	if err != nil {
		return "", err
	}
	if !info.IsDir() {
		return "", fmt.Errorf("%s is not a directory", resolved)
	}
	return filepath.Clean(resolved), nil
}

func validateConnectorPushReleaseWorktree(ctx context.Context, root string, rel string, sourceRevision string) error {
	if err := validateConnectorPushReleaseRoot(ctx, root, sourceRevision); err != nil {
		return err
	}
	untrackedSource, err := connectorPushGitOutput(ctx, root, "ls-files", "--others", "--exclude-standard", "--", rel)
	if err != nil {
		return fmt.Errorf("inspect strict recovery source untracked files: %w", err)
	}
	if strings.TrimSpace(untrackedSource) != "" {
		return fmt.Errorf("strict recovery local_path source contains untracked files")
	}
	packManifestPath := "pack.json"
	if rel != "." {
		packManifestPath = rel + "/pack.json"
	}
	if _, err := connectorPushGitOutput(ctx, root, "cat-file", "-e", sourceRevision+":"+packManifestPath); err != nil {
		return fmt.Errorf("strict recovery installed commit does not contain source pack.json: %w", err)
	}
	return nil
}

func validateConnectorPushReleaseRoot(ctx context.Context, root string, sourceRevision string) error {
	resolvedRevision, err := connectorPushGitOutput(ctx, root, "rev-parse", sourceRevision+"^{commit}")
	if err != nil {
		return fmt.Errorf("strict recovery release does not contain installed source revision %s: %w", sourceRevision, err)
	}
	if !strings.EqualFold(strings.TrimSpace(resolvedRevision), sourceRevision) {
		return fmt.Errorf("strict recovery release resolved installed source revision %s as %s", sourceRevision, strings.TrimSpace(resolvedRevision))
	}
	trackedStatus, err := connectorPushGitOutput(ctx, root, "status", "--porcelain=v1", "--untracked-files=no")
	if err != nil {
		return fmt.Errorf("inspect strict recovery release tracked state: %w", err)
	}
	if strings.TrimSpace(trackedStatus) != "" {
		return fmt.Errorf("strict recovery release worktree has tracked changes")
	}
	return nil
}

func connectorPushGitOutput(ctx context.Context, root string, args ...string) (string, error) {
	cmd := exec.CommandContext(ctx, "git", append([]string{"-C", root}, args...)...)
	out, err := cmd.CombinedOutput()
	if err != nil {
		return "", fmt.Errorf("git %s: %w: %s", strings.Join(args, " "), err, strings.TrimSpace(string(out)))
	}
	return strings.TrimSpace(string(out)), nil
}

func extractConnectorPushGitArchive(
	ctx context.Context,
	root string,
	sourceRevision string,
	rel string,
	destination string,
) error {
	args := []string{"-C", root, "archive", "--format=tar", sourceRevision}
	if rel != "." {
		args = append(args, "--", rel)
	}
	cmd := exec.CommandContext(ctx, "git", args...)
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		return fmt.Errorf("open strict recovery Git archive: %w", err)
	}
	var stderr bytes.Buffer
	cmd.Stderr = &stderr
	if err := cmd.Start(); err != nil {
		return fmt.Errorf("start strict recovery Git archive: %w", err)
	}
	extractErr := extractConnectorPushTar(stdout, destination)
	if extractErr != nil && cmd.Process != nil {
		_ = cmd.Process.Kill()
	}
	waitErr := cmd.Wait()
	if extractErr != nil {
		return extractErr
	}
	if waitErr != nil {
		return fmt.Errorf("archive strict recovery source: %w: %s", waitErr, strings.TrimSpace(stderr.String()))
	}
	return nil
}

func extractConnectorPushTar(reader io.Reader, destination string) error {
	tarReader := tar.NewReader(reader)
	var total int64
	type pendingSymlink struct {
		name     string
		target   string
		linkname string
	}
	var symlinks []pendingSymlink
	for {
		header, err := tarReader.Next()
		if err == io.EOF {
			break
		}
		if err != nil {
			return fmt.Errorf("read strict recovery source archive: %w", err)
		}
		name := path.Clean(strings.TrimPrefix(header.Name, "./"))
		if name == "." || name == "" || path.IsAbs(name) || name == ".." || strings.HasPrefix(name, "../") {
			return fmt.Errorf("strict recovery source archive contains an unsafe path")
		}
		target := filepath.Join(destination, filepath.FromSlash(name))
		targetRel, err := filepath.Rel(destination, target)
		if err != nil || targetRel == ".." || strings.HasPrefix(targetRel, ".."+string(filepath.Separator)) {
			return fmt.Errorf("strict recovery source archive escapes its snapshot root")
		}
		switch header.Typeflag {
		case tar.TypeXGlobalHeader:
			continue
		case tar.TypeDir:
			if err := os.MkdirAll(target, 0o700); err != nil {
				return fmt.Errorf("create strict recovery snapshot directory: %w", err)
			}
		case tar.TypeReg, tar.TypeRegA:
			if header.Size < 0 || header.Size > connectorPushSnapshotMaxFileBytes || total > connectorPushSnapshotMaxTotalBytes-header.Size {
				return fmt.Errorf("strict recovery source archive exceeds the snapshot size limit")
			}
			total += header.Size
			if err := os.MkdirAll(filepath.Dir(target), 0o700); err != nil {
				return fmt.Errorf("create strict recovery snapshot parent: %w", err)
			}
			file, err := os.OpenFile(target, os.O_CREATE|os.O_EXCL|os.O_WRONLY, 0o600)
			if err != nil {
				return fmt.Errorf("create strict recovery snapshot file: %w", err)
			}
			_, copyErr := io.CopyN(file, tarReader, header.Size)
			closeErr := file.Close()
			if copyErr != nil {
				return fmt.Errorf("extract strict recovery snapshot file: %w", copyErr)
			}
			if closeErr != nil {
				return fmt.Errorf("close strict recovery snapshot file: %w", closeErr)
			}
		case tar.TypeSymlink:
			linkname := strings.TrimSpace(header.Linkname)
			resolvedName := path.Clean(path.Join(path.Dir(name), linkname))
			if linkname == "" || path.IsAbs(linkname) || resolvedName == "." || resolvedName == ".." || strings.HasPrefix(resolvedName, "../") {
				return fmt.Errorf("strict recovery source archive contains an escaping symlink: name=%q", name)
			}
			if err := os.MkdirAll(filepath.Dir(target), 0o700); err != nil {
				return fmt.Errorf("create strict recovery snapshot symlink parent: %w", err)
			}
			symlinks = append(symlinks, pendingSymlink{name: name, target: target, linkname: linkname})
		default:
			return fmt.Errorf("strict recovery source archive contains a non-regular entry: name=%q type=%d", name, header.Typeflag)
		}
	}

	// Git records symlinks as leaf entries. Defer creating all of them until
	// regular files are extracted so no archive entry can traverse a link while
	// writing. Then prove every complete link chain stays inside the private root.
	for _, link := range symlinks {
		if _, err := os.Lstat(link.target); err == nil {
			return fmt.Errorf("strict recovery source archive contains duplicate path %q", link.name)
		} else if !os.IsNotExist(err) {
			return fmt.Errorf("inspect strict recovery snapshot symlink %q: %w", link.name, err)
		}
		if err := os.Symlink(link.linkname, link.target); err != nil {
			return fmt.Errorf("create strict recovery snapshot symlink %q: %w", link.name, err)
		}
	}
	destinationAbs, err := filepath.Abs(destination)
	if err != nil {
		return fmt.Errorf("resolve strict recovery snapshot root: %w", err)
	}
	destinationAbs, err = filepath.EvalSymlinks(destinationAbs)
	if err != nil {
		return fmt.Errorf("canonicalize strict recovery snapshot root: %w", err)
	}
	for _, link := range symlinks {
		resolved, err := filepath.EvalSymlinks(link.target)
		if err != nil {
			return fmt.Errorf("resolve strict recovery snapshot symlink %q: %w", link.name, err)
		}
		resolvedAbs, err := filepath.Abs(resolved)
		if err != nil {
			return fmt.Errorf("resolve strict recovery snapshot symlink %q: %w", link.name, err)
		}
		rel, err := filepath.Rel(destinationAbs, resolvedAbs)
		if err != nil || rel == ".." || strings.HasPrefix(rel, ".."+string(filepath.Separator)) {
			return fmt.Errorf("strict recovery source archive symlink %q escapes its snapshot root", link.name)
		}
	}
	return nil
}
