using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Text;
using Newtonsoft.Json;
using FCOMMON;

namespace Project.Web
{
    public partial class MachineBridge
    {
        #region Kuntae API

        #region 오류검사 관련 클래스
        public class KuntaeErrorCheckResult
        {
            public string Date { get; set; }
            public string Gubun { get; set; }
            public string OccurDay { get; set; }
            public string OccurTime { get; set; }
            public string UseDay { get; set; }
            public string UseTime { get; set; }
            public string CateError { get; set; }
            public bool IsError { get; set; }
            public bool IsMagam { get; set; }
        }

        public class KuntaeErrorCheckProgress
        {
            public string CurrentDate { get; set; }
            public double JobreportOT { get; set; }
            public double HolidayRequestDay { get; set; }
            public double HolidayRequestTime { get; set; }
            public double KuntaeCRDay { get; set; }
            public double KuntaeCRTime { get; set; }
            public double KuntaeDRDay { get; set; }
            public double KuntaeDRTime { get; set; }
        }
        #endregion

        /// <summary>
        /// 근태 목록 조회
        /// </summary>
        public string Kuntae_GetList(string sd, string ed)
        {
            try
            {
                var sql = @"SELECT k.*, u.name as userName
                           FROM EETGW_Kuntae k WITH (nolock)
                           LEFT JOIN Users u ON k.uid = u.id
                           WHERE k.gcode = @gcode AND k.uid = @uid";

                var parameters = new List<SqlParameter>();
                parameters.Add(new SqlParameter("@gcode", info.Login.gcode));
                parameters.Add(new SqlParameter("@uid", info.Login.no));

                if (!string.IsNullOrEmpty(sd))
                {
                    sql += " AND k.kdate >= @sd";
                    parameters.Add(new SqlParameter("@sd", sd));
                }
                if (!string.IsNullOrEmpty(ed))
                {
                    sql += " AND k.kdate <= @ed";
                    parameters.Add(new SqlParameter("@ed", ed));
                }

                sql += " ORDER BY k.kdate DESC";

                var cs = Properties.Settings.Default.gwcs;
                var cn = new SqlConnection(cs);
                var cmd = new SqlCommand(sql, cn);
                cmd.Parameters.AddRange(parameters.ToArray());

                var da = new SqlDataAdapter(cmd);
                var dt = new DataTable();
                da.Fill(dt);
                da.Dispose();
                cmd.Dispose();
                cn.Dispose();

                return JsonConvert.SerializeObject(new { Success = true, Data = dt }, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
            }
            catch (Exception ex)
            {
                return JsonConvert.SerializeObject(new { Success = false, Message = ex.Message });
            }
        }

        /// <summary>
        /// 근태 삭제
        /// </summary>
        public string Kuntae_Delete(int id)
        {
            try
            {
                var sql = "DELETE FROM EETGW_Kuntae WHERE idx = @idx AND gcode = @gcode AND uid = @uid";

                var cs = Properties.Settings.Default.gwcs;
                var cn = new SqlConnection(cs);
                var cmd = new SqlCommand(sql, cn);
                cmd.Parameters.AddWithValue("@idx", id);
                cmd.Parameters.AddWithValue("@gcode", info.Login.gcode);
                cmd.Parameters.AddWithValue("@uid", info.Login.no);

                cn.Open();
                var result = cmd.ExecuteNonQuery();
                cn.Close();
                cmd.Dispose();
                cn.Dispose();

                return JsonConvert.SerializeObject(new { Success = result > 0, Message = result > 0 ? "삭제되었습니다." : "삭제에 실패했습니다." });
            }
            catch (Exception ex)
            {
                return JsonConvert.SerializeObject(new { Success = false, Message = ex.Message });
            }
        }

        /// <summary>
        /// 근태 오류 검사 실행
        /// </summary>
        public string Kuntae_ErrorCheck(string sd, string ed)
        {
            try
            {
                var startDate = DateTime.Parse(sd);
                var endDate = DateTime.Parse(ed);
                var gcode = info.Login.gcode;
                var uid = info.Login.no;

                var okList = new List<KuntaeErrorCheckResult>();
                var ngList = new List<KuntaeErrorCheckResult>();

                var cs = Properties.Settings.Default.gwcs;
                using (var cn = new SqlConnection(cs))
                {
                    cn.Open();
                    using (var cmd = new SqlCommand("", cn))
                    {
                        cmd.Parameters.Add("@gcode", SqlDbType.VarChar).Value = gcode;
                        cmd.Parameters.Add("@uid", SqlDbType.VarChar).Value = uid;

                        var idx = 0;
                        while (true)
                        {
                            var currentDate = startDate.AddDays(idx++);
                            if (currentDate > endDate) break;

                            var pdate = currentDate.ToString("yyyy-MM-dd");
                            var result = CheckDateError(cmd, pdate, gcode);

                            if (result.IsError)
                                ngList.Add(result);
                            else
                                okList.Add(result);
                        }
                    }
                }

                return JsonConvert.SerializeObject(new {
                    Success = true,
                    OkList = okList,
                    NgList = ngList
                });
            }
            catch (Exception ex)
            {
                return JsonConvert.SerializeObject(new { Success = false, Message = ex.Message });
            }
        }

        /// <summary>
        /// 특정 날짜의 오류 검사
        /// </summary>
        private KuntaeErrorCheckResult CheckDateError(SqlCommand cmd, string pdate, string gcode)
        {
            var result = new KuntaeErrorCheckResult
            {
                Date = pdate,
                Gubun = "입력/생성",
                IsError = false,
                IsMagam = false
            };

            // 1. 업무일지 OT2 합계 (발생시간)
            cmd.CommandText = $"SELECT SUM(ISNULL(ot2,0)) FROM jobreport WHERE gcode = @gcode AND pdate='{pdate}' AND ISNULL(ot,0) > 0 AND ISNULL(ot2,0) > 0";
            var jobreportOT = 0.0;
            var objJobreport = cmd.ExecuteScalar();
            if (objJobreport != null && objJobreport != DBNull.Value)
                jobreportOT = Convert.ToDouble(objJobreport);

            // 2. 휴가신청 확인 (승인된 것만)
            cmd.CommandText = $"SELECT cate, SUM(HolyDays), SUM(HolyTimes) FROM EETGW_HolydayRequest WHERE gcode = @gcode AND sdate = '{pdate}' AND ISNULL(conf,0) = 1 GROUP BY cate";
            var holidayDay = 0.0;
            var holidayTime = 0.0;
            var cateListD = new Dictionary<string, double>();
            var cateListT = new Dictionary<string, double>();

            using (var reader = cmd.ExecuteReader())
            {
                while (reader.Read())
                {
                    var cate = reader[0].ToString();
                    var vDay = reader[1] != DBNull.Value ? Convert.ToDouble(reader[1]) : 0.0;
                    var vTime = reader[2] != DBNull.Value ? Convert.ToDouble(reader[2]) : 0.0;

                    holidayDay += vDay;
                    holidayTime += vTime;

                    if (vDay != 0.0)
                    {
                        if (cateListD.ContainsKey(cate))
                            cateListD[cate] += vDay;
                        else
                            cateListD.Add(cate, vDay);
                    }

                    if (vTime != 0.0)
                    {
                        if (cateListT.ContainsKey(cate))
                            cateListT[cate] += vTime;
                        else
                            cateListT.Add(cate, vTime);
                    }
                }
            }

            // 3. 근태입력자료 확인
            cmd.CommandText = $@"SELECT cate, SUM(term), SUM(crtime), SUM(termdr), SUM(drtime), SUM(drtimepms)
                                FROM Holyday
                                WHERE gcode = @gcode AND sdate = '{pdate}' AND ISNULL(extidx,-1) <> -1
                                GROUP BY cate";

            var kuntaeCRDay = 0.0;
            var kuntaeCRTime = 0.0;
            var kuntaeDRDay = 0.0;
            var kuntaeDRTime = 0.0;
            var dCRD = new Dictionary<string, double>();
            var dCRT = new Dictionary<string, double>();
            var dDRD = new Dictionary<string, double>();
            var dDRT = new Dictionary<string, double>();

            using (var reader = cmd.ExecuteReader())
            {
                while (reader.Read())
                {
                    var cate = reader[0].ToString();
                    var vCRD = reader[1] != DBNull.Value ? Convert.ToDouble(reader[1]) : 0.0;
                    var vCRT = reader[2] != DBNull.Value ? Convert.ToDouble(reader[2]) : 0.0;
                    var vDRD = reader[3] != DBNull.Value ? Convert.ToDouble(reader[3]) : 0.0;
                    var vDRT = reader[4] != DBNull.Value ? Convert.ToDouble(reader[4]) : 0.0;

                    if (vCRD != 0.0)
                    {
                        if (dCRD.ContainsKey(cate)) dCRD[cate] += vCRD;
                        else dCRD.Add(cate, vCRD);
                    }
                    if (vCRT != 0.0)
                    {
                        if (dCRT.ContainsKey(cate)) dCRT[cate] += vCRT;
                        else dCRT.Add(cate, vCRT);
                    }
                    if (vDRD != 0.0)
                    {
                        if (dDRD.ContainsKey(cate)) dDRD[cate] += vDRD;
                        else dDRD.Add(cate, vDRD);
                    }
                    if (vDRT != 0.0)
                    {
                        if (dDRT.ContainsKey(cate)) dDRT[cate] += vDRT;
                        else dDRT.Add(cate, vDRT);
                    }

                    kuntaeCRDay += vCRD;
                    kuntaeCRTime += vCRT;
                    kuntaeDRDay += vDRD;
                    kuntaeDRTime += vDRT;
                }
            }

            // 4. 카테고리별 데이터 확인
            var sbCate = new StringBuilder();
            var cateErr = false;

            // 휴가신청(일) vs 근태입력(CR일)
            foreach (var item in cateListD)
            {
                if (!dCRD.ContainsKey(item.Key))
                {
                    sbCate.Append($"{item.Key}(X)");
                    cateErr = true;
                    break;
                }
                else if (dCRD[item.Key] != item.Value)
                {
                    sbCate.Append($"{item.Key}({dCRD[item.Key]}|{item.Value})");
                    cateErr = true;
                    break;
                }
            }

            if (!cateErr)
            {
                foreach (var item in cateListT)
                {
                    if (!dCRT.ContainsKey(item.Key))
                    {
                        sbCate.Append($"{item.Key}(X)");
                        cateErr = true;
                        break;
                    }
                    else if (dCRT[item.Key] != item.Value)
                    {
                        sbCate.Append($"{item.Key}({dCRT[item.Key]}|{item.Value})");
                        cateErr = true;
                        break;
                    }
                }
            }

            if (!cateErr)
            {
                foreach (var item in dCRD)
                {
                    if (item.Key.Equals("대체")) continue;
                    if (!cateListD.ContainsKey(item.Key))
                    {
                        sbCate.Append($"{item.Key}(X)");
                        cateErr = true;
                        break;
                    }
                    else if (cateListD[item.Key] != item.Value)
                    {
                        sbCate.Append($"{item.Key}({cateListD[item.Key]}|{item.Value})");
                        cateErr = true;
                        break;
                    }
                }
            }

            if (!cateErr)
            {
                foreach (var item in dCRT)
                {
                    if (item.Key.Equals("대체")) continue;
                    if (!cateListT.ContainsKey(item.Key))
                    {
                        sbCate.Append($"{item.Key}(X)");
                        cateErr = true;
                        break;
                    }
                    else if (cateListT[item.Key] != item.Value)
                    {
                        sbCate.Append($"{item.Key}({cateListT[item.Key]}|{item.Value})");
                        cateErr = true;
                        break;
                    }
                }
            }

            // 5. 결과 생성
            result.OccurDay = $"--/{kuntaeDRDay}";
            result.OccurTime = $"{jobreportOT}/{kuntaeDRTime}";
            result.UseDay = $"{holidayDay}/{kuntaeCRDay}";
            result.UseTime = $"{holidayTime}/{kuntaeCRTime}";
            result.CateError = sbCate.ToString();

            // 오류 여부 판단
            if (jobreportOT != kuntaeDRTime) result.IsError = true;
            if (holidayDay != kuntaeCRDay) result.IsError = true;
            if (holidayTime != kuntaeCRTime) result.IsError = true;
            if (cateErr) result.IsError = true;

            // 마감 여부 확인
            if (result.IsError)
            {
                result.IsMagam = DBM.GetMagamStatus(pdate.Substring(0, 7));
            }

            return result;
        }

        /// <summary>
        /// 근태 오류 수정 (재생성)
        /// </summary>
        public string Kuntae_FixError(string pdate)
        {
            try
            {
                var gcode = info.Login.gcode;
                var uid = info.Login.no;

                var cs = Properties.Settings.Default.gwcs;
                using (var cn = new SqlConnection(cs))
                {
                    cn.Open();
                    using (var cmd = new SqlCommand("", cn))
                    {
                        cmd.Parameters.Add("@gcode", SqlDbType.VarChar).Value = gcode;
                        cmd.Parameters.Add("@uid", SqlDbType.VarChar).Value = uid;
                        cmd.Parameters.Add("@pdate", SqlDbType.VarChar).Value = pdate;

                        // 1. 근태-업무일지자료 삭제
                        cmd.CommandText = "DELETE FROM Holyday WHERE gcode = @gcode AND extcate = 'HO' AND sdate = @pdate AND ISNULL(extidx,-1) <> -1";
                        var cnt1 = cmd.ExecuteNonQuery();

                        // 2. 근태-업무일지자료 생성
                        cmd.CommandText = @"INSERT INTO Holyday(gcode, cate, sdate, edate, term, crtime, termdr, DrTime, contents, [uid], wdate, wuid, extcate, extidx)
                                           SELECT gcode, '대체', pdate, pdate, 0, 0, 0, ISNULL(ot2,0), projectname, uid, GETDATE(), @uid + '-ERR', 'HO', idx
                                           FROM jobreport
                                           WHERE gcode = @gcode AND pdate = @pdate AND ISNULL(ot2,0) > 0 AND ISNULL(ot,0) > 0";
                        var cnt2 = cmd.ExecuteNonQuery();

                        // 3. 근태-휴가신청자료 삭제
                        cmd.CommandText = "DELETE FROM Holyday WHERE gcode = @gcode AND extcate = '휴가' AND sdate = @pdate AND ISNULL(extidx,-1) <> -1";
                        var cnt3 = cmd.ExecuteNonQuery();

                        // 4. 근태-휴가신청자료 생성 (승인완료된 자료 대상)
                        cmd.CommandText = @"INSERT INTO Holyday(gcode, cate, sdate, edate, term, crtime, termdr, DrTime, contents, [uid], wdate, wuid, extcate, extidx)
                                           SELECT gcode, cate, sdate, edate, ISNULL(holydays,0), ISNULL(holytimes,0), 0, 0, HolyReason, uid, GETDATE(), @uid + '-ERR', '휴가', idx
                                           FROM EETGW_HolydayRequest
                                           WHERE gcode = @gcode AND sdate = @pdate AND ISNULL(conf,0) = 1";
                        var cnt4 = cmd.ExecuteNonQuery();

                        return JsonConvert.SerializeObject(new {
                            Success = true,
                            Message = $"{pdate} 재생성 완료 (삭제: {cnt1 + cnt3}건, 생성: {cnt2 + cnt4}건)"
                        });
                    }
                }
            }
            catch (Exception ex)
            {
                return JsonConvert.SerializeObject(new { Success = false, Message = ex.Message });
            }
        }

        /// <summary>
        /// 여러 날짜 오류 일괄 수정
        /// </summary>
        public string Kuntae_FixErrors(string dates)
        {
            try
            {
                var dateList = JsonConvert.DeserializeObject<List<string>>(dates);
                var results = new List<object>();

                foreach (var date in dateList)
                {
                    var resultJson = Kuntae_FixError(date);
                    var resultObj = JsonConvert.DeserializeObject<dynamic>(resultJson);
                    results.Add(new { Date = date, Success = (bool)resultObj.Success, Message = (string)resultObj.Message });
                }

                return JsonConvert.SerializeObject(new { Success = true, Results = results });
            }
            catch (Exception ex)
            {
                return JsonConvert.SerializeObject(new { Success = false, Message = ex.Message });
            }
        }

        #endregion
    }
}
