using UnityEngine;

namespace IStalk.Data
{
    [CreateAssetMenu(fileName = "GlobalRules", menuName = "IStalk/Global Rules")]
    public class GlobalRules_SO : ScriptableObject
    {
        public static GlobalRules_SO Instance { get; private set; }

        [Header("Extraction")]
        public int extractionThreshold = 100;
        public float altarChannelBaseTime = 3.0f;
        public float altarChannelWeightScale = 0.4f;

        [Header("Match Timing")]
        public float gracePeriodDuration = 30f;
        public float matchTimeLimit = 1080f;
        public float overtimeRoomSealRate = 30f;

        [Header("Eye — Dread Economy")]
        public float dreadBaseRegenRate = 3.0f;
        public float dreadNoiseBonusMultiplier = 2.0f;
        public float dreadStartingAmount = 0f;

        [Header("Weight Tier Thresholds (kg)")]
        public float weightThresholdLight = 1f;
        public float weightThresholdModerate = 6f;
        public float weightThresholdHeavy = 13f;
        public float weightThresholdOverloaded = 21f;

        [Header("Weight Speed Multipliers")]
        public float speedMultNaked = 1.00f;
        public float speedMultLight = 0.90f;
        public float speedMultModerate = 0.75f;
        public float speedMultHeavy = 0.55f;
        public float speedMultOverloaded = 0.35f;

        [Header("Runner Movement")]
        public float baseRunSpeed = 8f;
        public float sprintMultiplier = 1.4f;
        public float jumpForce = 10f;
        public float gravity = -25f;
        public float coyoteTime = 0.15f;
        public float jumpBuffer = 0.10f;
        public float wallRunMinSpeed = 4f;
        public float slideSpeed = 12f;
        public float dashDistance = 5f;
        public float dashDuration = 0.2f;
        public float airDashDistance = 4f;

        [Header("Eye Laser")]
        public float laserChargeTime = 1.5f;
        public float laserCooldown = 4f;
        public float laserRange = 80f;
        public float laserRadius = 0.35f;
        public float telegraphDuration = 0.8f;

        [Header("Eye Camera")]
        public float panSpeed = 20f;
        public float zoomMin = 8f;
        public float zoomMax = 40f;
        public float zoomSpeed = 5f;

        [Header("LoS")]
        public float losMaxDistance = 50f;
        public int losTicksPerSecond = 30;
        public float losStaleFrameTolerance = 3;

        [Header("Map Generation")]
        public int minRoomsPerMap = 8;
        public int maxRoomsPerMap = 30;
        public int minFloors = 2;
        public int maxFloors = 4;
        public float corridorRatioMin = 0.20f;
        public int maxLargeRooms = 3;
        public int minAltars = 2;
        public int maxAltars = 4;
        public int altarMinDistanceFromSpawn = 3;
        public float lootSpawnProbability = 0.7f;
        public float lootValueToThresholdRatio = 2.5f;
        public int maxShrinesPerMap = 3;
        public float cellWidth = 4.0f;
        public float cellHeight = 3.0f;

        [Header("Network")]
        public string relayUrlProduction = "wss://istalk-relay.caprover.al-arcade.com";
        public string relayUrlDevelopment = "ws://localhost:8080";
        public int networkTickRate = 30;
        public float reconcileSnapThreshold = 0.1f;

        [Header("Interaction")]
        public float pickupRadius = 1.5f;
        public float altarInteractRadius = 2.5f;
        public float playerSpawnTimeout = 10f;

        [Header("Eye Types")]
        public float flashDuration = 5f;
        public float flashTeamCooldown = 15f;
        public float watcherScanCooldownMultiplier = 0.6f;
        public float watcherScanRadiusMultiplier = 1.3f;
        public float predatorLaserCooldownMultiplier = 0.5f;
        public float predatorLaserRadiusMultiplier = 1.4f;
        public float trapperDreadCostMultiplier = 0.6f;
        public int trapperMaxActiveBonus = 3;

        [Header("Wearables")]
        public int maxWearableSlots = 2;
        public float dashCooldown = 3f;
        public float airDashCooldown = 5f;
        public float grappleCooldown = 8f;
        public float throwRangeBase = 8f;
        public float throwRangeWeightScale = 0.5f;

        [Header("Co-op")]
        public float boostHeight = 2f;
        public float boostRange = 1.5f;
        public float linkedSprintBonus = 0.2f;
        public float linkedSprintRadius = 5f;
        public float linkedSprintSlowDuration = 1f;

        [Header("Extraction Room")]
        public float extractionChannelDuration = 30f;
        public float antiAfkRitualDuration = 20f;
        public int antiAfkMinVoters = 2;

        public void Initialize()
        {
            Instance = this;
        }

        public WeightTier GetTier(float currentWeight)
        {
            if (currentWeight >= weightThresholdOverloaded) return WeightTier.Overloaded;
            if (currentWeight >= weightThresholdHeavy) return WeightTier.Heavy;
            if (currentWeight >= weightThresholdModerate) return WeightTier.Moderate;
            if (currentWeight >= weightThresholdLight) return WeightTier.Light;
            return WeightTier.Naked;
        }

        public float GetSpeedMultiplier(WeightTier tier)
        {
            return tier switch
            {
                WeightTier.Naked => speedMultNaked,
                WeightTier.Light => speedMultLight,
                WeightTier.Moderate => speedMultModerate,
                WeightTier.Heavy => speedMultHeavy,
                WeightTier.Overloaded => speedMultOverloaded,
                _ => 1f
            };
        }

        public float GetChannelTime(float carriedWeight)
        {
            return altarChannelBaseTime + carriedWeight * altarChannelWeightScale;
        }

        public string GetRelayUrl()
        {
#if DEVELOPMENT_BUILD || UNITY_EDITOR
            return relayUrlDevelopment;
#else
            return relayUrlProduction;
#endif
        }
    }

    public enum WeightTier { Naked, Light, Moderate, Heavy, Overloaded }
}
