using System.Collections;
using UnityEngine;
using TMPro;

public class ModularGun : MonoBehaviour
{
    public enum FireMode { SemiAuto, Burst, FullAuto }

    [Header("Gun Settings")]
    public float damage = 10f;
    public float range = 100f;
    public float fireRate = 15f;
    public float impactForce = 30f;

    [Header("Ammo Settings")]
    public int maxAmmo = 10;
    private int currentAmmo;
    public float reloadTime = 1f;
    private bool isReloading = false;

    [Header("Spread & Multi-Bullet")]
    public float spread = 0.05f;
    public int bulletsPerShot = 1;

    [Header("Fire Mode")]
    public FireMode fireMode = FireMode.FullAuto;
    public int burstCount = 3;

    [Header("Effects & Layers")]
    public LayerMask WhatIsEnemy;
    public GameObject enemyImpactEffect;
    public GameObject defaultImpactEffect;
    private int ignorePlayerMask;

    [Header("Headshot Settings")]
    public float headshotMultiplier = 2.0f;
    public string headTag = "Head";

    [Header("References")]
    public Camera fpsCamera;
    public Animator holderAnimator;
    public Animator weaponAnimator;
    public TextMeshProUGUI ammotext;
    public CamRecoil recoil;
    public PlayerMovement playermovement;
    public ShootEffect effect;
    public Animator crosshairAnim;
    public PlayerUpgrades upgrades;
    public Blood blood;
    public ScreenEffectsController screenEffectsController;

    private float nextTimeToFire = 0f;
    private bool isShooting = false;

    void Start()
    {
        upgrades = GameObject.FindGameObjectWithTag("Upgrades").GetComponent<PlayerUpgrades>();
        ignorePlayerMask = ~LayerMask.GetMask("Player");

        if (upgrades.extraAmmoPerReload)
            maxAmmo += (int)(maxAmmo / 3f);

        if (upgrades.improvedAccuracy)
            spread += spread / 3f;

        if (upgrades.highRishHighReward)
            damage *= 2f;

        currentAmmo = maxAmmo;
    }

    void OnEnable()
    {
        isReloading = false;
        if (holderAnimator != null)
            holderAnimator.SetBool("IsReloading", false);
    }

    void Update()
    {
        if (isReloading) return;

        ammotext.SetText(currentAmmo.ToString());

        if (currentAmmo <= 0 || (Input.GetKey(KeyCode.R) && currentAmmo != maxAmmo))
        {
            StartCoroutine(Reload());
            return;
        }

        HandleFireInput();
        UpdateRunningAnimation();
    }

    void HandleFireInput()
    {
        if (fireMode == FireMode.FullAuto && Input.GetButton("Fire1") && Time.time >= nextTimeToFire)
        {
            nextTimeToFire = Time.time + 1f / fireRate;
            Shoot();
        }
        else if (fireMode == FireMode.SemiAuto && Input.GetButtonDown("Fire1") && Time.time >= nextTimeToFire)
        {
            nextTimeToFire = Time.time + 1f / fireRate;
            Shoot();
        }
        else if (fireMode == FireMode.Burst && Input.GetButtonDown("Fire1") && !isShooting)
        {
            StartCoroutine(BurstFire());
        }
    }

    void UpdateRunningAnimation()
    {
        if (!isReloading)
        {
            bool isWalking = playermovement.state == PlayerMovement.MovementState.walking;
            bool isMoving = Input.GetAxisRaw("Horizontal") != 0 || Input.GetAxisRaw("Vertical") != 0;
            holderAnimator.SetBool("Running", isWalking && isMoving);
        }
    }

    IEnumerator Reload()
    {
        crosshairAnim.SetBool("Reloading", true);
        isReloading = true;

        if (holderAnimator != null)
            holderAnimator.SetBool("IsReloading", true);

        yield return new WaitForSeconds(reloadTime * upgrades.reloadSpeedMultiplier - 0.25f);

        if (holderAnimator != null)
            holderAnimator.SetBool("IsReloading", false);

        yield return new WaitForSeconds(0.25f);

        currentAmmo = maxAmmo;
        crosshairAnim.SetBool("Reloading", false);
        isReloading = false;
    }

    void Shoot()
    {
        if (currentAmmo <= 0) return;

        weaponAnimator.Play(weaponAnimator.gameObject.name + "Shoot", -1, 0f);
        crosshairAnim.Play("CrosshairShoot", -1, 0f);
        recoil.Fire();
        currentAmmo--;

        StartCoroutine(effect.Flash());

        screenEffectsController.PulseChromatic(1.0f, 0.2f);
        screenEffectsController.PulseBloom(10f, 0.1f);
        screenEffectsController.DesaturationFlash(0.1f);
        screenEffectsController.LensPunch(-0.5f, 0.15f);

        for (int i = 0; i < bulletsPerShot; i++)
        {
            Vector3 direction = (fpsCamera.transform.forward + new Vector3(
                Random.Range(-spread, spread),
                Random.Range(-spread, spread),
                Random.Range(-spread, spread)
            )).normalized;

            RaycastHit hit;
            if (Physics.Raycast(fpsCamera.transform.position, direction, out hit, range, ignorePlayerMask))
            {
                Debug.DrawRay(fpsCamera.transform.position + fpsCamera.transform.forward * 0.7f, direction * range, Color.red, 1.5f);
                Debug.Log($"Raycast hit: {hit.transform.name}");

                float finalDamage = damage;
                Target enemyTarget = hit.transform.GetComponentInParent<Target>();

                if (enemyTarget != null)
                {
                    if (hit.collider.CompareTag(headTag))
                    {
                        finalDamage *= headshotMultiplier;
                        blood.GainBlood(30);
                        Debug.Log("HEADSHOT! Damage: " + finalDamage);
                    }

                    if (currentAmmo == maxAmmo - 1 && upgrades.extraFirstBulletDamage)
                    {
                        finalDamage = 150;
                    }

                    enemyTarget.TakeDamage(finalDamage);
                }

                if (hit.rigidbody != null)
                {
                    hit.rigidbody.AddForce(-hit.normal * impactForce);
                }

                GameObject impactPrefab = ((WhatIsEnemy & (1 << hit.transform.gameObject.layer)) != 0) ? enemyImpactEffect : defaultImpactEffect;
                GameObject impactGO = Instantiate(impactPrefab, hit.point, Quaternion.LookRotation(hit.normal));
                Destroy(impactGO, 2f);
            }
        }
    }

    IEnumerator BurstFire()
    {
        isShooting = true;
        for (int i = 0; i < burstCount; i++)
        {
            if (currentAmmo > 0)
            {
                Shoot();
                yield return new WaitForSeconds(1f / fireRate);
            }
            else break;
        }
        isShooting = false;
    }
}