using HtmlAgilityPack;
using System;
using System.ComponentModel.DataAnnotations;
using System.Globalization;
using System.Net;
using System.Reflection;
using System.Text.RegularExpressions;

namespace BackOffice.Common.Utilities;

public static class Extensions
{
    public static string ExtractUserFriendlyMessage(this string errorMessage)
    {
        // کلیدواژه‌ای که بعد از آن بخش مورد نظر شروع می‌شود
        string keyword = "Exception:";

        // بررسی وجود کلیدواژه در پیام خطا
        int keywordIndex = errorMessage.IndexOf(keyword);

        if (keywordIndex >= 0)
        {
            // استخراج بخش بعد از کلیدواژه
            string userFriendlyMessage = errorMessage.Substring(keywordIndex + keyword.Length).Trim();
            if (userFriendlyMessage.EndsWith(")"))
            {
                userFriendlyMessage = userFriendlyMessage.Substring(0, userFriendlyMessage.Length - 2);
            }
            return userFriendlyMessage;
        }

        // اگر کلیدواژه وجود نداشت، کل پیام خطا برگردانده شود
        return errorMessage;
    }
    public static string ToDashString(this string? text) => string.IsNullOrWhiteSpace(text) ? "-" : text;
    public static string ToThousands(this double? digit) => digit == null ? "0" : digit.Value.ToString("N0");
    public static string ToThousands(this float? digit) => digit == null ? "0" : digit.Value.ToString("N0");
    public static string ToThousands(this int? digit) => digit == null ? "0" : digit.Value.ToString("N0");
    public static string ToThousands(this long? digit) => digit == null ? "0" : digit.Value.ToString("N0");
    public static string ToThousands(this double digit) => digit.ToString("N0");
    public static string ToThousands(this float digit) => digit.ToString("N0");
    public static string ToThousands(this int digit) => digit.ToString("N0");
    public static string ToThousands(this long digit) => digit.ToString("N0");
    public static string ToCurrency(this string price) => price + " ریال";
    public static DateTime UnixTimeStampToDateTime(this long unixTimeStamp)
    {
        // Unix timestamp is seconds past epoch
        DateTime dateTime = new(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
        dateTime = dateTime.AddMilliseconds(unixTimeStamp).ToLocalTime();
        return dateTime;
    }
    public static string PersianToEnglish(this string persianStr)
    {
        return persianStr.Replace("۰", "0")
            .Replace("۱", "1")
            .Replace("۲", "2")
            .Replace("۳", "3")
            .Replace("۴", "4")
            .Replace("۵", "5")
            .Replace("۶", "6")
            .Replace("۷", "7")
            .Replace("۸", "8")
            .Replace("۹", "9");
    }
    public static string ArabicToPersian(this string arabicStr)
    {
        return arabicStr
            .Replace("ک", "ك")
            .Replace("ی", "ي");
    }
    public static string Truncate(this string value, int maxLength, bool isAppendDots = false)
    {
        if (string.IsNullOrEmpty(value)) return value;
        return value.Length <= maxLength ? value : isAppendDots ? value.Substring(0, maxLength) + "..." : value.Substring(0, maxLength);
    }

    public static string DiffDateTime(this DateTime dateTime)
    {
        const int SECOND = 1;
        const int MINUTE = 60 * SECOND;
        const int HOUR = 60 * MINUTE;
        const int DAY = 24 * HOUR;
        const int MONTH = 30 * DAY;
        var ts = new TimeSpan(DateTime.Now.Ticks - dateTime.Ticks);
        double delta = Math.Abs(ts.TotalSeconds);
        if (delta < 1 * MINUTE)
        {
            return ts.Seconds == 1 ? "لحظه ای قبل" : ts.Seconds + " ثانیه قبل";
        }
        if (delta < 2 * MINUTE)
        {
            return "یک دقیقه قبل";
        }
        if (delta < 45 * MINUTE)
        {
            return ts.Minutes + " دقیقه قبل";
        }
        if (delta < 90 * MINUTE)
        {
            return "یک ساعت قبل";
        }
        if (delta < 24 * HOUR)
        {
            return ts.Hours + " ساعت قبل";
        }
        if (delta < 48 * HOUR)
        {
            return "دیروز";
        }
        if (delta < 30 * DAY)
        {
            return ts.Days + " روز قبل";
        }
        if (delta < 12 * MONTH)
        {
            int months = Convert.ToInt32(Math.Floor((double)ts.Days / 30));
            return months <= 1 ? "یک ماه قبل" : months + " ماه قبل";
        }
        int years = Convert.ToInt32(Math.Floor((double)ts.Days / 365));
        return years <= 1 ? "یک سال قبل" : years + " سال قبل";
    }
    public static bool GenericEquals<T>(this T value1, T value2)
    {
        if (value1 == null && value2 == null)
            return true;

        if (value1 != null && value2 == null || value1 == null && value2 != null)
            return false;

        foreach (var item in value1.GetType().GetProperties())
        {
            var val1 = item.GetValue(value1);
            var val2 = value2.GetType().GetProperty(item.Name).GetValue(value2);

            if (Convert.GetTypeCode(val1) == TypeCode.Object)
                continue;

            var strVal = Convert.ToString(val1);
            var strVal2 = Convert.ToString(val2);
            if (!strVal.Equals(strVal2))
            {
                return false;
            }
        }

        return true;
    }

    public static string GetDisplayName(this Enum enumValue)
    {
        try
        {
            return enumValue.GetType().GetMember(enumValue.ToString()).First().GetCustomAttribute<DisplayAttribute>()?.GetName();
        }
        catch (Exception ex)
        {
            return "";
        }
    }
    public static void ChangeLoading(ref bool loading, ref bool toLoading)
    {
        loading = toLoading;
    }
    //public static bool IsValidURL(this string source)
    //{
    //    Uri uri = null;
    //    if (!Uri.TryCreate(source, UriKind.Absolute, out uri) || null == uri)
    //        return false;
    //    else
    //        return true;
    //}
    public static bool IsValidUrl(this string webSiteUrl)
    {
        if (webSiteUrl.StartsWith("www."))
        {
            webSiteUrl = "http://" + webSiteUrl;
        }

        return Uri.TryCreate(webSiteUrl, UriKind.Absolute, out Uri uriResult)
                 && (uriResult.Scheme == Uri.UriSchemeHttp
                  || uriResult.Scheme == Uri.UriSchemeHttps) && uriResult.Host.Replace("www.", "").Split('.').Count() > 1 && uriResult.HostNameType == UriHostNameType.Dns && uriResult.Host.Length > uriResult.Host.LastIndexOf(".") + 1 && 100 >= webSiteUrl.Length;
    }

    public static string HtmlToText(this string html)
    {
        if (string.IsNullOrWhiteSpace(html))
            return string.Empty;

        HtmlDocument doc = new HtmlDocument();
        doc.LoadHtml(html);
        string text = doc.DocumentNode.InnerText;

        return WebUtility.HtmlDecode(text).Trim(); // ← این خط مهمه
    }
}
