using UnityEngine;

public class PlayerMovement : MonoBehaviour
{
    private float horizontal;
    private float speed = 8f;
    private float jumpingPower = 10f;
    private bool isFacingRight = true;

    private bool isWallSliding;
    private float wallSlidingSpeed = 2f;

    private bool isWallJumping;
    private float wallJumpingDirection;
    private float wallJumpingTime = 0.4f;
    private float wallJumpingCounter;
    private float maxWallJumpSpeed = 5f;
    private Vector2 wallJumpingPower = new Vector2(5f, 9f);
    private bool canWallJump = true;
    private float wallJumpCooldown = 0.2f; // Duration of the cooldown period

    [SerializeField] private Rigidbody2D rb;           // Assign in Inspector
    [SerializeField] private Transform groundCheck;      // Assign in Inspector
    [SerializeField] private LayerMask groundLayer;        // Assign in Inspector
    [SerializeField] private Transform wallCheck;        // Assign in Inspector
    [SerializeField] private LayerMask wallLayer;          // Assign in Inspector
    [SerializeField] private BoxCollider2D playerCollider; // Assign in Inspector

    void Update()
    {
        horizontal = Input.GetAxisRaw("Horizontal");

        if (Input.GetButtonDown("Jump") && IsGrounded())
        {
            rb.linearVelocity = new Vector2(rb.linearVelocity.x, jumpingPower);
        }

        if (Input.GetButtonUp("Jump") && rb.linearVelocity.y > 0f)
        {
            rb.linearVelocity = new Vector2(rb.linearVelocity.x, rb.linearVelocity.y * 0.5f);
        }

        // Slide input has been moved to a separate script

        wallSlide();
        wallJump();

        if (!isWallJumping)
        {
            Flip();
        }
    }

    private bool IsGrounded()
    {
        return Physics2D.OverlapCircle(groundCheck.position, 0.3f, groundLayer);
    }

    private void FixedUpdate()
    {
        // Get a reference to the PlayerSlide script (e.g., via GetComponent)
        
        PlayerSlide slideScript = GetComponent<PlayerSlide>();
        if (!isWallJumping)
        {
            rb.linearVelocity = new Vector2(horizontal * speed, rb.linearVelocity.y);
        }
    }

    private bool isWalled()
    {
        return Physics2D.OverlapCircle(wallCheck.position, 0.2f, wallLayer);
    }

    private void wallSlide()
    {
        if (isWalled() && !IsGrounded() && horizontal != 0f)
        {
            isWallSliding = true;
            rb.linearVelocity = new Vector2(rb.linearVelocity.x, Mathf.Clamp(rb.linearVelocity.y, -wallSlidingSpeed, float.MaxValue));
        }
        else
        {
            isWallSliding = false;
        }
    }

    private void wallJump()
    {
        if (isWallSliding && canWallJump)
        {
            isWallJumping = false;
            wallJumpingDirection = -transform.localScale.x;
            wallJumpingCounter = wallJumpingTime;

            CancelInvoke(nameof(stopWallJumping));
        }
        else
        {
            wallJumpingCounter -= Time.deltaTime;
        }

        if (Input.GetButtonDown("Jump") && wallJumpingCounter > 0f && canWallJump)
        {
            isWallJumping = true;
            rb.linearVelocity = new Vector2(wallJumpingDirection * wallJumpingPower.x, wallJumpingPower.y);
            wallJumpingCounter = 0f;

            if (transform.localScale.x != wallJumpingDirection)
            {
                isFacingRight = !isFacingRight;
                Vector3 localScale = transform.localScale;
                localScale.x *= -1f;
                transform.localScale = localScale;
            }

            float clampedX = Mathf.Clamp(rb.linearVelocity.x, -maxWallJumpSpeed, maxWallJumpSpeed);
            rb.linearVelocity = new Vector2(clampedX, rb.linearVelocity.y);

            canWallJump = false;
            Invoke(nameof(ResetWallJump), wallJumpCooldown);
            Invoke(nameof(stopWallJumping), wallJumpingTime);
        }
    }

    private void ResetWallJump()
    {
        canWallJump = true;
    }

    private void stopWallJumping()
    {
        isWallJumping = false;
    }

    private void Flip()
    {
        if ((isFacingRight && horizontal < 0) || (!isFacingRight && horizontal > 0))
        {
            isFacingRight = !isFacingRight;
            Vector3 localScale = transform.localScale;
            localScale.x *= -1f;
            transform.localScale = localScale;
        }
    }
}