using Forks.EnterpriseServices.DomainObjects2;
using Forks.EnterpriseServices.DomainObjects2.DQuery;
using Forks.JsonRpc.Client;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using TSingSoft.WebPluginFramework;

namespace ButcherFactory.BO.Utils
{
  public static class LoginUtil
  {
    public static Worker InitUserFromLocal()
    {
      if (string.IsNullOrEmpty(AppContext.ConnectInfo.SqlConnection))
        return new Worker();
      using (var session = DmoSession.New())
      {
        var query = new DmoQuery(typeof(Worker));
        var obj = session.ExecuteScalar(query);
        if (obj != null)
          return (Worker)obj;
      }
      return new Worker();
    }

    public static void InitRpcFacade()
    {
      if (string.IsNullOrEmpty(AppContext.ConnectInfo.MainUrl))
        throw new Exception("请先设置服务器地址");
      if (!AppContext.RpcFacadeInited)
      {
        RpcFacade.Init(AppContext.ConnectInfo.MainUrl, "ButcherFactorySolution");
        AppContext.RpcFacadeInited = true;
      }
    }

    public static void ReInitRpcFacade()
    {
      if (AppContext.RpcFacadeInited)
        RpcFacade.ReInit(AppContext.ConnectInfo.MainUrl);
    }

    public static string GetWorkerNameByCode(string code)
    {
      string method = "/MainSystem/B3ClientService/Rpcs/LoginRpc/GetWorkerNameByCode";
      if (AppContext.ConnectInfo.ServerMode == 1)
        method = "/MainSystem/B3ButcherManage/Rpcs/ClientRpc/GetUserName";
      var result = RpcFacade.Call<string>(method, code);
      int r;
      if (int.TryParse(result, out r))
      {
        if (r == 0)
          throw new Exception("工号输入错误");
        throw new Exception("账号被停用");
      }
      else
      {
        AppContext.Worker.Code = code;
        return result;
      }
    }

    public static void Login(string userName, string pwd, int mode)
    {
      if (mode == 0)
        RpcLogin(userName, pwd);
      else
        FacedLogin(userName, pwd);

      AppContext.Worker.Name = userName;
      AppContext.Worker.Password = EncodePwd(pwd);
      using (var session = DmoSession.New())
      {
        var table = DmoInfo.Get(typeof(Worker)).MappedDBObject;
        var sql = string.Format(@"delete from [{0}]", table);
        session.ExecuteSqlNonQuery(sql);
        session.Insert(AppContext.Worker);
        session.Commit();
      }
    }

    static void FacedLogin(string userName, string pwd)
    {
      RpcFacade.Login(userName, pwd);
      const string roleMethod = "/MainSystem/B3ButcherManage/Rpcs/ClientRpc/GetUserRole";
      AppContext.Worker.Role = RpcFacade.Call<string>(roleMethod);
    }

    static void RpcLogin(string name, string pwd)
    {
      const string loginMethod = "/MainSystem/B3ClientService/Rpcs/LoginRpc/Login";
      var r = RpcFacade.Call<long>(loginMethod, name, pwd);
      if (r == 0)
        throw new Exception("用户名密码错误");
      else if (r == -1)
        throw new Exception("账号被停用");
      AppContext.Worker.ID = r;
      const string wpfUserMethod = "/MainSystem/B3ClientService/Rpcs/LoginRpc/GetWorkerBindDrive";
      AppContext.Worker.Role = RpcFacade.Call<string>(wpfUserMethod, AppContext.Worker.ID);
    }

    public static byte[] EncodePwd(string pwd)
    {
      using (MD5 md5 = MD5.Create())
        return md5.ComputeHash(Encoding.Unicode.GetBytes(pwd));
    }

    public static bool TestConnection(int? millisecondsTimeout = null)
    {
      var url = AppContext.ConnectInfo.MainUrl;
      if (string.IsNullOrEmpty(url))
        return false;
      var uri = new Uri(url);
      if (millisecondsTimeout == null)
      {
        millisecondsTimeout = 50;
      }
      return TestConnection(uri.Host, uri.Port, millisecondsTimeout.Value);
    }

    public static bool TestConnection(string host, int port, int millisecondsTimeout)
    {
      var client = new System.Net.Sockets.TcpClient();
      try
      {
        var ar = client.BeginConnect(host, port, null, null);
        ar.AsyncWaitHandle.WaitOne(millisecondsTimeout);
        return client.Connected;
      }
      catch (Exception)
      {
        return false;
      }
      finally
      {
        client.Close();
      }
    }
  }
}
