using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SystemX.Product.ALIS.Interface;
using SystemX.Product.CP.TRA;
using SystemX.Product.TRA.UIControl;

using static SystemX.Product.TRA.DataManager.DMOverview;
using static SystemX.Product.CP.TRA.Commons;
using SystemX.Net.Platform.SystemX.Net.XEFCore;

using CPXV2Log = SystemX.Net.Platform.SystemX.Net.XEFCore.DBContext.CPXV2Log;
using CPXV2LogJson = SystemX.Net.Platform.SystemX.Net.XEFCore.DBContext.CPXV2LogJson;
using Newtonsoft.Json;
using DataBaseConnection.Control;
using SystemX.Common.Util;

namespace SystemX.Product.TRA.DataManager
{
    public class DMTestDetail
    {
        public enum eColHideListLog
        {
            No,
            AccessKey,
            //TestID
        }

        public enum eColTestLog
        {
            No,
            StepID,
            MeasVal,
            MeasValStr,
            Message,
            GlobalMin,
            GlobalMax,
            Result,
            SpentTime,
            DataDT
        }

        public enum eColHideListTL
        {
            No,
            TestListNo,
            StepVersion,
            Enable,
            IsGlobal,
            UpdateDT
        }

        public enum eColTestlist
        {
            No,
            TestListNo,
            StepID,
            Variant,
            Gate,
            Activate,
            StepVersion,
            Enable,
            Position,
            StepDesc,
            UseFunction,
            SpecMin,
            SpecMax,
            Dim,
            IsGlobal,
            UpdateDT
        }

        private SqlConnection DBConn { get; set; }
        private SqlConnection ShortTermDBConn { get; set; }
        public SqlConnection LongTermDBConn { get; private set; }

        private SqlCommand SQLCmd { get; set; }

        private IDataBaseController DBControllers { get; set; }

        public eSelectDataView NgHistorySelectView { get; set; }

        public DMTestDetail(eSelectDataView SelectView, IDataBaseController getDBController, DateTime dtStart)
        {
            DBControllers = getDBController;
            DBConn = getDBController.GetMainConn();

            if (SelectView == eSelectDataView.DataDocumentViewC1)
            {
                NgHistorySelectView = eSelectDataView.DataDocumentViewC1;
                ShortTermDBConn = getDBController.GetShortTermConn1();

                LongTermDBConn = getDBController.GetLongTermConn1().Where(x=>x.Key.Contains(dtStart.Year.ToString())).First().Value;
            }
            else if (SelectView == eSelectDataView.DataDocumentViewC2)
            {
                NgHistorySelectView = eSelectDataView.DataDocumentViewC2;
                ShortTermDBConn = getDBController.GetShortTermConn2();

                LongTermDBConn = getDBController.GetLongTermConn2().Where(x => x.Key.Contains(dtStart.Year.ToString())).First().Value;
            }
        }

        public DataTable SearchTestlist(DetailTestDataCollection data)
        {
            DataTable dtResult = new DataTable();           
            string strQuery = string.Empty;

            if (data == null)
                return dtResult;

            /*
            --최신 목록 스텝 Index Seek 특정 버전 이하 만 찾기
		    SELECT * FROM (SELECT *, ROW_NUMBER() OVER(PARTITION BY StepID ORDER BY StepVersion DESC) 
            AS RN FROM VRFY_Release WITH (INDEX=[CSK_VRFY_Release_1], NOLOCK) WHERE TestlistNo = 28 AND StepVersion <= 18) AS X
		    WHERE X.RN = 1 ORDER BY X.StepID ASC; 

		    --최신 목록 스텝 Index Seek
		    SELECT * FROM (SELECT *, ROW_NUMBER() OVER(PARTITION BY StepID ORDER BY StepVersion DESC) 
            AS RN FROM VRFY_Release WITH (INDEX=[CSK_VRFY_Release_1], NOLOCK) WHERE TestlistNo = 4) AS X
		    WHERE X.RN = 1 ORDER BY X.StepID ASC; 
            */

            /*
            strQuery += $"SELECT * FROM(SELECT *, ROW_NUMBER() OVER(PARTITION BY StepID ORDER BY StepVersion DESC) " +
            $"AS RN FROM VRFY_Release WITH(INDEX =[CSK_VRFY_Release_1], NOLOCK) WHERE TestlistNo = {data.TestlistNo}) AS X " +
            $"WHERE X.RN = 1 ORDER BY X.StepID ASC;";
            */

            strQuery = $"SELECT A.ProdNo_C, B.ProdNo_P, B.UpdateDT, D.TestCode, D.Gate1, D.Gate2, E.FileName, A.RegUserComment, B.Description, C.GroupName, C.ModelName, A.VariantNo AS 'TestListNo', A.Config, E.TestType, E.Version, E.ProdCode, B.UseTLPosition, B.TestListFileNo, E.UpdateDT AS 'TestListFileUpdateDT', A.VariantNo FROM [PROD_Release] AS A WITH(NOLOCK) " +
                $"INNER JOIN(SELECT * FROM [PROD_Variant] WITH(NOLOCK)) AS B ON A.VariantNo = B.No " +
                $"INNER JOIN(SELECT * FROM [PROD_Group] WITH(NOLOCK)) AS C ON B.GroupNo = C.No " +
                $"INNER JOIN(SELECT * FROM [STAT_TestCode] WITH(NOLOCK)) AS D ON A.TestCodeNo = D.No " +
                $"INNER JOIN(SELECT * FROM [STOR_TestListFile] WITH(NOLOCK)) AS E ON B.TestListFileNo = E.No " +
                $"WHERE A.ProdNo_C = '{data.ProductNo}' AND D.TestCode = '{data.TestCode}' AND E.TestType = '{data.TestType}' AND E.Version = '{data.FileVersion}' AND E.ProdCode = '{data.FileCode}';";

            SQLCmd = new SqlCommand(strQuery, DBConn);
            SQLCmd.CommandTimeout = DMCommon.nDefaultScanTime;

            DbDataReader dtCompReader = SQLCmd.ExecuteReader();
            DataTable dtCompResult = new DataTable();

            dtCompResult.Load(dtCompReader);

            if (Commons.isHasRow(dtCompResult) == false)
                return dtResult;

            string strCompVariNo = dtCompResult.Rows[0]["VariantNo"].ToString();
            string strCompFileNo = dtCompResult.Rows[0]["TestListFileNo"].ToString();

            dtCompReader.Close();

            string strGetTestListFileNo = string.Empty;

            if (strCompVariNo.CompareTo(data.TestListVariantNo) == 0 &&
            strCompFileNo.CompareTo(data.TestListFileNo) == 0)
                strGetTestListFileNo = data.TestListFileNo;
            else
                strGetTestListFileNo = strCompFileNo;

            strQuery = $"SELECT * FROM ( " +
                    $"SELECT *, ROW_NUMBER() OVER(PARTITION BY StepID ORDER BY StepVersion DESC) " +
                    $"AS RN FROM VRFY_TestListFileRelease WITH (NOLOCK, INDEX=[CSK_VRFY_Release_2]) WHERE TestListFileNo = {strGetTestListFileNo} " +
                    $"AND StepVersion <= {data.StepVersion}) X WHERE RN = 1 ORDER BY X.StepID ASC;";

            /*strQuery += $"SELECT ";           
            strQuery += $"*";
            strQuery += " ";
            strQuery += $"from [VRFY_Release] ";
            strQuery += $"WITH(NOLOCK) ";
            strQuery += $"where [TestListNo] = {data.TestlistNo}";        
            strQuery += " ";
            strQuery += $"order by ";
            strQuery += $"[StepID]";
            strQuery += ";";*/

            SQLCmd = new SqlCommand(strQuery, DBConn);
            SQLCmd.CommandTimeout = DMCommon.nDefaultScanTime;

            DbDataReader dtReader = SQLCmd.ExecuteReader();

            dtResult.Load(dtReader);

            dtReader.Close();

            //PK 키 지정
            DataColumn[] keys1 = new DataColumn[1];
            keys1[0] = new DataColumn();
            keys1[0] = dtResult.Columns["StepID"];

            dtResult.PrimaryKey = keys1;

            //StepID 마다 가장 높은 버전 찾기
            //SQL 수정으로 사용 X
            //dtResult = RefineStepVersion(dtResult, data);

            return dtResult;
        }

        public DataTable RefineStepVersion(DataTable dtTestlist, DetailTestDataCollection data)
        {            
            var DuplicatedSteps = dtTestlist.AsEnumerable().GroupBy(x => x[eColTestlist.StepID.ToString()]).
                Select(x => new { StepID = x.Key, Count = x.Count() }).Where(x => x.Count > 1);
            
            foreach(var value in DuplicatedSteps)
            {
                List<DataRow> vdtRow = dtTestlist.AsEnumerable().Where(x => x[eColTestlist.StepID.ToString()].ToString() == value.StepID.ToString()).ToList();
                DataRow vExcRow = vdtRow.Where(x => x[eColTestlist.StepVersion.ToString()].ToString() == data.StepVersion).FirstOrDefault();

                if(vExcRow == null)
                {
                    int nMaxVer = vdtRow.Max(x => Convert.ToInt32(x[eColTestlist.StepVersion.ToString()]));

                    vExcRow = vdtRow.Where(x => Convert.ToInt32(x[eColTestlist.StepVersion.ToString()]) == nMaxVer).FirstOrDefault();
                }

                vdtRow.Remove(vExcRow);
                                
                foreach (DataRow dtRow in vdtRow)
                    dtTestlist.Rows.Remove(dtRow);
            }

            return dtTestlist;
        }

        public DataTable SearchTestHistory(DetailTestDataCollection data)
        {
            if (NgHistorySelectView == eSelectDataView.DataDocumentViewC1)
            {
                ShortTermDBConn = DBControllers.GetShortTermConn1();

                LongTermDBConn = DBControllers.GetLongTermConn1().Where(x => x.Key.Contains(data.StartTime.Year.ToString())).First().Value;
            }
            else if (NgHistorySelectView == eSelectDataView.DataDocumentViewC2)
            {
                ShortTermDBConn = DBControllers.GetShortTermConn2();

                LongTermDBConn = DBControllers.GetLongTermConn2().Where(x => x.Key.Contains(data.StartTime.Year.ToString())).First().Value;
            }

            DataTable dtResult = new DataTable();
            List<CPXV2Log.Tables.HIST_TestResult> list = new List<CPXV2Log.Tables.HIST_TestResult>();
            StringBuilder strQuery = new StringBuilder();                      

            if (data == null)
                return dtResult;
         
            strQuery.Append($"SELECT ");
            strQuery.Append($"*");
            strQuery.Append(" ");
            strQuery.Append($"FROM {DMCommon.ResultLogTable} ");
            strQuery.Append($"WITH(NOLOCK) ");
            strQuery.Append($"WHERE No='{data.No}' ");
            strQuery.Append(";");

            if (DatabaseConnControl.ScanLongTermLog) SQLCmd = new SqlCommand(strQuery.ToString(), LongTermDBConn);
            else SQLCmd = new SqlCommand(strQuery.ToString(), ShortTermDBConn);
            SQLCmd.CommandTimeout = DMCommon.nDefaultScanTime;

            DbDataReader dtReader = SQLCmd.ExecuteReader();

            dtResult.Load(dtReader);
            dtReader.Close();

            if (dtResult.Rows.Count > 0)
            {
                var logData = dtResult.Rows[0]["LogData"].ToString();
                var decompStr = logData.GzipDecompress();

                list = JsonConvert.DeserializeObject<List<CPXV2Log.Tables.HIST_TestResult>>(decompStr);

                dtResult = list.ToDataTable();
            }          

            return dtResult;
        }

        DataTable GetRawResult(DetailTestDataCollection data)
        {
            DataTable dtResult = new DataTable();
            string strQuery = string.Empty;

            if (data == null)
                return dtResult;
                        
            SQLCmd = new SqlCommand(strQuery, DBConn);
            SQLCmd.CommandTimeout = DMCommon.nDefaultScanTime;

            DbDataReader dtReader = SQLCmd.ExecuteReader();

            dtResult.Load(dtReader);

            dtReader.Close();

            return dtResult;
        }
    }
}
