package entity

import (
	"fmt"
	"os"

	r "xyj-figures/pkg/relationship"

	yaml "gopkg.in/yaml.v3"
)

type Entity struct {
	Schema  string      `yaml:"schema,flow"`
	Type    string      `yaml:"type,flow"`
	Details interface{} `yaml:"details,flow"`
}

type EntityType string

const (
	EntityTypeCharacter = "character"
	EntityTypeGroup     = "group"
)

type EntityDetails interface {
	GetRelationships() []r.Relationship
}

func NewEntity() (*Entity, error) {
	return &Entity{Schema: "v1"}, nil
}

func Load(path string) (*Entity, error) {
	f, err := os.ReadFile(path)
	if err != nil {
		return nil, fmt.Errorf("failed to open file: %v", err)
	}
	e, _ := NewEntity()
	if err = yaml.Unmarshal(f, &e); err != nil {
		return nil, fmt.Errorf("failed to unmarshal file: %v", err)
	}
	switch e.Type {
	case EntityTypeCharacter:
		tmp, err := yaml.Marshal(e.Details)
		if err != nil {
			return nil, fmt.Errorf("failed to marshal filed %s: %v", EntityTypeCharacter, err)
		}
		c := Character{}
		if err = yaml.Unmarshal(tmp, &c); err != nil {
			return nil, fmt.Errorf("failed to unmarshal filed %s: %v", EntityTypeCharacter, err)
		}
		e.Details = c
	case EntityTypeGroup:
		tmp, err := yaml.Marshal(e.Details)
		if err != nil {
			return nil, fmt.Errorf("failed to marshal filed %s: %v", EntityTypeGroup, err)
		}
		g := Group{}
		if err = yaml.Unmarshal(tmp, &g); err != nil {
			return nil, fmt.Errorf("failed to unmarshal filed %s: %v", EntityTypeGroup, err)
		}
		e.Details = g
	}
	return e, nil
}

func (e Entity) Merge(other Entity) error {
	if (e.Schema != other.Schema) || (e.Type != other.Type) {
		return fmt.Errorf("unmatch merge between %v and %v", e, other)
	}
	switch e.Type {
	case EntityTypeCharacter:
		if e.Details.(Character).Name != other.Details.(Character).Name {
			return fmt.Errorf("unmatch merge between %v and %v: names unmatch", e, other)
		}
		e.Details = Character{
			Name:          e.Details.(Character).Name,
			OtherNames:    append(e.Details.(Character).OtherNames, other.Details.(Character).OtherNames...),
			Relationships: append(e.Details.(Character).Relationships, other.Details.(Character).Relationships...),
			Description:   fmt.Sprintf("%s%s", e.Details.(Character).Description, other.Details.(Character).Description),
			Links:         append(e.Details.(Character).Links, other.Details.(Character).Links...),
		}
	case EntityTypeGroup:
		e.Details = Group{
			Name:          e.Details.(Group).Name,
			OtherNames:    append(e.Details.(Group).OtherNames, other.Details.(Group).OtherNames...),
			Members:       append(e.Details.(Group).Members, other.Details.(Group).Members...),
			Relationships: append(e.Details.(Group).Relationships, other.Details.(Group).Relationships...),
			Description:   fmt.Sprintf("%s%s", e.Details.(Group).Description, other.Details.(Group).Description),
			Links:         append(e.Details.(Group).Links, other.Details.(Group).Links...),
		}
	}
	return nil
}
