using System.Collections;
using System.Collections.Generic;
using TreeEditor;
using UnityEngine;
using UnityEngine.InputSystem;

[System.Serializable]
public class PlayerStat
{
    public PlayerData data;
    public PlayerStat() { }

    public PlayerStat(PlayerData data)
    {
        this.data = data;
    }
}
public class PlayerController : MonoBehaviour
{
    [Header("Player Datas")]
    [SerializeField] private PlayerData playerData;

    // 런타임에서 계산된 스탯을 담아둘 리스트
    private PlayerStat playerStat;
    private PlayerStat currentStat;

    [SerializeField] private Rigidbody2D rbody;
    private Vector2 moveInput;

    private float axisH = 0.0f;   // 좌우 입력 값 저장
    bool isDash = false;   // 대시 플래그
    bool goJump = false;   // 점프 개시 플래그
    bool isDead = false;   // 사망 플래그
    bool onGround = false;   // 지면에 서 있는 플래그
    bool isHit = false;
    private bool isInvincible = false;
    public LayerMask groundLayer;   // 착지할 수 있는 레이어

    private Animator animator;
    private Animator nanimator;
    private Animator tanimator;
    private PlayerAttacks playerAttacks;
    SpriteRenderer spriteRenderer;


    [SerializeField] private GameObject nano;
    [SerializeField] private GameObject tera;
    bool isnano = false;
    bool istera = false;
    int CurrentHp;

    [Header("Tag System")]
    private float maxGauge = 60f; // 한 칸을 채우는 데 필요한 게이지
    private float CurrentGauge;
    private int TagCount;
    private int maxTagCount = 5;

    void Start()
    {
        if (playerData != null) playerStat = new PlayerStat(playerData);

        nano.SetActive(true);
        isnano = true;
        tera.SetActive(false);
        currentStat = playerStat;

        rbody = GetComponent<Rigidbody2D>();
        nanimator = nano.GetComponent<Animator>();
        tanimator = tera.GetComponent<Animator>();
        playerAttacks = GetComponent<PlayerAttacks>();

        CurrentHp = playerStat.data.playerHp;
        CurrentGauge = playerStat.data.playerCurrentGauge;
        TagCount = playerStat.data.playerTagCount;
    }

    public void ChargeTagGauge(float amount)
    {
        // 태그 카운트가 이미 최대라면 더 이상 충전하지 않음
        if (TagCount >= maxTagCount) return;

        CurrentGauge += amount;
        Debug.Log($"게이지 충전: +{amount} / 현재 게이지: {CurrentGauge}");

        // 게이지가 60을 넘었을 때 카운트 처리 (이월 포함)
        while (CurrentGauge >= maxGauge && TagCount < maxTagCount)
        {
            CurrentGauge -= maxGauge; // 오버된 만큼 이월
            TagCount++;
            Debug.Log($"태그 카운트 상승! 현재 카운트: {TagCount}");

            // 카운트가 최대치에 도달하면 게이지를 0으로 고정하고 탈출
            if (TagCount >= maxTagCount)
            {
                CurrentGauge = 0;
                Debug.Log("태그 카운트 최대 도달! 태그 준비 완료.");
                break;
            }
        }
    }


    public void OnTagKey(InputValue value)
    {
        if (isDead) return;
        if (!value.isPressed) return;

        if (TagCount < maxTagCount)
        {
            Debug.Log($"태그 불가! 카운트가 부족합니다. (현재: {TagCount}/{maxTagCount})");
            return;
        }

        Debug.Log(" Z 버튼 눌림! ");

        isnano = !isnano;
        istera = !isnano;
        nano.SetActive(isnano);
        tera.SetActive(istera);

        if (CurrentHp < 5)
        {
            CurrentHp += 1;
        }

        animator = (isnano) ? nanimator : tanimator;
        TagCount = 0;
        CurrentGauge = 0;
    }

    void OnMove(InputValue value)
    {
        if (isDead) return;
        // Vector2 값 중 x축(좌우) 값만 가져옴
        Vector2 inputVector = value.Get<Vector2>();
        axisH = inputVector.x;
    }
    void OnDash(InputValue value)
    {
        if (isDead) return;
        isDash = value.isPressed;

        if (isDash) Debug.Log("대시 중...");
        else Debug.Log("대시 중단");
    }
    public void OnJump(InputValue value)
    {
        if (isDead) return;
        // 버튼이 눌린 순간(isPressed)이고 지면 위라면 점프 예약
        if (value.isPressed && onGround)
        {
            goJump = true;
            if (isnano)  nanimator.SetBool("jump", true);
            else if (istera)  tanimator.SetBool("jump", true);
            Debug.Log(" 점프 버튼 눌림! ");
        }
    }

    public void OnSAtk(InputValue value)
    {
        if (isDead) return;
        if (!value.isPressed) return;

        Debug.Log(" s 버튼 눌림! ");
        if (playerAttacks.IsAnyWeaponInUse) return;

        playerAttacks.IsAnyWeaponInUse = true;
        StartCoroutine(playerAttacks.ableAtk(0, "SAtk", isnano));
    }

    public void OnAAtk(InputValue value)
    {
        if (isDead) return;
        if (!value.isPressed) return;

        Debug.Log(" a 버튼 눌림! ");
        if (playerAttacks.IsAnyWeaponInUse) return;

        playerAttacks.IsAnyWeaponInUse = true;
        StartCoroutine(playerAttacks.ableAtk(0, "AAtk", isnano));
    }


    void Update()
    {
        if (isDead) return;

        bool isMoving = axisH != 0;
        // 지면 상태 확인
        if (isnano) nanimator.SetBool("jump", !onGround);
        else if (istera) tanimator.SetBool("jump", !onGround);

        if (isnano) nanimator.SetBool("Dash", isDash);
        else if (istera) tanimator.SetBool("Dash", isDash);
        if (isnano) nanimator.SetBool("Move", isMoving);
        else if (istera) tanimator.SetBool("Move", isMoving);

        // 플래그 초기화
        if (Keyboard.current.leftShiftKey.wasReleasedThisFrame) isDash = false;

        // 방향 조절
        if (isMoving && !playerAttacks.IsAnyWeaponInUse)
        {
            float direction = axisH > 0 ? 1 : -1;
            transform.localScale = new Vector2(direction, 1);
        }

        else
        {
            if (isnano) nanimator.SetBool("Dash", false);
            else if (istera) tanimator.SetBool("Dash", false);
        }
    }

    private void FixedUpdate()
    {
        onGround = Physics2D.Linecast(transform.position,
                                      transform.position - (transform.up * 0.1f),
                                      groundLayer);

        if (isDead || isHit) return;

        // 공격중인지 확인
        if (playerAttacks.IsAnyWeaponInUse && onGround)
        {
            rbody.linearVelocity = new Vector2(0, rbody.linearVelocity.y); // 정지
            return;
        }

        float speed = (isDash && onGround) ? currentStat.data.playerDashSpeed : currentStat.data.playerDefaultSpeed;
        rbody.linearVelocity = new Vector2(axisH * speed, rbody.linearVelocity.y);

        if (goJump)
        {
            Debug.Log("점프!");
            rbody.AddForce(Vector2.up * currentStat.data.playerJumpPower, ForceMode2D.Impulse);
            goJump = false;
        }
    }


    private void OnTriggerEnter2D(Collider2D collision)
    {
        if (isDead) return;
        if (collision.CompareTag("Goal"))
        {
            GameStop();
        }

        else if (collision.CompareTag("Dead"))
        {
            GameOver();
        }
    }

    public void TakeDamage(int damageAmount, Vector2 attackerPos)  //데미지 크기, 공격 위치
    {
        // 이미 죽었거나, 무적 상태라면 데미지 무시
        if (isDead || isInvincible) return;

        // 체력 감소
        CurrentHp -= damageAmount;

        Debug.Log($"남은 체력: {CurrentHp}");

        // 체력 0 체크
        if (CurrentHp <= 0)
        {
            Die();
            return;
        }

        // 넉백 및 무적 코루틴 실행
        StartCoroutine(KnockBack(attackerPos));
    }
    IEnumerator KnockBack(Vector2 attackerPos)
    {
        isHit = true;
        isInvincible = true; 

        Vector2 knockbackDir = (transform.position - (Vector3)attackerPos).normalized;
        rbody.linearVelocity = Vector2.zero;
        rbody.AddForce(knockbackDir * 2f + Vector2.up * 1f, ForceMode2D.Impulse);

        if (spriteRenderer != null) spriteRenderer.color = new Color(1, 0, 0, 0.5f);

        yield return new WaitForSeconds(0.5f);
        isHit = false;

        if (spriteRenderer != null) spriteRenderer.color = Color.white;

        yield return new WaitForSeconds(1f);
        isInvincible = false;
    }

    void Die()
    {
        isDead = true;
        animator.SetTrigger("Die");
        rbody.linearVelocity = Vector2.zero;
        GetComponent<Collider2D>().enabled = false;
    }


public void GameStop()
    {
        rbody.linearVelocity = Vector2.zero;
    }

    public void GameOver()
    {
        isDead = true;
        animator.SetBool("Move", false);
        //anim.SetTrigger("Die");
        GameStop();
    }
}
