package roast

import (
	"errors"
	"fmt"
	"git-roast/internal/log"
	"git-roast/internal/util"
	"net/url"
	"os"
	"os/exec"
	"path/filepath"
	"time"

	"github.com/go-git/go-git/v5"
)

func (r *Roast) Request(from string, into string) error {
	log.Debugf("requesting merge from %s into %s\n", from, into)

	sourceBranch, err := r.repo.Branch(from)
	if err != nil {
		return errors.Join(fmt.Errorf("failed to get source branch %s", from), err)
	}

	targetBranch, err := r.repo.Branch(into)
	if err != nil {
		return errors.Join(fmt.Errorf("failed to get target branch %s", from), err)
	}

	id := url.PathEscape(fmt.Sprintf(
		"%016x_from_%s_into_%s",
		time.Now().Unix(),
		sourceBranch.Name,
		targetBranch.Name,
	))

	initialMessage, err := util.Textedit(fmt.Sprintf(
		"%s is requesting merge into `%s` from `%s`\n",
		GitUserName(),
		into,
		from,
	))
	if err != nil {
		return err
	}

	p := filepath.Join(r.dir, id)
	if err := os.MkdirAll(p, 0700); err != nil {
		return errors.Join(errors.New("failed to create directory for request"), err)
	}

	successful := false
	defer func() {
		if !successful {
            clean := exec.Command("git", "clean", "-xfd")
            clean.Path = r.dir
            _ = clean.Run()
			log.Printf("action not successful, rollback...\n")
			reset := exec.Command("git", "reset", "--hard")
			reset.Path = r.dir
			_ = reset.Run()
		}
	}()

	f, err := os.Create(filepath.Join(p, fmt.Sprintf(
		"%016x_%s.md",
		time.Now().Unix(),
		GitUserName(),
	)))
	if err != nil {
		return errors.Join(errors.New("failed to create file for request"), err)
	}

	if _, err := f.Write([]byte(initialMessage)); err != nil {
		return errors.Join(errors.New("failed to write to file for request"), err)
	}

	if err := r.repo.Push(&git.PushOptions{Atomic: true}); err != nil {
		return errors.Join(errors.New("failed to push request"), err)
	}

	successful = true
	return nil
}