package wikipress

import (
	"fmt"
	"io"
	"os"
	"path/filepath"
	"strings"
	"time"

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

func ListFilesFromHDD(opath string) ([]File, error) {
	opath = opath + "/"
	FileList := []File{}
	err := filepath.Walk(opath, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err // z.B. fehlende Leserechte
		}
		if !info.IsDir() {
			v := Version{}

			data, err := os.ReadFile(path)
			if err != nil {
				return err
			}
			v.content = string(data)
			v.contentbinary = data
			v.Author.Name = "HDD"
			v.Date = time.Now()
			v.Hash = "abc"
			v.Message = "test"

			f := File{}
			f.Name = strings.TrimPrefix(path, opath)
			f.Versions = append(f.Versions, v)

			FileList = append(FileList, f)
		}

		return nil
	})
	return FileList, err
}

func ListFilesFromGitRepro(path string) ([]File, error) {
	repo, err := git.PlainOpen(path)
	if err != nil {
		return []File{}, fmt.Errorf("%w: %s", ErrCantReadGitRepro, err)
	}

	ref, err := repo.Head()
	if err != nil {
		return []File{}, fmt.Errorf("%w: %s", ErrCantReadGitRepro, err)
	}

	commitIter, err := repo.Log(&git.LogOptions{From: ref.Hash()})
	if err != nil {
		return []File{}, fmt.Errorf("%w: %s", ErrCantReadGitRepro, err)
	}

	var commits []*object.Commit
	err = commitIter.ForEach(func(c *object.Commit) error {
		commits = append(commits, c)
		return nil
	})
	if err != nil {
		return []File{}, fmt.Errorf("%w: %s", ErrCantReadGitRepro, err)
	}

	for i, j := 0, len(commits)-1; i < j; i, j = i+1, j-1 {
		commits[i], commits[j] = commits[j], commits[i]
	}

	lastContent := make(map[string]string)
	fileList := make(map[string]File)
	currentFileList := make(map[string]bool)

	for _, c := range commits {

		tree, err := c.Tree()
		if err != nil {
			return []File{}, err
		}

		currentFileList = make(map[string]bool)

		err = tree.Files().ForEach(func(f *object.File) error {
			path := filepath.ToSlash(f.Name)
			currentFileList[f.Name] = true
			content, err := f.Contents()
			if err != nil {
				return err
			}

			if lastContent[path] == content {
				return nil
			}

			byteContentReader, err := f.Reader()
			if err != nil {
				return err
			}

			byteContent, err := io.ReadAll(byteContentReader)
			if err != nil {
				return err
			}

			lastContent[path] = content

			version := Version{}
			version.Author.Name = c.Author.Name
			version.Message = c.Message
			version.Date = c.Author.When
			version.content = content
			version.contentbinary = byteContent
			version.Hash = c.Hash.String()

			file, ok := fileList[path]
			if !ok {
				file.Name = f.Name
			}

			file.Versions = append(file.Versions, version)

			fileList[path] = file
			return nil
		})
		if err != nil {
			return []File{}, err
		}
	}
	if err != nil {
		return []File{}, fmt.Errorf("%w: %s", ErrCantReadGitRepro, err)
	}

	fileListReturn := []File{}
	for _, f := range fileList {
		_, ok := currentFileList[f.Name]
		if !ok {
			f.Deleted = true
		}
		fileListReturn = append(fileListReturn, f)
	}

	return fileListReturn, nil
}
