using System;
using System.Globalization;
using System.Text;

namespace BMA.EHR.Recurit.Exam.Service.Extensions
{
    public static class DateTimeExtension
    {
        private static CultureInfo _culture = new CultureInfo("th-TH");

        #region " Methods "

        #region " Public "

        public static int DiffDay(this DateTime startDate, DateTime endDate)
        {
            if (endDate.Date < startDate.Date)
            {
                throw new ArgumentException("End Date must greater than start date.");
            }
            return (int)(endDate.Date - startDate.Date).TotalDays + 1;
        }

        public static double DiffYear(this DateTime currentDate)
        {
            return (DateTime.Today - currentDate).TotalDays / 365.2425;
        }

        public static int ToUnixTimeStamp(this DateTime value)
        {
            return (int)Math.Truncate((value.ToUniversalTime().Subtract(new DateTime(1970, 1, 1))).TotalSeconds);
        }

        public static string ToThaiFullDate(this DateTime value)
        {
            var yy = value.Year < 2400 ? value.Year + 543 : value.Year;
            return $"วันที่ {value.Day} เดือน {value.ToString("MMMM", _culture.DateTimeFormat)} พ.ศ. {yy}";
        }

        public static string ToThaiFullDate2(this DateTime value)
        {
            var yy = value.Year < 2400 ? value.Year + 543 : value.Year;
            return $"{value.Day} {value.ToString("MMMM", _culture.DateTimeFormat)} พ.ศ. {yy}";
        }

        public static string ToThaiFullDate3(this DateTime value)
        {
            var yy = value.Year < 2400 ? value.Year + 543 : value.Year;
            return $"{value.Day} {value.ToString("MMMM", _culture.DateTimeFormat)} {yy}";
        }

        public static string ToThaiShortDateTime(this DateTime value)
        {
            var yy = value.Year < 2400 ? value.Year + 543 : value.Year;
            return $"{value.Day} {value.ToString("MMM", _culture.DateTimeFormat)} {yy} {value.ToString("HH:mm:ss")}";
        }

        public static string ToThaiShortDate(this DateTime value)
        {
            var yy = value.Year < 2400 ? value.Year + 543 : value.Year;
            return $"{value.Day} {value.ToString("MMM", _culture.DateTimeFormat)} {yy}";
        }

        public static string ToThaiShortDate2(this DateTime value)
        {
            var yy = value.Year < 2400 ? value.Year + 543 : value.Year;
            return $"{value.Day} {value.ToString("MMM", _culture.DateTimeFormat)} {yy.ToString().Right(2)}";
        }

        public static string ToThaiDate(this DateTime value)
        {
            var yy = value.Year < 2400 ? value.Year + 543 : value.Year;
            return $"{value.Day}/{value.Month}/{yy}";
        }

        public static string ToCeDate(this DateTime value)
        {
            var yy = value.Year >= 2400 ? value.Year - 543 : value.Year;
            return $"{value.Day}/{value.Month}/{yy}";
        }

        public static string ToThaiDateFullDigit(this DateTime value)
        {
            var yy = value.Year < 2400 ? value.Year + 543 : value.Year;
            return $"{value.Day.ToString("00")}/{value.Month.ToString("00")}/{yy.ToString("00")}";
        }

        public static string GetDay(this DateTime value)
        {
            return value.Day.ToString();
        }

        public static string GetMonth(this DateTime value)
        {
            return value.ToString("MMMM", _culture.DateTimeFormat);
        }

        public static string GetYear(this DateTime value)
        {
            return value.Year.ToThaiYear().ToString();
        }

        public static string CalculateAgeStrV2(this DateTime date, int plusYear = 0, int subtractYear = 0)
        {
            try
            {
                var currentDate = DateTime.Now;
                var age = currentDate - date;


                if (date > currentDate)
                {
                    throw new ArgumentException("วันเกิดต้องไม่มากกว่าวันที่ปัจจุบัน");
                }

                int years = currentDate.Year - date.Year;
                int months = 0;
                int days = 0;

                if (currentDate.Month < date.Month ||
                    (currentDate.Month == date.Month && currentDate.Day < date.Day))
                {
                    years--;
                    months = 12 - date.Month + currentDate.Month;

                    if (currentDate.Day < date.Day)
                    {
                        months--;
                        int lastMonthDays = 0;
                        if (currentDate.Month == 1)
                            lastMonthDays = DateTime.DaysInMonth(currentDate.Year - 1, 12);
                        else
                            lastMonthDays = DateTime.DaysInMonth(currentDate.Year, currentDate.Month - 1);
                        days = lastMonthDays - date.Day + currentDate.Day;
                    }
                    else
                    {
                        days = currentDate.Day - date.Day;
                    }
                }
                else
                {
                    months = currentDate.Month - date.Month;

                    if (currentDate.Day < date.Day)
                    {
                        months--;
                        int lastMonthDays = 0;
                        if (currentDate.Month == 1)
                            lastMonthDays = DateTime.DaysInMonth(currentDate.Year - 1, 12);
                        else
                            lastMonthDays = DateTime.DaysInMonth(currentDate.Year, currentDate.Month - 1);
                        days = lastMonthDays - date.Day + currentDate.Day;
                    }
                    else
                    {
                        days = currentDate.Day - date.Day;
                    }
                }

                //return new Age(years, months, days);


                //// แปลงเป็นอายุในรูปแบบวันที่
                //int years = (int)(age.Days / 365.25) + plusYear - subtractYear;
                //int months = (int)((age.Days % 365.25) / 30.436875);
                //int days = (int)((age.Days % 365.25) % 30.436875);

                return $"{years} ปี {months} เดือน {days} วัน";
            }
            catch
            {
                throw;
            }
        }

        public static int CalculateAge(this DateTime date, int plusYear = 0, int subtractYear = 0)
        {
            try
            {
                var currentDate = DateTime.Now;
                var age = currentDate - date;

                // แปลงเป็นอายุในรูปแบบวันที่
                int years = (int)(age.Days / 365.25) + plusYear - subtractYear;

                return years;
            }
            catch
            {
                throw;
            }
        }

        public static int CalculateGovAge(this DateTime appointDate, int plusYear = 0, int subtractYear = 0)
        {
            if (DateTime.Now.Month - appointDate.Month >= 6)
                return (DateTime.Now.Year - appointDate.Year) + 1 + plusYear - subtractYear;
            else
                return (DateTime.Now.Year - appointDate.Year) + plusYear - subtractYear;
        }


        public static string CalculateGovAgeStr(this DateTime appointDate, int plusYear = 0, int subtractYear = 0)
        {
            var d2 = DateTime.Now;
            TimeSpan sp = d2.Subtract(appointDate);
            var alldays = sp.Days + ((plusYear - subtractYear) * 365);

            int yy = alldays / 365;
            int mm = (alldays - (yy * 365)) / 30;
            int dd = (alldays - (yy * 365) - (mm * 30));

            var sb = new StringBuilder();
            sb.Clear();
            sb.Append(yy == 0 ? "" : $"{yy} ปี ");
            sb.Append(mm == 0 ? "" : $"{mm} เดือน ");
            sb.Append(dd == 0 ? "" : $"{dd} วัน ");

            return sb.ToString();
        }

        public static string CalculateGovAgeInYear(this DateTime appointDate, int plusYear = 0, int subtractYear = 0)
        {
            var d2 = DateTime.Now;
            TimeSpan sp = d2.Subtract(appointDate);
            var alldays = sp.Days + ((plusYear - subtractYear) * 365);

            int yy = alldays / 365;

            return yy.ToString();
        }

        public static int GetDifferenceInYears(this DateTime startDate, DateTime endDate)
        {
            int finalResult = 0;

            const int daysInYear = 365;

            //DateTime endDate = DateTime.Now;

            TimeSpan timeSpan = endDate - startDate;

            if (timeSpan.TotalDays > 365)
            {
                finalResult = (int)Math.Round((timeSpan.TotalDays / daysInYear), MidpointRounding.ToEven);
            }

            return finalResult;
        }

        public static DateTime CalculateRetireDate(this DateTime birthDate)
        {
            var dd = birthDate.Day;
            var mm = birthDate.Month;
            var yy = birthDate.Year;

            var g1 = true;
            switch (mm)
            {
                case 10: if (dd >= 2) g1 = false; break;
                case 11:
                case 12: g1 = false; break;
            }

            if (g1)
                return new DateTime(yy + 60, 9, 30);
            else
                return new DateTime(yy + 61, 9, 30);
        }

        public static bool IsBetween(this DateTime now, TimeSpan start, TimeSpan end)
        {
            var time = now.TimeOfDay;
            // Scenario 1: If the start time and the end time are in the same day.
            if (start <= end)
                return time >= start && time <= end;
            // Scenario 2: The start time and end time is on different days.
            return time >= start || time <= end;
        }

        public static string CalculateBetweenDate(this DateTime startDate, DateTime endDate)
        {
            // var d2 = DateTime.Now;
            TimeSpan sp = endDate.Subtract(startDate);
            var alldays = sp.Days;

            int yy = alldays / 365;
            int mm = (alldays - (yy * 365)) / 30;
            int dd = (alldays - (yy * 365) - (mm * 30));

            var sb = new StringBuilder();
            sb.Clear();
            sb.Append(yy == 0 ? "" : $"{yy} ปี ");
            sb.Append(mm == 0 ? "" : $"{mm} เดือน ");
            sb.Append(dd == 0 ? "" : $"{dd} วัน ");

            return sb.ToString();
        }

        public static string CalculateBetweenDateV2(this DateTime startDate, DateTime endDate)
        {
            if (startDate == null || endDate == null)
                return "-";

            DateTime today = endDate;
            DateTime birthDate = Convert.ToDateTime(startDate).AddDays(-1);
            int years = new DateTime(endDate.Subtract(birthDate).Ticks).Year - 1;
            DateTime pastYearDate = birthDate.AddYears(years);
            int months = 0;
            for (int i = 1; i <= 12; i++)
            {
                if (pastYearDate.AddMonths(i) == today)
                {
                    months = i;
                    break;
                }
                else if (pastYearDate.AddMonths(i) >= today)
                {
                    months = i - 1;
                    break;
                }
            }
            int days = today.Subtract(pastYearDate.AddMonths(months)).Days;
            if (today.Day < pastYearDate.Day)
            {
                if (System.DateTime.DaysInMonth(pastYearDate.Year, pastYearDate.Month) > System.DateTime.DaysInMonth(pastYearDate.AddMonths(months).Year, pastYearDate.AddMonths(months).Month))
                {
                    days += 1;
                }
                if (System.DateTime.DaysInMonth(pastYearDate.Year, pastYearDate.Month) < System.DateTime.DaysInMonth(pastYearDate.AddMonths(months).Year, pastYearDate.AddMonths(months).Month))
                {
                    days -= 1;
                }
            }
            // int Hours = Today.Subtract(PastYearDate).Hours;
            // int Minutes = Today.Subtract(PastYearDate).Minutes;
            // int Seconds = Today.Subtract(PastYearDate).Seconds;
            Console.WriteLine(today);
            Console.WriteLine(pastYearDate);
            Console.WriteLine(months);
            Console.WriteLine(pastYearDate.AddMonths(months));
            var sb = new StringBuilder();
            sb.Clear();
            sb.Append(years == 0 ? "" : $"{years} ปี ");
            sb.Append(months == 0 ? "" : $"{months} เดือน ");
            sb.Append(days == 0 ? "" : $"{days} วัน ");
            return sb.ToString();
        }
        public static CalculateBetweenDateV2ValueObj CalculateBetweenDateV2Value(this DateTime startDate, DateTime endDate)
        {
            // if (startDate == null || endDate == null)
            //     return null;
            DateTime today = endDate.AddDays(1);
            DateTime birthDate = startDate;
            int years = new DateTime(endDate.Subtract(birthDate).Ticks).Year - 1;
            DateTime pastYearDate = birthDate.AddYears(years);
            int months = 0;
            for (int i = 1; i <= 12; i++)
            {
                if (pastYearDate.AddMonths(i) == today)
                {
                    months = i;
                    break;
                }
                else if (pastYearDate.AddMonths(i) >= today)
                {
                    months = i - 1;
                    break;
                }
            }
            int days = today.Subtract(pastYearDate.AddMonths(months)).Days;
            if (today.Day < pastYearDate.Day)
            {
                if (System.DateTime.DaysInMonth(pastYearDate.Year, pastYearDate.Month) > System.DateTime.DaysInMonth(pastYearDate.AddMonths(months).Year, pastYearDate.AddMonths(months).Month))
                {
                    days += 1;
                }
                if (System.DateTime.DaysInMonth(pastYearDate.Year, pastYearDate.Month) < System.DateTime.DaysInMonth(pastYearDate.AddMonths(months).Year, pastYearDate.AddMonths(months).Month))
                {
                    days -= 1;
                }
            }
            if (days >= 30)
            {
                months = months + 1;
                days = 0;
                if (months >= 12)
                {
                    years = years + 1;
                    months = 0;
                }
            }

            var sb = new StringBuilder();
            sb.Clear();
            sb.Append(years == 0 ? "" : $"{years} ปี ");
            sb.Append(months == 0 ? "" : $"{months} เดือน ");
            sb.Append(days == 0 ? "" : $"{days} วัน ");
            return new CalculateBetweenDateV2ValueObj { years = years, months = months, days = days };
        }
        public class CalculateBetweenDateV2ValueObj
        {
            public int years { get; set; }

            public int months { get; set; }

            public int days { get; set; }
        }

        #endregion

        #endregion
    }
}