using Dapper;
using LAPS_XMLQC_Service.Models;
using LAPS_XMLQC_Service.Models.Configuration;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using Npgsql;
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security.Principal;

namespace LAPS_XMLQC_Service.App_Data
{
    public class CommonRepository
    {
        private readonly string _connectionString;

        public CommonRepository(IConfiguration configuration)
        {
            _connectionString = configuration.GetConnectionString("DbConnection")
                                ?? throw new ArgumentNullException("Connection string is not configured.");
        }
        
        public IEnumerable<string> ExecuteSP_ReturnListWithoutMode(string spName, string inputJsonString)
        {
            return ExecuteStoredProcedure<string>(spName, new { inputjsonstr = inputJsonString });
        }

        public IEnumerable<string> ExecuteSP_ReturnList(string spName, string inputJsonString, string mode)
        {
            var parameters = new
            {
                inputjsonstr = inputJsonString,
                mode_p = mode
            };
            return ExecuteStoredProcedure<string>(spName, parameters);
        }

        public IEnumerable<string> FindByID(int id)
        {
            var input = new
            {
                userid_p = id
            };
            return ExecuteSP_ReturnList("spusermasterselect", JsonConvert.SerializeObject(input), "getbyid");
        }

        public string GetServerPath(string transactionId, string mode, bool createDir = false)
        {
            string osType = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "Windows" : "Linux";
            var parameters = new
            {
                p_tranid = Convert.ToInt32(transactionId),
                p_lotid = (int?)null,
                p_option = mode,
                p_ostype = osType
            };

            try
            {
                var serverPaths = ExecuteStoredProcedure<servermasterModel>("public.spusrserverpathinfo", parameters);
                var serverPath = FormatPath(serverPaths.FirstOrDefault().serverpath);

                if (createDir)
                {
                    Directory.CreateDirectory(Path.Combine(serverPath, "IN"));
                    Directory.CreateDirectory(Path.Combine(serverPath, "OUT"));
                }

                return serverPath;
            }
            catch (Exception ex)
            {
                LogError("Error retrieving server path: " + ex.Message);
                return string.Empty;
            }
        }
       
        public lotmasterModel ExecuteSP_ReturnListForLot(string spName, string inputJsonString, string mode)
        {
            string osType = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "Windows" : "Linux";
            var inputData = JsonConvert.DeserializeObject<lotmasterModel>(inputJsonString);

            var parameters = new DynamicParameters();
            parameters.Add("p_tranid", dbType: DbType.Int32, value: inputData.transactionid, direction: ParameterDirection.Input);
            parameters.Add("p_lotid", dbType: DbType.Int32, value: inputData.lotid, direction: ParameterDirection.Input);
            parameters.Add("p_option", dbType: DbType.String, value: inputData.option, direction: ParameterDirection.Input);
            parameters.Add("p_ostype", dbType: DbType.String, value: osType, direction: ParameterDirection.Input);

            return ExecuteStoredProcedure<lotmasterModel>(spName, parameters).FirstOrDefault();
        }

        private string FormatPath(string inputPath)
        {
            try
            {
                inputPath = inputPath.Replace("/", "\\").Replace("\\\\", "");
                return string.Concat("\\\\", inputPath);
            }
            catch (Exception ex)
            {
                LogError("Error formatting path: " + ex.Message);
                return string.Empty;
            }
        }

        private void LogError(string message)
        {
            var logData = new
            {
                errormessage = message,
                createdby = 0,
                controller = "UploaderApi: Downloader"
            };
            AddLog(logData, "errorlog");
        }

        public int AddLog(object data, string masterName)
        {
            var parameters = new
            {
                inputjsonstr = JsonConvert.SerializeObject(data),
                mode_p = "insert"
            };

            return ExecuteStoredProcedure<int>($"public.sp{masterName}", parameters).First();
        }

        private IEnumerable<T> ExecuteStoredProcedure<T>(string spName, object parameters)
        {
            using var dbConnection = new NpgsqlConnection(_connectionString);
            dbConnection.Open();
            return dbConnection.Query<T>(spName, parameters, commandType: CommandType.StoredProcedure);
        }
        public class Impartunate
        {
            #region Impersonating User

            #region Impersonation
            static IntPtr tokenHandle;
            // static WindowsImpersonationContext impersonatedUser;
            private string impersUsername { get; set; }
            private string impersPwd { get; set; }
            private string impersDomain { get; set; }
            static WindowsIdentity newId;
            #endregion

            public Impartunate(string username, string password, string domain)
            {
                impersUsername = username;
                impersPwd = password;
                impersDomain = domain;
            }


            // public static WindowsImpersonationContext oImpersonatedUser;
            [DllImport("advapi32.dll", SetLastError = true)]
            private static extern bool LogonUser(string sUsername, string sDomain, string sPassword, int iLogonType, int iLogonProvider, ref IntPtr oToken);

            [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
            private static extern bool CloseHandle(IntPtr oHandle);

            //public bool AllowAccesstoServer()
            public WindowsIdentity AllowAccesstoServer()
            {
                try
                {
                    tokenHandle = IntPtr.Zero;
                    bool Result = LogonUser(impersUsername, impersDomain, impersPwd, 2, 0, ref tokenHandle);
                    if (Result)
                    {
                        newId = new WindowsIdentity(tokenHandle);
                        //impersonatedUser = newId.Impersonate();
                        //return true;
                        return newId;
                    }
                    else
                    {
                        //return false;
                        return null;
                    }
                }
                catch (Exception ex)
                {
                    //return false;
                    return null;
                }
            }

            public void RemoveServerAccess()
            {
                try
                {
                    //if (impersonatedUser != null)
                    //{
                    //    impersonatedUser.Undo();
                    //}
                    if (tokenHandle != IntPtr.Zero)
                    {
                        CloseHandle(tokenHandle);
                    }
                }
                catch (Exception ex) { }
            }

            private void ImpersonateUser()
            {
                System.IO.FileInfo localFileLastModified;
                System.IO.FileInfo serverFileLastModified;
                if (AllowAccesstoServer() == null)
                {
                    RemoveServerAccess();
                }
            }

            #endregion
        }


    }
}
