package main

import (
	"encoding/json"
	"gardening/src/lib"
	"gardening/src/lib/spy"
	"gardening/sup/lib/asserter"
	"os"
)

func main() {
	data := &struct {
		Expected *spy.Report
		Actual   *spy.Report
	}{}

	report := &asserter.ExpectationReport{
		Data: data,
	}

	b, err := os.ReadFile("./tmp/last-test-fail.json")
	lib.Poe(err)
	err = json.Unmarshal(b, report)
	lib.Poe(err)

	println("Expected: ", report.Expected)
	println("Actual: ", report.Actual)

	sameStructure := isSameStructure(data.Expected, data.Actual)

	left := make(map[string]*spy.Record)
	right := make(map[string]*spy.Record)
	indexLeft := make(map[string]int)
	indexRight := make(map[string]int)

	// Populate left and right maps based on hash values of records
	for i, record := range data.Expected.Records {
		left[record.Hash] = record
		indexLeft[record.Hash] = i
	}
	for i, record := range data.Actual.Records {
		right[record.Hash] = record
		indexRight[record.Hash] = i
	}

	if sameStructure {
		smarterDiff(left, right)
	} else {
		diff(left, right)
	}

}

func smarterDiff(left map[string]*spy.Record, right map[string]*spy.Record) {
	var leftHashes []string
	var rightHashes []string

	for hash := range left {
		if _, exists := right[hash]; !exists {
			leftHashes = append(leftHashes, hash)
		}
	}
	for hash := range right {
		if _, exists := left[hash]; !exists {
			rightHashes = append(rightHashes, hash)
		}
	}

	for index, leftHash := range leftHashes {
		rightHash := rightHashes[index]
		leftRecord := left[leftHash]
		rightRecord := right[rightHash]
		println("Content differ")
		println("----")
		b, err := json.Marshal(leftRecord.Data)
		lib.Poe(err)
		println(string(b))
		println("--")
		b2, err := json.Marshal(rightRecord.Data)
		lib.Poe(err)
		println(string(b2))
		println("----")
		println("")
	}

}

func diff(left map[string]*spy.Record, right map[string]*spy.Record) {
	// Compare hash present in left but not in right
	for hash, record := range left {
		if _, exists := right[hash]; !exists {
			b, err := json.Marshal(record)
			lib.Poe(err)
			println("Hash present in left but not in right: ", hash, string(b))
		}
	}

	// Compare hash present in right but not in left
	for hash, record := range right {
		if _, exists := left[hash]; !exists {
			b, err := json.Marshal(record)
			lib.Poe(err)
			println("Hash present in right but not in left: ", hash, string(b))
		}
	}
}

func isSameStructure(expected *spy.Report, actual *spy.Report) bool {
	if len(expected.Records) != len(actual.Records) {
		return false
	}
	for i, record := range expected.Records {
		if record.Kind != actual.Records[i].Kind {
			return false
		}
	}
	return true
}
