using Adaptation.Shared.Methods;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace Adaptation.Shared;

public class Logistics : ILogistics
{

    public object NullData { get; private set; }
    public string JobID { get; private set; } //CellName
    public long Sequence { get; private set; } //Ticks
    public DateTime DateTimeFromSequence { get; private set; }
    public double TotalSecondsSinceLastWriteTimeFromSequence { get; private set; }
    public string MesEntity { get; private set; } //SPC
    public string ReportFullPath { get; private set; } //Extract file
    public string ProcessJobID { get; set; } //Reactor (duplicate but I want it in the logistics)
    public string MID { get; set; } //Lot & Pocket || Lot
    public List<string> Tags { get; set; }
    public List<string> Logistics1 { get; set; }
    public List<Logistics2> Logistics2 { get; set; }

    public Logistics(IFileRead fileRead)
    {
        DateTime dateTime = DateTime.Now;
        NullData = null;
        Sequence = dateTime.Ticks;
        DateTimeFromSequence = dateTime;
        JobID = fileRead.CellInstanceName;
        TotalSecondsSinceLastWriteTimeFromSequence = (DateTime.Now - dateTime).TotalSeconds;
        MesEntity = DefaultMesEntity(dateTime);
        ReportFullPath = string.Empty;
        ProcessJobID = nameof(ProcessJobID);
        MID = nameof(MID);
        Tags = new List<string>();
        Logistics1 = new string[] { string.Concat("LOGISTICS_1", '\t', "A_JOBID=", JobID, ";A_MES_ENTITY=", MesEntity, ";") }.ToList();
        Logistics2 = new List<Logistics2>();
    }

    public Logistics(IFileRead fileRead, string reportFullPath, bool useSplitForMID, int? fileInfoLength = null)
    {
        if (string.IsNullOrEmpty(fileRead.CellInstanceName))
            throw new Exception();
        if (string.IsNullOrEmpty(fileRead.MesEntity))
            throw new Exception();
        NullData = fileRead.NullData;
        FileInfo fileInfo = new(reportFullPath);
        DateTime dateTime = fileInfo.LastWriteTime;
        if (fileInfoLength.HasValue && fileInfo.Length < fileInfoLength.Value)
            dateTime = dateTime.AddTicks(-1);
        JobID = fileRead.CellInstanceName;
        Sequence = dateTime.Ticks;
        DateTimeFromSequence = dateTime;
        TotalSecondsSinceLastWriteTimeFromSequence = (DateTime.Now - dateTime).TotalSeconds;
        MesEntity = fileRead.MesEntity;
        ReportFullPath = fileInfo.FullName;
        ProcessJobID = nameof(ProcessJobID);
        string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fileInfo.FullName);
        if (useSplitForMID)
        {
            if (fileNameWithoutExtension.IndexOf(".") > -1)
                fileNameWithoutExtension = fileNameWithoutExtension.Split('.')[0].Trim();
            if (fileNameWithoutExtension.IndexOf("_") > -1)
                fileNameWithoutExtension = fileNameWithoutExtension.Split('_')[0].Trim();
            if (fileNameWithoutExtension.IndexOf("-") > -1)
                fileNameWithoutExtension = fileNameWithoutExtension.Split('-')[0].Trim();
        }
        MID = string.Concat(fileNameWithoutExtension.Substring(0, 1).ToUpper(), fileNameWithoutExtension.Substring(1).ToLower());
        Tags = new List<string>();
        Logistics1 = new string[] { string.Concat("LOGISTICS_1", '\t', "A_JOBID=", JobID, ";A_MES_ENTITY=", MesEntity, ";") }.ToList();
        Logistics2 = new List<Logistics2>();
    }

    public Logistics(string reportFullPath, string logistics)
    {
        string key;
        DateTime dateTime;
        string[] segments;
        Logistics1 = logistics.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries).ToList();
        if (!Logistics1.Any() || !Logistics1[0].StartsWith("LOGISTICS_1"))
        {
            NullData = null;
            JobID = "null";
            dateTime = new FileInfo(reportFullPath).LastWriteTime;
            Sequence = dateTime.Ticks;
            DateTimeFromSequence = dateTime;
            TotalSecondsSinceLastWriteTimeFromSequence = (DateTime.Now - dateTime).TotalSeconds;
            MesEntity = DefaultMesEntity(dateTime);
            ReportFullPath = reportFullPath;
            ProcessJobID = "R##";
            MID = "null";
            Tags = new List<string>();
            Logistics1 = new string[] { string.Concat("LOGISTICS_1", '\t', "A_JOBID=", JobID, ";A_MES_ENTITY=", MesEntity, ";") }.ToList();
            Logistics2 = new List<Logistics2>();
        }
        else
        {
            string logistics1Line1 = Logistics1[0];
            key = "NULL_DATA=";
            if (!logistics1Line1.Contains(key))
                NullData = null;
            else
            {
                segments = logistics1Line1.Split(new string[] { key }, StringSplitOptions.RemoveEmptyEntries);
                NullData = segments[1].Split(';')[0];
            }
            key = "JOBID=";
            if (!logistics1Line1.Contains(key))
                JobID = "null";
            else
            {
                segments = logistics1Line1.Split(new string[] { key }, StringSplitOptions.RemoveEmptyEntries);
                JobID = segments[1].Split(';')[0];
            }
            key = "SEQUENCE=";
            if (!logistics1Line1.Contains(key))
                dateTime = new FileInfo(reportFullPath).LastWriteTime;
            else
            {
                segments = logistics1Line1.Split(new string[] { key }, StringSplitOptions.RemoveEmptyEntries);
                if (!long.TryParse(segments[1].Split(';')[0].Split('.')[0], out long sequence) || sequence < new DateTime(1999, 1, 1).Ticks)
                    dateTime = new FileInfo(reportFullPath).LastWriteTime;
                else
                    dateTime = new DateTime(sequence);
            }
            Sequence = dateTime.Ticks;
            DateTimeFromSequence = dateTime;
            TotalSecondsSinceLastWriteTimeFromSequence = (DateTime.Now - dateTime).TotalSeconds;
            DateTime lastWriteTime = new FileInfo(reportFullPath).LastWriteTime;
            if (TotalSecondsSinceLastWriteTimeFromSequence > 600)
            {
                if (lastWriteTime != dateTime)
                    try
                    { File.SetLastWriteTime(reportFullPath, dateTime); }
                    catch (Exception) { }
            }
            key = "MES_ENTITY=";
            if (!logistics1Line1.Contains(key))
                MesEntity = DefaultMesEntity(dateTime);
            else
            {
                segments = logistics1Line1.Split(new string[] { key }, StringSplitOptions.RemoveEmptyEntries);
                MesEntity = segments[1].Split(';')[0];
            }
            ReportFullPath = reportFullPath;
            key = "PROCESS_JOBID=";
            if (!logistics1Line1.Contains(key))
                ProcessJobID = "R##";
            else
            {
                segments = logistics1Line1.Split(new string[] { key }, StringSplitOptions.RemoveEmptyEntries);
                ProcessJobID = segments[1].Split(';')[0];
            }
            key = "MID=";
            if (!logistics1Line1.Contains(key))
                MID = "null";
            else
            {
                segments = logistics1Line1.Split(new string[] { key }, StringSplitOptions.RemoveEmptyEntries);
                MID = segments[1].Split(';')[0];
            }
        }
        Logistics2 logistics2;
        Tags = new List<string>();
        Logistics2 = new List<Logistics2>();
        for (int i = 1; i < Logistics1.Count; i++)
        {
            if (Logistics1[i].StartsWith("LOGISTICS_2"))
            {
                logistics2 = new Logistics2(Logistics1[i]);
                Logistics2.Add(logistics2);
            }
        }
        for (int i = Logistics1.Count - 1; i > -1; i--)
        {
            if (Logistics1[i].StartsWith("LOGISTICS_2"))
                Logistics1.RemoveAt(i);
        }
    }

    public Logistics ShallowCopy() => (Logistics)MemberwiseClone();

    private static string DefaultMesEntity(DateTime dateTime) => string.Concat(dateTime.Ticks, "_MES_ENTITY");

    internal string GetLotViaMostCommonMethod() => MID.Substring(0, MID.Length - 2);

    internal string GetPocketNumberViaMostCommonMethod() => MID.Substring(MID.Length - 2);

    internal void Update(string dateTime, string processJobID, string mid)
    {
        if (!DateTime.TryParse(dateTime, out DateTime dateTimeCasted))
            dateTimeCasted = DateTime.Now;
        NullData = null;
        //JobID = Description.GetCellName();
        Sequence = dateTimeCasted.Ticks;
        DateTimeFromSequence = dateTimeCasted;
        TotalSecondsSinceLastWriteTimeFromSequence = (DateTime.Now - dateTimeCasted).TotalSeconds;
        //MesEntity = DefaultMesEntity(dateTime);
        //ReportFullPath = string.Empty;
        ProcessJobID = processJobID;
        MID = mid;
        Tags = new List<string>();
        Logistics1 = new string[] { string.Concat("LOGISTICS_1", '\t', "A_JOBID=", JobID, ";A_MES_ENTITY=", MesEntity, ";") }.ToList();
        Logistics2 = new List<Logistics2>();
    }
}