using TMPro;
using UnityEngine;

public class PlayerMovement : MonoBehaviour
{
    public float moveSpeed = 5f;
    public float jumpForce = 5f;
    public float jumpTime = 0.35f;
    private float jumpTimeCounter;
    private bool isJumping;

    private Rigidbody2D rb;
    public bool isGrounded;
    public Transform groundCheck;
    public float groundCheckRadius = 0.2f;
    [SerializeField] private LayerMask groundLayer;

    public float coyoteTime = 0.2f;
    private float coyoteTimeCounter;

    public float jumpBufferTime = 0.2f;
    private float jumpBufferCounter;

    public Transform firePoint;
    public GameObject bulletPrefab;
    private bool facingRight = true;

    Animator animator;

    [SerializeField] Animator gunAnimator;

    AudioSource audioSource;

    [SerializeField] AudioClip gunShotSound;
    [SerializeField] AudioClip noAmmoSound;
    [SerializeField] AudioClip reloadAmmoSound;
    [SerializeField] AudioClip healthPickupSound;

    PlayerStats playerStats;



    private void Start()
    {
        rb = GetComponent<Rigidbody2D>();
        animator = GetComponent<Animator>();
        audioSource = GetComponent<AudioSource>();
        playerStats = GetComponent<PlayerStats>();
    }

    private void Update()
    {
        Move();
        CheckGrounded();
        HandleJump();
        Aim();
        if (Input.GetButtonDown("Fire1") && GameManager.instance.gameHasEnded)
        {
            GameManager.instance.RestartGame();
        }
        if (Input.GetButtonDown("Fire1") && playerStats.currentAmmo > 0)
        {
            Shoot();
        }
        else if (Input.GetButtonDown("Fire1") && playerStats.currentAmmo <= 0)
        {
            Debug.Log("Out of ammo!");
            audioSource.PlayOneShot(noAmmoSound);
            PromptShower.instance.ShowPrompt("Out of ammo! R to reload.");
        }
        else if (Input.GetKeyDown(KeyCode.R))
        {
            playerStats.ReloadAmmo();
            audioSource.PlayOneShot(reloadAmmoSound);
            PromptShower.instance.HidePrompt();
        }

        if (Input.mousePosition.x < Screen.width / 2 && facingRight)
        {
            Flip();
        }
        else if (Input.mousePosition.x > Screen.width / 2 && !facingRight)
        {
            Flip();
        }

        animator.SetBool("isGrounded", isGrounded);
        animator.SetBool("isMoving", Input.GetAxis("Horizontal") != 0);
    }

    private void Move()
    {
        float moveX = Input.GetAxis("Horizontal");
        Vector2 move = new Vector2(moveX * moveSpeed, rb.velocity.y);
        rb.velocity = move;
    }

    private void Flip()
    {
        facingRight = !facingRight;
        Vector3 theScale = transform.localScale;
        theScale.x *= -1;
        transform.localScale = theScale;
    }

    private void HandleJump()
    {
        if (isGrounded)
        {
            coyoteTimeCounter = coyoteTime;
            jumpTimeCounter = jumpTime;
        }
        else
        {
            coyoteTimeCounter -= Time.deltaTime;
        }

        if (Input.GetButtonDown("Jump"))
        {
            jumpBufferCounter = jumpBufferTime;
        }
        else
        {
            jumpBufferCounter -= Time.deltaTime;
        }

        if (jumpBufferCounter > 0 && coyoteTimeCounter > 0 && isGrounded)
        {
            StartJump();
            jumpBufferCounter = 0;
        }

        if (Input.GetButtonUp("Jump"))
        {
            isJumping = false;
        }
    }

    private void StartJump()
    {
        isJumping = true;
        rb.velocity = new Vector2(rb.velocity.x, jumpForce);
        isGrounded = false;
    }

    private void CheckGrounded()
    {
        bool wasGrounded = isGrounded;
        isGrounded = Physics2D.OverlapCircle(groundCheck.position, groundCheckRadius, groundLayer);

        if (isGrounded && !wasGrounded)
        {
            coyoteTimeCounter = coyoteTime;
        }
    }

    private void Aim()
    {
        Vector3 mousePosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
        Vector2 direction = (mousePosition - transform.position).normalized;
        float angle = Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg;
        firePoint.rotation = Quaternion.Euler(new Vector3(0, 0, angle));
    }

    private void Shoot()
    {
        Instantiate(bulletPrefab, firePoint.position, firePoint.rotation);
        gunAnimator.SetTrigger("Shoot");
        audioSource.PlayOneShot(gunShotSound);
        playerStats.UseAmmo();
    }

    private void OnDrawGizmos()
    {
        Gizmos.color = Color.red;
        Gizmos.DrawWireSphere(groundCheck.position, groundCheckRadius);
    }

    public void HealPlayer()
    {
        audioSource.PlayOneShot(healthPickupSound);
    }
}
