using UnityEngine;
using Unity.Netcode;

public class UndergroundGenerator : NetworkBehaviour
{
    [Header("Generation Range")]
    [SerializeField] private Vector3Int generationRange = new Vector3Int(20, 30, 10);
    [SerializeField] private float noiseScale = 0.12f;

    [Header("Thresholds (0 to 1)")]
    [SerializeField, Range(0, 1)] private float hollowThreshold = 0.35f;
    [SerializeField, Range(0, 1)] private float baseResourceThreshold = 0.8f;

    [Header("Depth Settings")]
    [SerializeField] private bool increaseResourceWithDepth = true;
    [SerializeField] private float depthFactor = 0.005f; // 깊어질수록 임계값 감소 (자원 증가)

    [Header("Prefabs")]
    [SerializeField] private GameObject normalBlockPrefab;
    [SerializeField] private GameObject resourceBlockPrefab;

    [Header("Organization")]
    [SerializeField] private string containerName = "UndergroundBlocks";
    private Transform _blockContainer; // 블록들을 담을 부모 오브젝트

    private float _seedX, _seedY, _seedZ;

    private void Awake()
    {
        _seedX = Random.Range(0f, 99999f);
        _seedY = Random.Range(0f, 99999f);
        _seedZ = Random.Range(0f, 99999f);

        // Hierarchy 정리를 위한 컨테이너 생성
        _blockContainer = new GameObject(containerName).transform;
    }

    public override void OnNetworkSpawn()
    {
        if (IsServer) GenerateFromGeneratorPivot();
    }

    private void GenerateFromGeneratorPivot()
    {
        Vector3Int originGrid = BuildManager.Instance.WorldToGrid3D(transform.position);

        for (int x = 0; x < generationRange.x; x++)
        {
            for (int y = 0; y > -generationRange.y; y--)
            {
                for (int z = 0; z < generationRange.z; z++)
                {
                    Vector3Int targetGridPos = originGrid + new Vector3Int(x, y, z);
                    float noise = Get3DNoise(targetGridPos.x, targetGridPos.y, targetGridPos.z);

                    if (noise < hollowThreshold) continue;

                    float currentThreshold = baseResourceThreshold + (y * depthFactor);
                    GameObject prefab = (noise > currentThreshold) ? resourceBlockPrefab : normalBlockPrefab;

                    SpawnBlock(prefab, targetGridPos);
                }
            }
        }
    }

    private void SpawnBlock(GameObject prefab, Vector3Int gridPos)
    {
        if (prefab == null) return;

        Vector3 worldPos = BuildManager.Instance.GridToWorld(gridPos);

        // 1. 생성 시 부모(Container)를 지정하여 Hierarchy 정리
        GameObject block = Instantiate(prefab, worldPos, Quaternion.identity);

        // 2. 네트워크 스폰 (Netcode for GameObjects)
        block.GetComponent<NetworkObject>().Spawn();
    }

    private float Get3DNoise(int x, int y, int z)
    {
        // 대칭 방지를 위한 10000 오프셋 및 시드 적용
        float xCoord = (x + _seedX + 10000f) * noiseScale;
        float yCoord = (y + _seedY + 10000f) * noiseScale;
        float zCoord = (z + _seedZ + 10000f) * noiseScale;

        float ab = Mathf.PerlinNoise(xCoord, yCoord);
        float bc = Mathf.PerlinNoise(yCoord, zCoord);
        float ac = Mathf.PerlinNoise(xCoord, zCoord);

        return (ab + bc + ac) / 3f;
    }

    private void OnDrawGizmosSelected()
    {
        BuildManager bm = BuildManager.Instance;
        if (bm == null) bm = FindFirstObjectByType<BuildManager>(); // 에러 방지 안전장치
        if (bm == null) return;

        Vector3Int originGrid = bm.WorldToGrid3D(transform.position);

        for (int x = 0; x < generationRange.x; x += 2)
        {
            for (int y = -generationRange.y; y < 0; y += 2)
            {
                for (int z = 0; z < generationRange.z; z += 2)
                {
                    Vector3Int targetGridPos = originGrid + new Vector3Int(x, y, z);
                    float noise = Get3DNoise(targetGridPos.x, targetGridPos.y, targetGridPos.z);

                    if (noise < hollowThreshold) continue;

                    Gizmos.color = (noise > baseResourceThreshold) ? Color.yellow : new Color(0.5f, 0.5f, 0.5f, 0.2f);
                    Vector3 pos = bm.GridToWorld(targetGridPos);
                    Gizmos.DrawSphere(pos, 0.2f);
                }
            }
        }
    }
}