package JsonSerialization

import (
	"encoding/json"
	"errors"
	"fmt"
	"strings"

	"git.tovijaeschke.xyz/tovi/SuddenImpactRecords/Models"

	schema "github.com/Kangaroux/go-map-schema"
)

func DeserializePost(data []byte, allowMissing []string, allowAllMissing bool) (Models.Post, error) {
	var (
		postData                 Models.Post            = Models.Post{}
		jsonStructureTest        map[string]interface{} = make(map[string]interface{})
		jsonStructureTestResults *schema.CompareResults
		field                    schema.FieldMissing
		allowed                  string
		missingFields            []string
		i                        int
		err                      error
	)

	// Verify the JSON has the correct structure
	json.Unmarshal(data, &jsonStructureTest)
	jsonStructureTestResults, err = schema.CompareMapToStruct(
		&postData,
		jsonStructureTest,
		&schema.CompareOpts{
			ConvertibleFunc: CanConvert,
			TypeNameFunc:    schema.DetailedTypeName,
		})
	if err != nil {
		return postData, err
	}

	if len(jsonStructureTestResults.MismatchedFields) > 0 {
		return postData, errors.New(fmt.Sprintf(
			"MismatchedFields found when deserializing data: %s",
			jsonStructureTestResults.Errors().Error(),
		))
	}

	// Remove allowed missing fields from MissingFields
	for _, allowed = range allowMissing {
		for i, field = range jsonStructureTestResults.MissingFields {
			if allowed == field.String() {
				jsonStructureTestResults.MissingFields = append(
					jsonStructureTestResults.MissingFields[:i],
					jsonStructureTestResults.MissingFields[i+1:]...,
				)
			}
		}
	}

	if !allowAllMissing && len(jsonStructureTestResults.MissingFields) > 0 {
		for _, field = range jsonStructureTestResults.MissingFields {
			missingFields = append(missingFields, field.String())
		}

		return postData, errors.New(fmt.Sprintf(
			"MissingFields found when deserializing data: %s",
			strings.Join(missingFields, ", "),
		))
	}

	// Deserialize the JSON into the struct
	err = json.Unmarshal(data, &postData)
	if err != nil {
		return postData, err
	}

	return postData, err
}
