using ExcelToCsvToDb.BusinessLogic;
using ExcelToCsvToDb.Commons;
using KssSmaPlaLib.Batch.Dispatch;
using KssSmaPlaLib.Batch.Interface;
using KssSmaPlaLib.Batch.Log;
using KssSmaPlaLib.Batch.StepInfo;
using KssSmaPlaLib.Commons;
using KssSmaPlaLib.Encryption;
using KssSmaPlaLib.Ini;
using KssSmaPlaLib.IO.File;
using KssSmaPlaLib.Tools.FileHack;
using System.Linq;

namespace ExcelToCsvToDb
{
    internal class Program
    {
        /// <summary>
        /// エンドポイント
        /// </summary>
        /// <param name="args"></param>
        /// <returns>0:正常終了、-1以下:異常終了</returns>
        static int Main(string[] args)
        {
            // 暗号化ツール（Additional）
            if (SimpleEncryptUxer.TuckIntoMain(args)) return 0;
            if (FIleEncryptUxer.TuckIntoMain(args)) return 0;
            if (SplitFileBySizeUxer.TuckIntoMain(args)) return 0;
            if (MergeSplitFilesUxer.TuckIntoMain(args)) return 0;

            // INIファイルパス
            if (!PathUxer.TryResolveInAssemblyFolder(Common.INI_FILE_NAME, out Common.INI_FILE_PATH))
            {
                LoggerUxer.Error($"設定INIファイルのパス解決に失敗しました。[ファイル名:{Common.INI_FILE_NAME}]");
                return (int)Common.RetCode.IniFiilePathError;
            }

            // ログINI初期化（無ければ）と起動ログ
            LoggerUxer.Initialize(Common.INI_FILE_PATH);
            LoggerUxer.StartInfo();

            LoggerUxer.Info($"[起動時引数:{string.Join(",", args)}]");

            if (args.Length < 1)
            {
                LoggerUxer.Error("起動時引数が1個以上必要です。");
                return (int)Common.RetCode.ExecuteParameterCountError;
            }

            // タスク起動判定
            var isTask = false;
            string[] argsNew = args;
            if (args[0].Trim().ToLower() == "/task")
            {
                isTask = true;

                LoggerUxer.Info($"タスクモードで起動されました。[指定:{args[0].Trim()}]");

                // 先頭をカットして従来通り処理させる
                argsNew = args.Skip(1).ToArray();
            }

            // 起動パラメータの取得
            VariableUxer.SetArgs(argsNew);

            // CLの機能ディスパッチャ
            var stepDispatcher = new StepDispatcherUxer();

            // タスクモード繰り返しループ
            while (true)
            {
                // 処理区分による分岐
                var shoriKubun = argsNew[0].Trim('/');
                LoggerUxer.Info($"[処理区分:{shoriKubun}]");

                // ステップリスト取得
                var dic = IniReaderUxer.ReadSection(Common.INI_FILE_PATH, shoriKubun);
                if (!StepInfoUxer.TryCreateStepInfoFromIniDic(dic, out var stepInfo, out var messageForMe))
                {
                    LoggerUxer.Error($"{messageForMe}");
                    return (int)Common.RetCode.StepListError;
                }

                // ステップ処理開始ログ
                StepLogUxer.StepInfoLog(stepInfo);

                // ステップ全件
                foreach (var step in stepInfo.StepList)
                {
                    IFuncResultDto result;

                    LoggerUxer.Info($"ステップを開始します。[ステップ番号:{step.StepNo},機能:{step.StepSignature}]");

                    if (!StringUxer.TryParseIniSignature(step.StepSignature, out var functionName, out var funcArgs) || funcArgs.Count < 1)
                    {
                        LoggerUxer.Error($"ステップ情報の形式が不正です。[処理区分:{stepInfo.Title},ステップ番号:{step.StepNo},値（機能名）:{step.StepSignature}]");
                        return (int)Common.RetCode.IniStepInfoFormatError;
                    }

                    // INIの対象セクション名
                    var iniSectionName = funcArgs[0];

                    // 処理振り分け
                    if (functionName.ToUpper() == Common.MAINPJ_KOYU_STEP_NAME_EXCEL_TO_CSV_WEORDER)
                    {
                        // 固有（メインPJ）：Excel→CSV（WE生産計画詳細）
                        result = new ExcelToCsv().TryFuncExcelToCsvWeOrderByIni(Common.INI_FILE_PATH, iniSectionName);
                        if (result.Succeeded == false)
                        {
                            LoggerUxer.Error($"ステップが失敗しました。処理を中断します。[エラー内容:{result.ResultMessage}]");
                            return result.ExitCode;
                        }
                    }
                    else if (functionName.ToUpper() == Common.MAINPJ_KOYU_STEP_NAME_EXCEL_TO_CSV_EAZY)
                    {
                        // 固有（メインPJ）：Excel→CSV（簡易）
                        result = new ExcelToCsv().TryFuncExcelToCsvEazyByIni(Common.INI_FILE_PATH, iniSectionName);
                        if (result.Succeeded == false)
                        {
                            LoggerUxer.Error($"ステップが失敗しました。処理を中断します。[エラー内容:{result.ResultMessage}]");
                            return result.ExitCode;
                        }
                    }
                    else
                    {
                        // 共通（CL）処理
                        if (!stepDispatcher.TryDispatch(functionName, Common.INI_FILE_PATH, iniSectionName, out messageForMe, out var funcResultDto))
                        {
                            LoggerUxer.Error($"ステップの実行に失敗しました。[処理区分:{shoriKubun},ステップ:{step.StepNo},機能名:{step.StepSignature},エラー内容:{messageForMe}]");
                            return
                                funcResultDto != null && funcResultDto.ExitCode != (int)RetCodeUxer.RetCode.Success ?
                                funcResultDto.ExitCode :
                                (int)Common.RetCode.StepFunctionError;
                        }
                    }
                    LoggerUxer.Info($"ステップが終了しました。[ステップ番号:{step.StepNo},機能:{step.StepSignature}]");
                }
                if (!isTask)
                {
                    LoggerUxer.Info($"全てのステップが終了しました。プログラムを終了します。");
                    return (int)Common.RetCode.Success;
                }
                LoggerUxer.Info($"全てのステップが終了しました。少し休憩してのち、再開いたします。");

                // インターバル
                var sleepSec = int.TryParse(IniHelper.ReadValue(Common.INI_FILE_PATH, "Task", "IntervalSec", "10"), out var intVal) ? intVal : 10;
                System.Threading.Thread.Sleep(sleepSec * 1000);
            }
        }
    }
}
