using UnityEngine;
using System.Collections;

public abstract class Weapon : MonoBehaviour
{
    public string weaponName;
    public string description;
    public int damage;
    public float attackSpeed;
    public GameObject weaponModel; // Assign the 3D model for the weapon

    // Reference to the character wielding this weapon
    public Character Wielder { get; private set; }

    // Track if an attack is currently in progress
    protected bool isAttacking = false;

    public float lastAttackTime { get; private set; }

    // Abstract properties that must be implemented by derived classes

    public abstract int MinDamage { get; }
    public abstract int MaxDamage { get; }
    public abstract int Range { get; }
    public abstract int WeaponModifier { get; set; }
    protected int weaponModifier = 0; // Base modifier for the weapon, can be overridden by subclasses
    protected int baseWeaponModifier = 0; // Base modifier for the weapon, used for calculations
    public float AttackStarted { get; private set; }


    public void SetWielder(Character character)
    {
        Wielder = character;
        if (Wielder == null)
        {
            Debug.LogWarning($"Weapon {weaponName} - SetWielder called with null character!");
        }
    }

    public virtual int GetDamage()
    {
        return UnityEngine.Random.Range(MinDamage, MaxDamage + 1);
    }
    public virtual bool IsInRange(Vector3 attackerPosition, Vector3 targetPosition)
    {
        float distance = Vector3.Distance(attackerPosition, targetPosition);
        return distance <= Range;
    }
    public bool IsAttacking()
    {
        return isAttacking;
    }

    // Method to perform attack - can be called by the character
    public virtual void Attack(GameObject target)
    {
        if (Wielder == null)
        {
            Debug.LogError($"Cannot attack - {weaponName} has no wielder!");
            return;
        }

        if (isAttacking)
        {
            Debug.Log($"attack started {AttackStarted} time now  {Time.time}"); ;
            Debug.Log($"{Wielder.CharacterName} is already attacking!");
            return;

        }

        Character targetCharacter = target.GetComponent<Character>();
        if (targetCharacter == null)
        {
            Debug.LogError($"Target {target.name} is not a character!");
            return;
        }

        if (!targetCharacter.IsTargetable)
        {
            Debug.Log($"Cannot attack {targetCharacter.CharacterName} - target is not targetable!");
            return;
        }

        if (!IsInRange(Wielder.transform.position, target.transform.position))
        {
            Debug.Log($"{Wielder.CharacterName} is not in range to attack {targetCharacter.CharacterName} with {weaponName}");
            return;
        }

        AttackStarted = Time.time;
        // Start the attack coroutine
        StartCoroutine(PerformAttackSequence(targetCharacter));
    }

    protected virtual IEnumerator PerformAttackSequence(Character target)
    {
        isAttacking = true;
        lastAttackTime = Time.time;
        Debug.Log($"{Wielder.CharacterName} begins attacking {target.CharacterName} with {weaponName} (attack speed: {attackSpeed}s)");

        // Wait for the attack speed duration
        yield return new WaitForSeconds(attackSpeed);

        // Check if target is still in range after attack speed delay
        if (!IsInRange(Wielder.transform.position, target.transform.position))
        {
            Debug.Log($"{target.CharacterName} moved out of range before {Wielder.CharacterName}'s attack completed!");
            isAttacking = false;
            yield break;
        }

        // Check if target is still targetable (not dead)
        if (!target.IsTargetable)
        {
            Debug.Log($"{target.CharacterName} is no longer targetable!");
            isAttacking = false;
            yield break;
        }

        // Perform hit calculation (d20 + weapon modifier vs target armor class)
        int d20Roll = Random.Range(1, 21);
        int attackRoll = d20Roll + WeaponModifier;
        bool hits = attackRoll >= target.ArmorClass;

        int healthBefore = target.CurrentHealth;

        Debug.Log($"=== ATTACK DEBUG ===");
        Debug.Log($"Attacker: {Wielder.CharacterName} with {weaponName}");
        Debug.Log($"Target: {target.CharacterName}");
        Debug.Log($"D20 Roll: {d20Roll} + Weapon Modifier: {WeaponModifier} = Attack Roll: {attackRoll}");
        Debug.Log($"Target AC: {target.ArmorClass}");
        Debug.Log($"Target Health Before: {healthBefore}/{target.MaxHealth}");

        if (hits)
        {
            int damageDealt = GetDamage();
            Debug.Log($"HIT! Damage Roll: {damageDealt}");
            target.TakeDamage(damageDealt);
            Debug.Log($"Target Health After: {target.CurrentHealth}/{target.MaxHealth}");
            Debug.Log($"{Wielder.CharacterName} hits {target.CharacterName} with {weaponName} for {damageDealt} damage!");
        }
        else
        {
            Debug.Log($"MISS! {attackRoll} < {target.ArmorClass}");
            Debug.Log($"Target Health After: {healthBefore}/{target.MaxHealth} (no change)");
            Debug.Log($"{Wielder.CharacterName} misses {target.CharacterName} with {weaponName}!");
        }

        Debug.Log($"=== END ATTACK ===");

        isAttacking = false;
    }
}
