using System;
using System.Collections.Generic;
using System.Globalization;
using Siger.Middlelayer.Common;
using Siger.Middlelayer.Common.Extensions;

namespace Siger.Middlelayer.Utility.Helpers
{
    public class DateTimeHelper
    {
        public static string GetWeekName(int week)
        {
            var weekname = "";
            switch (week)
            {
                case 0:
                    weekname = "日";
                    break;
                case 1:
                    weekname = "一";
                    break;
                case 2:
                    weekname = "二";
                    break;
                case 3:
                    weekname = "三";
                    break;
                case 4:
                    weekname = "四";
                    break;
                case 5:
                    weekname = "五";
                    break;
                case 6:
                    weekname = "六";
                    break;
                default:
                    break;
            }

            return weekname;
        }

        public static int GetInteral(int type)
        {
            var interal = 1;
            switch (type)
            {
                case 0: //天
                    interal = 1;
                    break;
                case 1: //周
                    interal = 7;
                    break;
                case 2: //月
                    interal = 30;
                    break;
                case 4: //年
                    interal = 365;
                    break;
                case 5: //季度
                    interal = 91;
                    break;
                case 999: //小时
                    interal = 91;
                    break;
                default:
                    break;
            }

            return interal;
        }

        public static DateTime GetWeekRangeStart(string week)
        {
            var weeks = week.Split('-');
            var year = weeks[0].ToInt();
            var weekIndex = weeks[1].ToInt();
            if (weekIndex < 1)
            {
                throw new Exception("请输入大于0的整数");
            }

            int allDays = (weekIndex - 1) * 7;
            //确定当年第一天
            DateTime firstDate = new DateTime(year, 1, 1);
            int firstDayOfWeek = (int)firstDate.DayOfWeek;

            firstDayOfWeek = firstDayOfWeek == 0 ? 7 : firstDayOfWeek;

            //周开始日
            int startAddDays = allDays + (1 - firstDayOfWeek);
            DateTime weekRangeStart = firstDate.AddDays(startAddDays);
            //周结束日
            int endAddDays = allDays + (7 - firstDayOfWeek);
            DateTime weekRangeEnd = firstDate.AddDays(endAddDays);

            //if (weekRangeStart.Year > year ||
            //    (weekRangeStart.Year == year && weekRangeEnd.Year > year))
            //{
            //    throw new Exception("今年没有第" + weekIndex + "周。");
            //}

            return weekRangeStart;
        }

        public static DateTime GetWeekRangeEnd(string week)
        {
            var weeks = week.Split('-');
            var year = weeks[0].ToInt();
            var weekIndex = weeks[1].ToInt();
            if (weekIndex < 1)
            {
                throw new Exception("请输入大于0的整数");
            }

            int allDays = (weekIndex - 1) * 7;
            //确定当年第一天
            DateTime firstDate = new DateTime(year, 1, 1);
            int firstDayOfWeek = (int)firstDate.DayOfWeek;

            firstDayOfWeek = firstDayOfWeek == 0 ? 7 : firstDayOfWeek;

            //周开始日
            int startAddDays = allDays + (1 - firstDayOfWeek);
            DateTime weekRangeStart = firstDate.AddDays(startAddDays);
            //周结束日
            int endAddDays = allDays + (7 - firstDayOfWeek);
            DateTime weekRangeEnd = firstDate.AddDays(endAddDays);

            return weekRangeEnd;
        }
        public static List<DateTime> GetDateTimes(DateTime dtStart, DateTime dtEnd, int type)
        {
            var listDays = new List<DateTime>();
            DateTime dtDay;
            if (type == 0 || type == 1 || type == 4 || type == 5)
            {
                for (dtDay = dtStart; dtDay.CompareTo(dtEnd) <= 0; dtDay = dtDay.AddDays(GetInteral(type)))
                {
                    listDays.Add(dtDay);
                }
            }
            else if (type == 11 || type==13)
            {

                var start = dtStart;
                while (start <= dtEnd)
                {
                    var data = dtStart.Year + "-" + GetWeekOfDay(start.AddSeconds(-1)).ToString("D2");
                    var weekStart = DateTimeHelper.GetWeekRangeStart(data);
                    var weekEnd = DateTimeHelper.GetWeekRangeEnd(data);
                    var dt = weekEnd <= dtEnd ? start.AddSeconds(-1) : dtEnd;
                    listDays.Add(dt);
                    start = weekEnd.AddDays(1);
                }
            }
            else if (type == 12)
            {

                var start = dtStart;
                while (start <= dtEnd)
                {
                   var dts = start.AddMonths(1);
                    dts = dts.AddDays(0 - dts.Day);
                    
                    var dt = dts <= dtEnd ? start : dtEnd;
                    listDays.Add(start);
                    start = dts.AddDays(1);
                }
            }
            else if (type == 2)
            {
                dtEnd = dtEnd.ToString(ParameterConstant.MouthFirstDay).ToDateTime().AddMonths(1).AddMilliseconds(-1);
                for (dtDay = dtStart; dtDay.CompareTo(dtEnd) <= 0; dtDay = dtDay.AddMonths(1))
                {
                    listDays.Add(dtDay);
                }
            }
            else if (type == 3)
            {
                for (dtDay = dtStart; dtDay.CompareTo(dtEnd) <= 0; dtDay = dtDay.AddYears(1))
                {
                    listDays.Add(dtDay);
                }
            }
            else if (type == 999)
            {
                for (dtDay = dtStart; dtDay.CompareTo(dtEnd) <= 0; dtDay = dtDay.AddHours(1))
                {
                    listDays.Add(dtDay);
                }
            }
            return listDays;
        }

        /// <summary>
        /// 长江润发
        /// </summary>
        /// <param name="dtStart">开始时间</param>
        /// <param name="dtEnd">结束时间</param>
        /// <param name="type">模块类别</param>
        /// <returns></returns>
        public static List<DateTime> GetDateTimesCJ(DateTime dtStart, DateTime dtEnd, int type)
        {
            var listDays = new List<DateTime>();
            DateTime dtDay;
            if (type == 0 || type == 4 || type == 5)
            {
                for (dtDay = dtStart; dtDay.CompareTo(dtEnd) <= 0; dtDay = dtDay.AddDays(GetInteral(type)))
                {
                    listDays.Add(dtDay);
                }
            }
            else if (type == 1)
            {
                var start = dtStart;
                while (start <= dtEnd)
                {
                    var data = dtStart.Year + "-" + GetWeekOfDay(start.AddSeconds(-1)).ToString("D2");
                    var weekStart = DateTimeHelper.GetWeekRangeStart(data);
                    var weekEnd = DateTimeHelper.GetWeekRangeEnd(data);
                    var dt = weekEnd <= dtEnd ? start.AddSeconds(-1) : dtEnd;
                    listDays.Add(dt);
                    start = weekEnd.AddDays(1);
                }
            }
            else if (type == 11)
            {

                var start = dtStart;
                while (start <= dtEnd)
                {
                    var data = dtStart.Year + "-" + GetWeekOfDay(start.AddSeconds(-1)).ToString("D2");
                    var weekStart = DateTimeHelper.GetWeekRangeStart(data);
                    var weekEnd = DateTimeHelper.GetWeekRangeEnd(data);
                    var dt = weekEnd <= dtEnd ? start.AddSeconds(-1) : dtEnd;
                    listDays.Add(dt);
                    start = weekEnd.AddDays(1);
                }
            }
            else if (type == 12)
            {

                var start = dtStart;
                while (start <= dtEnd)
                {
                    var dts = start.AddMonths(1);
                    dts = dts.AddDays(0 - dts.Day);

                    var dt = dts <= dtEnd ? start : dtEnd;
                    listDays.Add(start);
                    start = dts.AddDays(1);
                }
            }
            else if (type == 2)
            {
                dtEnd = dtEnd.ToString(ParameterConstant.MouthFirstDay).ToDateTime().AddMonths(1).AddMilliseconds(-1);
                for (dtDay = dtStart; dtDay.CompareTo(dtEnd) <= 0; dtDay = dtDay.AddMonths(1))
                {
                    listDays.Add(dtDay);
                }
            }
            else if (type == 3)
            {
                for (dtDay = dtStart; dtDay.CompareTo(dtEnd) <= 0; dtDay = dtDay.AddYears(1))
                {
                    listDays.Add(dtDay);
                }
            }
            else if (type == 999)
            {
                for (dtDay = dtStart; dtDay.CompareTo(dtEnd) <= 0; dtDay = dtDay.AddHours(1))
                {
                    listDays.Add(dtDay);
                }
            }
            return listDays;
        }
        public static List<string> GetStrDateTimes(DateTime dtStart, DateTime dtEnd, int type)
        {
            var result = new List<string>();
            var list = GetDateTimes(dtStart, dtEnd, type);
            if (type == 0)
            {
                foreach (var dateTime in list)
                {
                    result.Add(dateTime.ToString(DateFormatHelper.DateFormat));
                }
            }


            if (type == 1)
            {
                foreach (var dateTime in list)
                {
                    result.Add(dateTime.Year + "-" + GetWeekOfDay(dateTime).ToString("D2"));
                }
            }

            if (type == 2)
            {
                foreach (var dateTime in list)
                {
                    result.Add(dateTime.Year + "-" + dateTime.Month.ToString("D2"));
                }
            }

            if (type == 3)
            {
                foreach (var dateTime in list)
                {
                    result.Add(dateTime.Year.ToString());
                }
            }
            if (type == 11)
            {
                foreach (var dateTime in list)
                {
                    result.Add(dateTime.Year + "-" + GetWeekOfDay(dateTime).ToString("D2"));
                }
            }

            if (type == 12)
            {
                foreach (var dateTime in list)
                {
                    result.Add(dateTime.Year + "-" + dateTime.Month.ToString("D2"));
                }
            }
            if (type == 13)
            {
                foreach (var dateTime in list)
                {
                    result.Add(GetWeekOfDay(dateTime).ToString("D2"));
                }
            }
            return result;
        }

        public static List<string> GetStrDateTimesCJ(DateTime dtStart, DateTime dtEnd, int type)
        {
            var result = new List<string>();
            var list = GetDateTimesCJ(dtStart, dtEnd, type);
            if (type == 0)
            {
                foreach (var dateTime in list)
                {
                    result.Add(dateTime.ToString(DateFormatHelper.DateFormat));
                }
            }


            if (type == 1)
            {
                foreach (var dateTime in list)
                {
                    result.Add(dateTime.Year + "-" + GetWeekOfDay(dateTime).ToString("D2"));
                }
            }

            if (type == 2)
            {
                foreach (var dateTime in list)
                {
                    result.Add(dateTime.Year + "-" + dateTime.Month.ToString("D2"));
                }
            }

            if (type == 3)
            {
                foreach (var dateTime in list)
                {
                    result.Add(dateTime.Year.ToString());
                }
            }
            if (type == 11)
            {
                foreach (var dateTime in list)
                {
                    result.Add(dateTime.Year + "-" + GetWeekOfDay(dateTime).ToString("D2"));
                }
            }

            if (type == 12)
            {
                foreach (var dateTime in list)
                {
                    result.Add(dateTime.Year + "-" + dateTime.Month.ToString("D2"));
                }
            }
            return result;
        }

        public static int GetWeekOfDay(DateTime dt)
        {
            var firstWeekend = 7 - Convert.ToInt32(DateTime.Parse(dt.Year + "-1-1").DayOfWeek);
            var currentDay = dt.DayOfYear;
            return Convert.ToInt32(Math.Ceiling((currentDay - firstWeekend) / 7.0)) + 1;
        }

        public static DateTime GetLastSunday(DateTime time)
        {
            if (time.DayOfWeek == DayOfWeek.Sunday)
            {
                time = time.AddDays(-7);
            }
            while (time.DayOfWeek != DayOfWeek.Sunday)
            {
                time = time.AddDays(-1);
            }
            return time;
        }

        /// <summary>
        /// 日期时间 转日期
        /// </summary>
        /// <param name="datetime"></param>
        /// <returns></returns>
        public static DateTime GetDate(DateTime datetime)
        {
            var busidateStr = datetime.ToString(DateFormatHelper.DateFormat);
            DateTime.TryParse(busidateStr, out DateTime busidate);
            return busidate;
        }
        /// <summary>
        /// 当前月第一天
        /// </summary>
        /// <param name="datetime"></param>
        /// <returns></returns>
        public static DateTime FirstDayMoth(DateTime datetime)
        {
            int span = Convert.ToInt32(datetime.Day);
            span = span - 1;
            System.DateTime dateStart = datetime.AddDays(-span);
            return dateStart;
            // return datetime.AddDays(1 - DateTime.Now.Day).Date;
        }
        /// <summary>
        /// 当前月最后一天
        /// </summary>
        /// <param name="datetime"></param>
        /// <returns></returns>
        public static DateTime LastDayMonth(DateTime datetime)
        {
            int span = Convert.ToInt32(datetime.Day);
            System.DateTime dateEnd = datetime.AddMonths(1).AddDays(-span);
            return dateEnd;

           // return datetime.AddDays(1 - DateTime.Now.Day).Date.AddMonths(1).AddSeconds(-1);
        }
        /// <summary>
        /// 取当天开始日期
        /// </summary>
        /// <returns></returns>
        public static DateTime GetTodayStartTime()
        {
            var year = DateTime.Now.Year;
            var month = DateTime.Now.Month;
            var day = DateTime.Now.Day;
            return new DateTime(year, month, day, 0, 0, 0);
        }
        public static DateTime GetTodayStartTime(DateTime dt)
        {
            var year = dt.Year;
            var month = dt.Month;
            var day = dt.Day;
            return new DateTime(year, month, day, 0, 0, 0);
        }
        public static int GetWeekOfYear(DateTime dt)
        {
            GregorianCalendar gc = new GregorianCalendar();
            int weekOfYear = gc.GetWeekOfYear(dt, CalendarWeekRule.FirstDay, DayOfWeek.Monday);
            return weekOfYear;
        }
        public static int GetQuarterByMonth(int month)
        {
            if (month < 1 || month > 12)
            {
                return 0;
            }
            return (month - 1) / 3 + 1;
        }

        /// <summary>
        /// 获取前一个班次，从8点到第二天8点
        /// </summary>
        /// <param name="date"></param>
        /// <returns></returns>
        public static DateTimeRange GetDateTimeRange(string date)
        {
            var currentTime = string.IsNullOrWhiteSpace(date) ? DateTime.Now : date.ToDateTime();
            var start = DateTime.Parse(currentTime.ToString(ParameterConstant.DateFormat) + " 8:00:00");
            var sub = DateTime.Now.Subtract(currentTime).Days;
            if (sub >= 2)
            {
                return new DateTimeRange(start, start.AddDays(1).AddMilliseconds(-1));
            }

            if (sub == 1)
            {
                if (DateTime.Now.Hour >= 8)
                {
                    return new DateTimeRange(start, start.AddDays(1).AddMilliseconds(-1));
                }
                return new DateTimeRange(start, DateTime.Now);
            }
            if (DateTime.Now.Hour >= 8)
            {
                return new DateTimeRange(start, DateTime.Now);
            }
            //return new DateTimeRange(DateTime.Parse(currentTime.Date.AddDays(-1) + " 8:00:00"), DateTime.Now);
            return new DateTimeRange(currentTime.Date.AddDays(-1).AddHours(8), DateTime.Now);
        }

        /// <summary>
        /// 获取开始时间
        /// </summary>
        /// <param name="TimeType"></param>
        /// <param name="dt"></param>
        /// <returns></returns>
        public static DateTime GetTimeStartByType(int TimeType, DateTime dt)
        {
            switch (TimeType)
            {
                case 1://周
                    if ((int)dt.DayOfWeek == 0)
                    {
                        return dt.AddDays(-6);
                    }
                    return dt.AddDays(-(int)dt.DayOfWeek + 1);
                case 2://月
                    return dt.AddDays(-dt.Day + 1);
                case 5://季度
                    var time = dt.AddMonths(0 - ((dt.Month - 1) % 3));
                    return time.AddDays(-time.Day + 1);
                case 4://年
                    return dt.AddDays(-dt.DayOfYear + 1);
                default:
                    return dt;
            }
        }

        /// <summary>
        /// 获取结束时间
        /// </summary>
        /// <param name="TimeType"></param>
        /// <param name="now"></param>
        /// <returns></returns>
        public static DateTime GetTimeEndByType(int TimeType, DateTime dt)
        {
            switch (TimeType)
            {
                case 1:
                    var week = (int)dt.DayOfWeek;
                    if (week == 0)
                    {
                        return dt;
                    }
                    return dt.AddDays(7 - (int)dt.DayOfWeek);
                case 2:
                    return dt.AddMonths(1).AddDays(-dt.AddMonths(1).Day + 1).AddDays(-1);
                case 5:
                    var time = dt.AddMonths((3 - ((dt.Month - 1) % 3) - 1));
                    return time.AddMonths(1).AddDays(-time.AddMonths(1).Day + 1).AddDays(-1);
                case 4:
                    var time2 = dt.AddYears(1);
                    return time2.AddDays(-time2.DayOfYear);
                default:
                    return dt;
            }
        }

        public static string GetTimeStrByType(int TimeType, DateTime dt)
        {
            string timeStr;
            switch (TimeType)
            {
                case 0: //天
                    timeStr = dt.ToString(ParameterConstant.DateFormat);
                    break;
                case 1: //周
                    timeStr = $"W{GetWeekOfYear(dt)}";
                    break;
                case 2: //月
                    timeStr = dt.ToString(ParameterConstant.YearMonthFormat);
                    break;
                case 4: //年
                    timeStr = dt.Year.ToString();
                    break;
                case 5: //季度
                    var mouth = dt.Month;
                    if (mouth <= 3 && mouth >= 1)
                    {
                        timeStr = "Q1";
                    }
                    else if (mouth <= 6 && mouth >= 4)
                    {
                        timeStr = "Q2";
                    }
                    else if (mouth <= 9 && mouth >= 7)
                    {
                        timeStr = "Q3";
                    }
                    else if (mouth <= 12 && mouth >= 10)
                    {
                        timeStr = "Q4";
                    }
                    else
                    {
                        timeStr = dt.ToString(ParameterConstant.YearMonthFormat);
                    }
                    break;
                default:
                    timeStr = dt.ToString(ParameterConstant.DateFormat);
                    break;
            }
            return timeStr;
        }
    }

    public class DateTimeRange
    {
        public DateTime StarTime { get; set; }

        public DateTime EndTime { get; set; }

        public DateTimeRange(DateTime starTime, DateTime endTime)
        {
            StarTime = starTime;
            EndTime = endTime;
        }
    }
}
