package coverage

import (
	"context"
	"fmt"
	"git.unistack.org/unistack-org/pkgdash/internal/models"
	"golang.org/x/tools/cover"
	"io"
	"strings"
)

func Analyze(ctx context.Context, dataCoverage io.Reader, pack models.Package) (float64, error) {
	calculcate, err := calculateFiles(dataCoverage)
	if err != nil {
		return 0, err
	}

	mapCover := make(map[string]float64)
	{
		tree, err := GetTreeFromGit(ctx, pack.URL)
		if err != nil {
			return 0, err
		}
		list, err := tree.GoFileList("")
		if err != nil {
			return 0, err
		}

		for _, f := range list {
			mapCover[f] = 0.0
		}
	}

	cur := len(mapCover)

	for _, d := range calculcate.Files {
		file := strings.TrimPrefix(d.Name, pack.Name+"/")
		mapCover[file] = d.Coverage
	}

	// check)
	if len(mapCover) != cur {
		fmt.Printf("add new keys, was: %d, has: %d", cur, len(mapCover))
	}

	//TODO add calculate full

	return 0, nil
}

type Data struct {
	Files []*calculateFile
	Set   bool
}

type calculateFile struct {
	Name     string
	Coverage float64
}

func calculateFiles(coverSrc io.Reader) (d *Data, err error) {
	profiles, err := cover.ParseProfilesFromReader(coverSrc)
	if err != nil {
		return nil, err
	}

	d = new(Data)
	for _, profile := range profiles {
		fn := profile.FileName
		if profile.Mode == "set" {
			d.Set = true
		}

		d.Files = append(d.Files, &calculateFile{
			Name:     fn,
			Coverage: percentCovered(profile),
		})
	}
	return d, err
}

func percentCovered(p *cover.Profile) float64 {
	var total, covered int64
	for _, b := range p.Blocks {
		total += int64(b.NumStmt)
		if b.Count > 0 {
			covered += int64(b.NumStmt)
		}
	}
	if total == 0 {
		return 0
	}
	return float64(covered) / float64(total) * 100
}
