using KitsuneCafe.ItemSystem;
using KitsuneCafe.System;
using NaughtyAttributes;
using UnityEngine;
using UnityEngine.Events;

namespace KitsuneCafe.Interaction
{
    using Result = IInteractable.Result;

    public class Gate : MonoBehaviour, IInteractable
    {
        public enum Requirement
        {
            None,
            Key,
            Switch
        }

        [SerializeField]
        private bool isOpen;

        [SerializeField]
        private bool isLocked;

        [SerializeField, ShowIf("isLocked")]
        private Requirement requirement;

        [SerializeField, ShowIf("requirement", Requirement.Key)]
        private Item key;

        [SerializeField, ShowIf("requirement", Requirement.Key)]
        private bool consumeKey;

        [SerializeField]
        private UnityEvent opened = default;

        public bool IsInteractable => true;
        public bool IsOpen => isOpen;
        public bool IsLocked => isLocked;

        public IResult<Unit, InteractionError> Interact(IInteractor interactor)
        {
            return TryOpen(interactor);
        }

        private IResult<Unit, InteractionError> TryOpen(IInteractor interactor)
        {
            if (isOpen)
            {
                return Result.Ok();
            }
            else if (!isLocked)
            {
                opened.Invoke();
                return Result.Ok();
            }
            else if (requirement == Requirement.None)
            {
                return Result.Err(InteractionErrorCode.Locked);
            }
            else if (requirement == Requirement.Switch)
            {
                return Result.Err(InteractionErrorCode.RequiresSwitch);
            }
            else if (requirement == Requirement.Key && interactor.TryGetComponent<IInventory<InventoryItem>>(out var inventory))
            {
                if (inventory.Has(key))
                {
                    if (consumeKey)
                    {
                        inventory.Remove(key);
                    }

                    ForceOpen();
                    return Result.Ok();
                }
                else
                {
                    return Result.Err(InteractionErrorCode.MissingItem);
                }
            }
            else
            {
                return Result.Err(InteractionErrorCode.MissingItem);
            }
        }

        private void ForceOpen()
        {
            isOpen = true;
            opened.Invoke();
        }
    }
}
