package game

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
)

type Collider struct {
	Rect
	Type string
}

type World struct {
	Manifest     AssetManifest
	ChunkLibrary map[string]Chunk
}

func NewWorld() *World {
	return &World{
		Manifest:     AssetManifest{Assets: make(map[string]AssetDefinition)},
		ChunkLibrary: make(map[string]Chunk),
	}
}

func (w *World) LoadManifest(path string) error {
	data, err := ioutil.ReadFile(path)
	if err != nil {
		return err
	}
	return json.Unmarshal(data, &w.Manifest)
}

func (w *World) LoadChunkLibrary(dir string) error {
	entries, err := os.ReadDir(dir)
	if err != nil {
		return err
	}

	count := 0
	for _, f := range entries {
		if filepath.Ext(f.Name()) == ".json" {
			data, _ := ioutil.ReadFile(filepath.Join(dir, f.Name()))
			var c Chunk
			if err := json.Unmarshal(data, &c); err == nil {
				if c.ID == "" {
					c.ID = strings.TrimSuffix(f.Name(), ".json")
				}
				w.ChunkLibrary[c.ID] = c
				count++
			}
		}
	}
	fmt.Printf("📦 Library: %d Chunks geladen aus %s\n", count, dir)
	return nil
}

// NEU: Gibt die Liste zurück, statt sie zu speichern!
func (w *World) GenerateColliders(activeChunks []ActiveChunk) []Collider {
	list := []Collider{}

	// 1. Boden
	list = append(list, Collider{
		Rect: Rect{OffsetX: -10000, OffsetY: 540, W: 100000000, H: 200},
		Type: "platform",
	})

	// 2. Objekte
	for _, ac := range activeChunks {
		chunk, exists := w.ChunkLibrary[ac.ChunkID]
		if !exists {
			continue
		}

		for _, obj := range chunk.Objects {
			def, ok := w.Manifest.Assets[obj.AssetID]
			if !ok {
				continue
			}

			if def.Type == "obstacle" || def.Type == "platform" {
				c := Collider{
					Rect: Rect{
						OffsetX: ac.X + obj.X + def.Hitbox.OffsetX,
						OffsetY: obj.Y + def.Hitbox.OffsetY,
						W:       def.Hitbox.W,
						H:       def.Hitbox.H,
					},
					Type: def.Type,
				}
				list = append(list, c)
			}
		}
	}
	return list
}

// CheckRectCollision prüft, ob zwei Rechtecke sich überschneiden (AABB)
func CheckRectCollision(a, b Rect) bool {
	return a.OffsetX < b.OffsetX+b.W &&
		a.OffsetX+a.W > b.OffsetX &&
		a.OffsetY < b.OffsetY+b.H &&
		a.OffsetY+a.H > b.OffsetY
}
