namespace Hims.Shared.DataFilters
{
    using System;
    using Library.Enums;

    /// <summary>
    /// The date time filter.
    /// </summary>
    public class DateTimeFilter
    {
        /// <summary>
        /// The to est.
        /// </summary>
        /// <param name="dateUtc">
        /// The date utc.
        /// </param>
        /// <param name="timeZone">
        /// The time Zone.
        /// </param>
        /// <returns>
        /// The <see cref="DateTime"/>.
        /// </returns>
        public static DateTime ToLocale(DateTime dateUtc, string timeZone) => TimeZoneInfo.ConvertTimeFromUtc(dateUtc, TimeZoneInfo.FindSystemTimeZoneById(timeZone));

        /// <summary>
        /// The to date.
        /// </summary>
        /// <param name="date">
        /// The date.
        /// </param>
        /// <returns>
        /// The <see cref="DateTime"/>.
        /// </returns>
        public static DateTime? ToDate(string date)
        {
            if (string.IsNullOrEmpty(date))
            {
                return null;
            }

            if (!date.Contains("-"))
            {
                return null;
            }

            var dt = date.Split('-');
            return new DateTime(Convert.ToInt32(dt[0]), Convert.ToInt32(dt[1]), Convert.ToInt32(dt[2]));
        }

        /// <summary>
        /// The to date.
        /// </summary>
        /// <param name="date">
        /// The date.
        /// </param>
        /// <returns>
        /// The <see cref="DateTime"/>.
        /// </returns>
        public static DateTime ToNotNullDate(string date)
        {
            var dt = date.Split('-');
            return new DateTime(Convert.ToInt32(dt[0]), Convert.ToInt32(dt[1]), Convert.ToInt32(dt[2]));
        }

        /// <summary>
        /// The to date.
        /// </summary>
        /// <param name="date">
        /// The date.
        /// </param>
        /// <returns>
        /// The <see cref="DateTime"/>.
        /// </returns>
        public static DateTime ToUTCDate(string date)
        {
            var dt = date.Split('-');
            return new DateTime(Convert.ToInt32(dt[0]), Convert.ToInt32(dt[1]), Convert.ToInt32(dt[2])).ToUniversalTime();
        }

        /// <summary>
        /// The to date time.
        /// </summary>
        /// <param name="dateTime">
        /// The date time.
        /// </param>
        /// <returns>
        /// The <see cref="DateTime"/>.
        /// </returns>
        public static DateTime? ToDateTime(string dateTime)
        {
            // 2019-04-10 10:50 PM
            if (string.IsNullOrEmpty(dateTime))
            {
                return null;
            }

            var dtS = dateTime.Split('-');
            var dtY = dtS[2].Split(' ');
            var dtH = dtY[1].Trim().Split(':');
            var hour = int.Parse(dtH[0]);
            if (dtY[2].ToUpper() == "PM")
            {
                hour = (hour % 12) + 12;
            }

            var convertedDateTime = new DateTime(int.Parse(dtS[0]), int.Parse(dtS[1]), int.Parse(dtY[0]), hour, int.Parse(dtH[1]), 0);
            return convertedDateTime;
        }

        /// <summary>
        /// The to date time offset.
        /// </summary>
        /// <param name="dateTime">
        /// The date time.
        /// </param>
        /// <returns>
        /// The <see cref="DateTimeOffset"/>.
        /// </returns>
        public static DateTimeOffset? ToDateTimeOffset(string dateTime)
        {
            if (string.IsNullOrEmpty(dateTime))
            {
                return null;
            }

            var dtS = dateTime.Split('-');
            var dtY = dtS[2].Split(' ');
            var dtH = dtY[1].Trim().Split(':');
            var hour = int.Parse(dtH[0]);
            if (dtY[2].ToUpper() == "PM")
            {
                hour = (hour % 12) + 12;
            }

            var convertedDateTime = new DateTimeOffset(int.Parse(dtY[0]), int.Parse(dtS[1]), int.Parse(dtS[0]), hour, int.Parse(dtH[1]), 0, TimeZoneInfo.Local.GetUtcOffset(DateTime.Now));
            return convertedDateTime;
        }

        /// <summary>
        /// The difference between two dates.
        /// </summary>
        /// <param name="startDate">
        /// The start date.
        /// </param>
        /// <param name="endDate">
        /// The end date.
        /// </param>
        /// <param name="calendarType">
        /// The calendar Type.
        /// </param>
        /// <returns>
        /// The <see cref="int"/>.
        /// </returns>
        public static int Difference(DateTime startDate, DateTime endDate, CalendarType calendarType)
        {
            switch (calendarType)
            {
                case CalendarType.Years:
                    var difference = endDate.Year - startDate.Year;
                    if (startDate > endDate.AddYears(-difference))
                    {
                        difference--;
                    }

                    return difference;
                case CalendarType.Hours:
                    var timeSpan = endDate - startDate;
                    return (int)timeSpan.TotalHours;
                default:
                    return 0;
            }
        }

        /// <summary>
        /// The difference in minutes.
        /// </summary>
        /// <param name="startTime">
        /// The start time.
        /// </param>
        /// <param name="endTime">
        /// The end time.
        /// </param>
        /// <returns>
        /// The <see cref="int"/>.
        /// </returns>
        public static int DifferenceInMinutes(TimeSpan startTime, TimeSpan endTime)
        {
            var totalHours = endTime - startTime;
            var midNight = new TimeSpan(24, 0, 0);
            if (startTime <= endTime)
            {
                return (int)totalHours.TotalMinutes;
            }

            var f1 = midNight - startTime;
            totalHours = f1 + endTime;
            return (int)totalHours.TotalMinutes;
        }
    }
}