using System.Collections;
using System.Linq;
using Cat;
using NUnit.Framework.Constraints;
using UnityEngine;

public enum CatReaction
{
    Heart,
    Heartbreak,
    DirtyLitterbox,
    WaitingForPets,

    DeadCat
}

public class CatAI : UtilityAI
{
    [Header("Petting")]
    [SerializeField] private ActionAdvertiser pleasureAdvertiser;
    [SerializeField] private float petTimeWindow = 6f;

    private bool waitingForPet = false;
    private bool wasPet = false;

    [Header("Litterbox")]
    [SerializeField] private Litterbox litterbox;
    [SerializeField] private ActionAdvertiser litterboxAdvertiser;

    [Header("Sleeping")]
    [SerializeField] private Sprite sleepSprite;
    [SerializeField] private SpriteRenderer catRenderer;

    [Header("Food")]
    [SerializeField] private Bowl bowl;
    private bool emptyBowlSoundPlayed = false;

    [Header("Final Action")]
    public ActionAdvertiser catBedAdvertiser;
    private bool finalActionTriggered = false;

    private Animator catAnimator;
    private Sprite originalCatSprite;

    [SerializeField] private GameObject deadCat;


    [Header("Reaction Visuals")]
    [SerializeField] private SpriteRenderer reactionRenderer;

    [SerializeField] private Sprite heartSprite;
    [SerializeField] private Sprite heartbreakSprite;
    [SerializeField] private Sprite dirtyLitterboxSprite;
    [SerializeField] private Sprite waitingForPetsSprite;
    [SerializeField] private Sprite deadCatSprite;

    private Coroutine reactionCoroutine;

    protected override void Awake()
    {
        base.Awake();
        catAnimator = catRenderer.GetComponent<Animator>();
        originalCatSprite = catRenderer.sprite;
    }

    protected override void OnReachedTarget()
    {
        // EMPTY BOWL, hungry sound
        if (currentAction != null &&
            currentAction.advertiser != null &&
            currentAction.advertiser.actionName == "Bowl" &&
            bowl.IsEmpty &&
            !emptyBowlSoundPlayed)
        {
            AudioManager.Instance?.PlayCatHungry();
            emptyBowlSoundPlayed = true;
        }

        if (finalActionTriggered &&
            currentAction != null &&
            currentAction.advertiser == catBedAdvertiser)
        {
            GetComponent<GrandmaMovement>().enabled = false;
            catRenderer.sprite = sleepSprite;
            GetComponent<Animator>().enabled = false;
            GetComponent<CatAI>().enabled = false;
            return;
        }

        base.OnReachedTarget();
    }
    protected override void OnActionStarted(GrandmaAction action)
    {

        // CatBed : sleep visually during wait
        if (action.advertiser != null && action.advertiser.actionName == "CatBed")
        {
            if (catAnimator != null)
                catAnimator.enabled = false;

            if (sleepSprite != null)
                catRenderer.sprite = sleepSprite;
        }

        // Pleasure action: check if the player petted
        if (action.advertiser.actionName == "Petting")
        {
            StartCoroutine(WaitForPet());
        }

        // Litterbox action
        if (action.advertiser == litterboxAdvertiser)
        {
            HandleLitterboxUse();
        }

    }

    protected override void OnActionCompleted(GrandmaAction action)
    {
        if (action.advertiser != null && action.advertiser.name == "CatBed")
        {
            catRenderer.sprite = originalCatSprite;

            if (catAnimator != null)
                catAnimator.enabled = true;
        }

        if (action.advertiser != null && action.advertiser.actionName == "Bowl")
        {
            if (!bowl.IsEmpty)
            {
                bowl.Eat();
                emptyBowlSoundPlayed = false;
            }

        }


    }

    /* PETTING  */

    private IEnumerator WaitForPet()
    {
        waitingForPet = true;
        wasPet = false;

        AudioManager.Instance?.PlayCatWantsPets();

        float t = 0f;
        while (t < petTimeWindow)
        {
            t += Time.deltaTime;
            ShowReaction(CatReaction.WaitingForPets, petTimeWindow);
            if (wasPet)
            {
                ShowReaction(CatReaction.Heart, 3f);
                AudioManager.Instance.PlayCatSatisfied();
                waitingForPet = false;
                break;
            }
            yield return null;

        }

        if (!wasPet)
        {
            // Player ignored cat, pee on ground
            Debug.Log("Cat was not petted in time, peeing on the ground.");
            AudioManager.Instance?.PlayCatPee();
            ShowReaction(CatReaction.Heartbreak, 3f);
            SpawnPuddle();
        }

        waitingForPet = false;
        //currentAction = null;
    }

    public void RegisterPet()
    {
        if (!waitingForPet) return;
        wasPet = true;
    }

    /* LITTERBOX */

    private void HandleLitterboxUse()
    {
        bool isClean = litterbox.IsClean;
        if (litterbox != null)
        {
            if (!isClean)
            {
                SpawnTrash();
            }

            litterbox.ShowCatInside(true);
        }

        StartCoroutine(FinishLitterboxUse(isClean));
    }


    private IEnumerator FinishLitterboxUse(bool wasClean)
    {
        yield return new WaitForSeconds(currentActionAdvertiser.progressDuration);
        litterbox.Use();
        if (!wasClean)
        {
            ShowReaction(CatReaction.DirtyLitterbox, 3f);
        }
        litterbox.ShowCatInside(false);
        //currentAction = null;
    }

    /* FOOD BOWL */

    protected override bool CanFulfillNeed(GrandmaAction action)
    {
        if (action.advertiser.actionName == "Bowl")
            return !bowl.IsEmpty;

        return true;
    }


    public void TriggerFinalAction()
    {
        finalActionTriggered = true;

        ClearActions();
        GrandmaAction finalSleep = new GrandmaAction(catBedAdvertiser, 999f);
        finalSleep.advertiser.progressDuration = 100;

        actionQueue.Enqueue(finalSleep);
    }

    protected override void UpdateNeeds()
    {
        if (waitingForPet)
            return;
        bool committedToNonFood =
            currentAction != null &&
            !movement.ReachedTarget() &&
            (currentAction.advertiser.actionName == "Bowl" ||
            currentAction.advertiser.actionName == "Litterbox");

        bool bowlQueued =
            actionQueue.Any(a => a.advertiser.actionName == "Bowl");

        bool suppressFoodDecay = committedToNonFood || bowlQueued;

        foreach (var need in needs)
        {
            if (need.name == "Food" && suppressFoodDecay)
                continue;

            need.UpdateNeed(Time.deltaTime);
        }

        var food = needs.FirstOrDefault(n => n.name == "Food");

        if (food != null &&
            food.value <= 0f &&
            bowl.IsEmpty &&
            !suppressFoodDecay)
        {
            Debug.Log("Cat has starved to death!");
            AudioManager.Instance?.PlayCatDeath();
            ShowReaction(CatReaction.DeadCat, 5f);
            deadCat.SetActive(true);
            GetComponent<Animator>().enabled = false;
            GetComponent<SpriteRenderer>().enabled = false;
            GetComponent<CatAI>().enabled = false;
            GetComponent<GrandmaMovement>().enabled = false;
        }
    }


    /* SPAWNS */

    private void SpawnPuddle()
    {
        PuddleSpawner.Instance.Spawn(transform.position);
    }

    private void SpawnTrash()
    {
        CatTrashSpawner.Instance.SpawnTrashBehind(transform);
    }

    private void ShowReaction(CatReaction reaction, float duration)
    {
        if (reactionRenderer == null)
            return;

        if (reactionCoroutine != null)
            StopCoroutine(reactionCoroutine);

        Sprite sprite = reaction switch
        {
            CatReaction.Heart => heartSprite,
            CatReaction.Heartbreak => heartbreakSprite,
            CatReaction.DirtyLitterbox => dirtyLitterboxSprite,
            CatReaction.WaitingForPets => waitingForPetsSprite,
            CatReaction.DeadCat => deadCatSprite,
            _ => null
        };

        if (sprite == null)
            return;

        reactionCoroutine = StartCoroutine(ReactionRoutine(sprite, duration));
    }

    private IEnumerator ReactionRoutine(Sprite sprite, float duration)
    {
        reactionRenderer.sprite = sprite;
        reactionRenderer.enabled = true;

        yield return new WaitForSeconds(duration);

        reactionRenderer.enabled = false;
        reactionRenderer.sprite = null;
    }

}