using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using SystemX.Common;
using SystemX.Common.Archive;
using SystemX.Net.BaseProtocol;
using SystemX.Net.Schedule;

using static SystemX.Net.Platform.Common.Util.LogMessage;

namespace SystemX.Net.XAdaptor.PC
{
    public partial class XAdaptorPC
    {
        private async void WatchSubProcess()
        {
            await Task.Delay(500).ConfigureAwait(false);

            while (!StateClientGetInformation)
            {
                await Task.Delay(10).ConfigureAwait(false);
            }

            while (!m_bTaskSubBlock)
            {
                await Task.Delay(10).ConfigureAwait(false);

                try
                {
                    StreamCT.ThrowIfCancellationRequested();
                }
                catch (OperationCanceledException CancelEx)
                {
                    MessageOutput.ConsoleWrite(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss>>") + @" Work Canceled. [SystemX.Net.XAdaptor.PC.XPCAdaptor : ProcessTask.WatchFailedFile]\r\n" + CancelEx.Message, ConsoleColor.Yellow, LogMessageLevel.DEBUG);

                    break;
                }
                //
                try
                {
                    if (StateClientStreamSocketConnect == false)
                        continue;
                    ///
                    /// 5분이상 기존 파일전송이 없을 경우 
                    ///
                    if (stFileSendTime.ElapsedMilliseconds < FILE_SEND_MAX_WAITTIME)
                        goto ROUTINE_OUT;
                    ///
                    /// 직전 전송이 10초 이상 일때(완전 처리 대기)
                    ///
                    if (stBackupFileSendTime.ElapsedMilliseconds < FILE_SEND_INTERVAL_TIME)
                        goto ROUTINE_OUT;

                    if (bTaskSubLockState)
                        goto ROUTINE_OUT;

                    try
                    {
                        bTaskSubLockState = await _smpSlim.WaitAsync(100);

                        if (bTaskSubLockState == false)
                            goto ROUTINE_OUT;

                        //Scan And Send File
                        //오늘 포함 -6일전까지 검색
                        string[] strYYYY = new string[7];
                        string[] strMM = new string[7];
                        string[] strdd = new string[7];

                        for (int i = 6; i >= 0; i--)
                        {
                            DateTime dtSet = DateTime.Today.AddDays(-i);
                            strYYYY[i] = dtSet.ToString("yyyy");
                            strMM[i] = dtSet.ToString("MM");
                            strdd[i] = dtSet.ToString("dd");
                        }
                        //
                        // 7일치 위치 확인
                        // 
                        for (int i = 0; i < 7; i++)
                        {
                            string strGetRoot = Path.GetPathRoot(Environment.CurrentDirectory);

                            string DirPath = strGetRoot + $@"\XLog\FileFailedBackup\{LoadInfo.HOST_ID}\{LoadInfo.SECTION}\{strYYYY[i]}\{strMM[i]}\{strdd[i]}\";
                            string DirMovePath = strGetRoot + $@"\XLog\FileFailedBackup\{LoadInfo.HOST_ID}\{LoadInfo.SECTION}\{strYYYY[i]}\{strMM[i]}\{strdd[i]}\History\";

                            //생성 폴더가 없을경우 SKIP
                            if (Directory.Exists(DirPath) == false)
                                continue;

                            if (Directory.Exists(DirMovePath) == false)
                                Directory.CreateDirectory(DirMovePath);

                            string fileExtension = "zip";

                            string[] dirs = Directory.GetDirectories(DirPath);
                            string[] files = Directory.GetFiles(DirPath, $"*.{fileExtension}", SearchOption.TopDirectoryOnly);

                            if (files.Length > 0)
                            {
                                string strExtractFilePos = string.Empty;
                                string strOrgRemoveFilePos = string.Empty;

                                string strHeaderInfo = string.Empty;
                                string strLogFileNameInfo = string.Empty;

                                foreach (string f in files)
                                {
                                    strOrgRemoveFilePos = f;

                                    strHeaderInfo = string.Empty;
                                    strLogFileNameInfo = string.Empty;

                                    string[] strInfos = f.Split(';');

                                    //파일정보 확인(로그 저장관련 정보)
                                    string strSetDateTime = strInfos[1];
                                    string strSetStationName = strInfos[2];
                                    int nSetTestListVariantNo = int.Parse(strInfos[3]);
                                    string strSetProcNoP = strInfos[4];
                                    string strSetProcNoC = strInfos[5];
                                    string strSetTestType = strInfos[6];
                                    string strSetTestCode = strInfos[7];
                                    string strSetVersion = strInfos[8];
                                    string strSetProdCode = strInfos[9];
                                    string strSetTestListCntID = strInfos[10];
                                    int nSetTryNo = int.Parse(strInfos[11]);

                                    for (int n = 1; n < 10; n++)
                                        strHeaderInfo += (strInfos[n + 1] + ";");

                                    strHeaderInfo = strHeaderInfo.Remove(strHeaderInfo.Length - 1, 1);

                                    //압축해제 하여 로그 파일 추출
                                    using (FileStream fs = new FileStream(f, FileMode.Open))
                                    using (ZipArchive zip = new ZipArchive(fs, ZipArchiveMode.Update, false))
                                    {
                                        foreach (ZipArchiveEntry zae in zip.Entries)
                                        {
                                            strLogFileNameInfo = zae.FullName;

                                            if (strLogFileNameInfo.IndexOf(".txt") >= 0)
                                                continue;

                                            strExtractFilePos = DirPath + strLogFileNameInfo;

                                            zae.ExtractToFile(strExtractFilePos, true);
                                        }
                                    }

                                    //로그 파일 전송
                                    if (await AsyncFailedLogFileTransfer(strExtractFilePos,
                                        strSetStationName,
                                        nSetTestListVariantNo,
                                        strSetProcNoP,
                                        strSetProcNoC,
                                        strSetTestType,
                                        strSetTestCode,
                                        strSetVersion,
                                        strSetProdCode,
                                        strSetTestListCntID) == eFileSendRecvResult.FileProcSuccess)
                                    {
                                        //성공시
                                        string strCopyPos = DirMovePath;
                                        for (int n = 0; n < 10; n++)
                                            strCopyPos += (";" + strInfos[n + 1]);

                                        strCopyPos += (";" + nSetTryNo.ToString() + ";.zip");

                                        File.Copy(f, strCopyPos, true);

                                        XAdaptorFileLogWrite(eSetFileLogCategory.FileLog, strYYYY[i], strMM[i], strdd[i], strHeaderInfo, strLogFileNameInfo, "FailedFileTrySend>Success");
                                    }
                                    else
                                    {
                                        //실패시 
                                        nSetTryNo++;

                                        string strTryNo = string.Empty;

                                        string strCopyPos = string.Empty;

                                        //재시도 3회 초과 일시 히스토리로 이동 
                                        if (nSetTryNo > 3)
                                        {
                                            strCopyPos = DirMovePath;

                                            strTryNo = "X";

                                            XAdaptorFileLogWrite(eSetFileLogCategory.FileLog, strYYYY[i], strMM[i], strdd[i], strHeaderInfo, strLogFileNameInfo, "FailedFileTrySend>UnprocessableFile");
                                        }
                                        else
                                        {
                                            strCopyPos = DirPath;

                                            strTryNo = nSetTryNo.ToString();

                                            XAdaptorFileLogWrite(eSetFileLogCategory.FileLog, strYYYY[i], strMM[i], strdd[i], strHeaderInfo, strLogFileNameInfo, "FailedFileTrySend>Fail");
                                        }

                                        for (int n = 0; n < 10; n++)
                                            strCopyPos += (";" + strInfos[n + 1]);

                                        strCopyPos += (";" + strTryNo + ";.zip");

                                        File.Copy(f, strCopyPos, true);
                                    }

                                    //압축해제 파일 삭제
                                    File.Delete(strExtractFilePos);

                                    break;
                                }

                                //성공시나 실패시 새로운 파일생성 되기 때문에 기존 파일 삭제
                                if (strOrgRemoveFilePos != string.Empty)
                                    File.Delete(strOrgRemoveFilePos);

                                break;
                            }
                        }

                        stBackupFileSendTime.Restart();
                    }
                    finally
                    {
                        if (bTaskSubLockState)
                        {
                            try
                            {
                                _smpSlim.Release();
                            }
                            catch
                            {
                                ;//smp release lock exception
                            }

                            bTaskSubLockState = false;
                        }
                    }

                    ROUTINE_OUT:;
                }
                catch (Exception ex)
                {
                    MessageOutput.ConsoleWrite(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss>>") + @"General Queue Process failed.[SystemX.Net.XAdaptor.PC.XPCAdaptor : ProcessTask.WatchFailedFile]\r\n" + ex.Message, ConsoleColor.Yellow, LogMessageLevel.DEBUG);
                }
            }
        }
    }
}
