using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

namespace Gyvr.Mythril2D
{
    public class Mount : Character<MountSheet>
    {
        private CharacterBase m_rider;
        private List<ITemporalEffect> m_appliedTemporalEffects = new();
        private float m_remountCooldownTimer = 0f;
        private Rigidbody2D m_mountRigidbody;
        private MountController m_mountController;

        public bool IsMounted => m_rider != null;
        public bool IsInRemountCooldown => m_remountCooldownTimer > 0f;

        public CharacterBase rider => m_rider;

        private void Start()
        {
            m_mountRigidbody = GetComponent<Rigidbody2D>();
            m_mountController = (MountController)m_controller;
        }

        protected override void InitializeStats()
        {
            UpdateStats();
        }

        public void SetLevel(int level)
        {
            m_level = level;
            UpdateStats();
        }

        public void UpdateStats()
        {
            m_stats.Set(m_sheet.stats[m_level]);
        }

        public void MountPlayer(CharacterBase rider)
        {
            m_mountController.ClearStaleOrders();
            m_rider = rider;

            EffectApplicationResult result = EffectDispatcher.Apply(this, new[] { rider }, m_sheet.mountEffects);

            m_appliedTemporalEffects.Clear();
            foreach (var target in result.affectedTargets)
            {
                if (target == rider)
                {
                    foreach (var effect in target.temporalEffects)
                    {
                        if (effect.initialized && m_sheet.mountEffects.Any(e => effect.stackableEffectId == (e as ITemporalEffect)?.stackableEffectId))
                        {
                            m_appliedTemporalEffects.Add(effect);
                        }
                    }
                }
            }

            SetSimulated(false);
            SetMountLayer("Default");

            if (m_mountController != null)
            {
                ((MountPolydirectionalAnimationStrategy)m_animationStrategy)?.SetMountedState(true);

                if (m_rider.controller is RiderController riderController)
                {
                    riderController.SetIsRiding(true);
                }

                m_mountController.SetMaster(rider);
                m_mountController.Start();

                if (m_mountController.DismountOnDamage)
                {
                    GameManager.NotificationSystem.damageApplied.AddListener(OnDamageApplied);
                }
            }
        }

        public void DismountPlayer()
        {
            if (m_rider != null)
            {
                foreach (var effect in m_appliedTemporalEffects)
                {
                    if (effect != null)
                    {
                        m_rider.RemoveTemporalEffectPrematurely(effect);
                    }
                }

                m_appliedTemporalEffects.Clear();

                if (m_mountController != null)
                {
                    m_mountController.Stop();
                    m_remountCooldownTimer = m_mountController.RemountCooldown;
                }

                ((MountPolydirectionalAnimationStrategy)m_animationStrategy)?.SetMountedState(false);

                if (m_rider.controller is RiderController riderController)
                {
                    riderController.SetIsRiding(false);
                    SetSimulated(true);
                }

                if (m_mountController.DismountOnDamage)
                {
                    GameManager.NotificationSystem.damageApplied.RemoveListener(OnDamageApplied);
                }
                m_rider = null;
            }
        }

        private void SetSimulated(bool value)
        {
            if (m_mountRigidbody != null)
            {
                m_mountRigidbody.simulated = value;
            }
        }

        private void SetMountLayer(string layer)
        {
            gameObject.layer = LayerMask.NameToLayer(layer);
        }

        private void OnDamageApplied(CharacterBase character, DamageInputDescriptor input, EEffectVisualFlags flags)
        {
            if (m_rider == character)
            {
                DismountPlayer();
            }
        }

        protected override void Update()
        {
            base.Update();

            if (IsMounted) return;

            if (!IsMounted && Vector2.Distance(transform.position, GameManager.Player.transform.position) > m_mountController.DestroyDistance)
            {
                Kill();
            }

            if (m_remountCooldownTimer > 0f)
            {
                m_remountCooldownTimer -= Time.deltaTime;

                if (m_remountCooldownTimer <= 0f)
                {
                    SetMountLayer("Interaction");
                }
            }
        }

        public override void Kill()
        {
            Debug.Log("[Mount] Kill called");
            if (IsMounted) { DismountPlayer(); }
            base.Kill();
            OnDeath();
        }

        protected override void OnDeath()
        {
            Debug.Log("[Mount] OnDeath triggered (forced destroy)");
            Destroy();
        }

        public override void Destroy()
        {
            Debug.Log("[Mount] Destroy called");
            base.Destroy();
        }
    }
}
