using System;
using System.Runtime.CompilerServices;
using ModernUO.Serialization;
using Server.Engines.VeteranRewards;
using Server.Gumps;
using Server.Multis;

namespace Server.Items;

[SerializationGenerator(1)]
public partial class TreeStump : BaseAddon, IRewardItem
{
    [InvalidateProperties]
    [SerializableField(0)]
    [SerializedCommandProperty(AccessLevel.GameMaster)]
    private bool _isRewardItem;

    [InvalidateProperties]
    [SerializableField(1)]
    [SerializedCommandProperty(AccessLevel.GameMaster)]
    private int _logs;

    [SerializableField(2)]
    [SerializedCommandProperty(AccessLevel.GameMaster, AccessLevel.Administrator)]
    private DateTime _lastChecked;

    [Constructible]
    public TreeStump(int itemID)
    {
        AddComponent(new AddonComponent(itemID), 0, 0, 0);
        _lastChecked = Core.Now;
    }

    public override BaseAddonDeed Deed =>
        new TreeStumpDeed
        {
            IsRewardItem = _isRewardItem,
            Logs = _logs
        };

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    private void UpdateLogs()
    {
        var now = Core.Now;
        var daysSince = (now - _lastChecked).Days;
        _logs = Math.Min(100, _logs + daysSince * 10);
        _lastChecked = now;
    }

    public override void OnComponentUsed(AddonComponent c, Mobile from)
    {
        var house = BaseHouse.FindHouseAt(this);

        /*
         * Unique problems have unique solutions.  OSI does not have a problem with 1000s of mining carts
         * due to the fact that they have only a miniscule fraction of the number of 10 year vets that a
         * typical RunUO shard will have (RunUO's scaled down account aging system makes this a unique problem),
         * and the "freeness" of free accounts. We also dont have mitigating factors like inactive (unpaid)
         * accounts not gaining veteran time.
         *
         * The lack of high end vets and vet rewards on OSI has made testing the *exact* ranging/stacking
         * behavior of these things all but impossible, so either way its just an estimation.
         *
         * If youd like your shard's carts/stumps to work the way they did before, simply replace the check
         * below with this line of code:
         *
         * if (!from.InRange(GetWorldLocation(), 2)
         *
         * However, I am sure these checks are more accurate to OSI than the former version was.
         *
         */

        if (!from.InRange(GetWorldLocation(), 2) || !from.InLOS(this) || !(from.Z - Z > -3 && from.Z - Z < 3))
        {
            from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that.
            return;
        }

        if (house?.HasSecureAccess(from, SecureLevel.Friends) != true)
        {
            from.SendLocalizedMessage(1061637); // You are not allowed to access this.
            return;
        }

        UpdateLogs();

        if (_logs <= 0)
        {
            from.SendLocalizedMessage(1094720); // There are no more logs available.
            return;
        }

        var logs = Utility.Random(7) switch
        {
            0 => new Log(),
            1 => new AshLog(),
            2 => new OakLog(),
            3 => new YewLog(),
            4 => new HeartwoodLog(),
            5 => new BloodwoodLog(),
            _ => new FrostwoodLog()
        };

        var amount = Math.Min(10, _logs);
        logs.Amount = amount;

        if (!from.PlaceInBackpack(logs))
        {
            logs.Delete();
            from.SendLocalizedMessage(1078837); // Your backpack is full! Please make room and try again.
        }
        else
        {
            _logs -= amount;
            PublicOverheadMessage(MessageType.Regular, 0, 1094719, _logs.ToString()); // Logs: ~1_COUNT~
        }
    }

    private void Deserialize(IGenericReader reader, int version)
    {
        _isRewardItem = reader.ReadBool();
        _logs = reader.ReadInt();

        var next = reader.ReadDateTime();

        if (next < Core.Now)
        {
            next = Core.Now;
        }

        _lastChecked = next - TimeSpan.FromDays(1);
    }
}

[SerializationGenerator(0)]
public partial class TreeStumpDeed : BaseAddonDeed, IRewardItem, IRewardOption
{
    [InvalidateProperties]
    [SerializableField(0)]
    [SerializedCommandProperty(AccessLevel.GameMaster)]
    private bool _isRewardItem;

    [InvalidateProperties]
    [SerializableField(1)]
    [SerializedCommandProperty(AccessLevel.GameMaster)]
    private int _logs;

    private int _itemID;

    [Constructible]
    public TreeStumpDeed() => LootType = LootType.Blessed;

    public override int LabelNumber => 1080406; // a deed for a tree stump decoration

    public override BaseAddon Addon =>
        new TreeStump(_itemID)
        {
            IsRewardItem = _isRewardItem,
            Logs = _logs
        };

    public void GetOptions(RewardOptionList list)
    {
        list.Add(1, 1080403); // Tree Stump with Axe West
        list.Add(2, 1080404); // Tree Stump with Axe North
        list.Add(3, 1080401); // Tree Stump East
        list.Add(4, 1080402); // Tree Stump South
    }

    public void OnOptionSelected(Mobile from, int option)
    {
        _itemID = option switch
        {
            1 => 0xE56,
            2 => 0xE58,
            3 => 0xE57,
            4 => 0xE59,
            _ => _itemID
        };

        if (!Deleted)
        {
            base.OnDoubleClick(from);
        }
    }

    public override void GetProperties(IPropertyList list)
    {
        base.GetProperties(list);

        if (_isRewardItem)
        {
            list.Add(1076223); // 7th Year Veteran Reward
        }
    }

    public override void OnDoubleClick(Mobile from)
    {
        if (_isRewardItem && !RewardSystem.CheckIsUsableBy(from, this))
        {
            return;
        }

        if (IsChildOf(from.Backpack))
        {
            from.SendGump(new RewardOptionGump(this));
        }
        else
        {
            from.SendLocalizedMessage(1062334); // This item must be in your backpack to be used.
        }
    }
}
