using Knoks.Core.Entities;
using Knoks.Core.Logic.Interfaces;
using Knoks.Framework.Extentions;
using Knoks.Framework.Services;
using System;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace Knoks.Core.Logic.Managers
{
    public class PhoneManager : IPhoneManager
    {
        private const string PassPhoneEnd = "123456", PassPinCode = "1234";

        private IPhoneService _phoneService;
        private ISmsService _smsService;

        public PhoneManager(IPhoneService phoneService, ISmsService smsService)
        {
            _phoneService = phoneService;
            _smsService = smsService;
        }

        public bool IsPassPhoneNumber(PhoneNumber phoneSet)
        {
            return IsPassPhoneNumber(phoneSet.E164Format);
        }

        public bool IsPassPhoneNumber(string phoneNumber)
        {
            return phoneNumber.EndsWith(PassPhoneEnd);
        }

        public bool IsFormatted(PhoneNumber phoneNumber)
        {
            return phoneNumber.OriginalFormat != null && (phoneNumber.NationalFormat == null || phoneNumber.E164Format == null || phoneNumber.CountryCode2 == null);
        }

        public async Task<PhoneNumber> GetPhoneNumber(string phoneNumber, string countryCode = null)
        {
            var phoneSet = await _phoneService.Lookup(phoneNumber, countryCode);
            if (phoneSet == null)
            {
                throw new InvalidOperationException($"Invalid phone number: {phoneNumber}");
            }

            return phoneSet;
        }

        private static readonly int[] PinCodeBuilderArray = new int[] { 6, 5, 3, 1 };
        public string GetPinCode(PhoneNumber phoneNumber)
        {
            if (IsPassPhoneNumber(phoneNumber))
                return PassPinCode;

            return string.Concat(PinCodeBuilderArray.Select(i => phoneNumber.E164Format[i] - 48));
        }

        private static readonly Regex PinRegex = new Regex("{pin}", RegexOptions.IgnoreCase);
        
        public bool IsValidPinCode(PhoneNumber phoneNumber, string pinCode)
        {
            if (IsPassPhoneNumber(phoneNumber) && pinCode == PassPinCode)
                return true;

            return pinCode == GetPinCode(phoneNumber);
        }
    }
}
