using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using GxPress.Common.Address;
using GxPress.Common.Http;
using GxPress.Common.Tools;
using GxPress.Repository.Interface;
using GxPress.Request.App.ChatRecord;
using GxPress.Service.Interface.IM;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Caching.Distributed;
using Newtonsoft.Json;
using GxPress.Common.Extensions;
using GxPress.Service.Interface.GroupChat;
namespace GxPress.Service.Implement.IM
{
    public partial class IMService : IIMService
    {
        private readonly IWebHostEnvironment _environment;
        private readonly IDistributedCache _cache;
        private readonly IChatRecordRepository _chatRecordRepository;
        private readonly IUserRepository _userRepository;
        private readonly IGroupChatRepository _groupChatRepository;
        private readonly IGroupChatService groupChatService;
        private readonly IGroupChatUserRepository _groupChatUserRepository;
        private readonly IFileLibraryRepository _fileLibraryRepository;
        private readonly IBlacklistUserRepository _blacklistUserRepository;
        private readonly IOftenContactRepository _oftenContactRepository;
        public IMService(IWebHostEnvironment environment, IDistributedCache cache, IChatRecordRepository chatRecordRepository,
            IUserRepository userRepository, IFileLibraryRepository fileLibraryRepository,
            IGroupChatRepository groupChatRepository, IGroupChatUserRepository groupChatUserRepository,
            IBlacklistUserRepository blacklistUserRepository, IOftenContactRepository oftenContactRepository,IGroupChatService groupChatService)
        {
            _environment = environment;
            _cache = cache;
            _chatRecordRepository = chatRecordRepository;
            _userRepository = userRepository;
            _fileLibraryRepository = fileLibraryRepository;
            _groupChatRepository = groupChatRepository;
            _groupChatUserRepository = groupChatUserRepository;
            _blacklistUserRepository = blacklistUserRepository;
            _oftenContactRepository = oftenContactRepository;
            this.groupChatService=groupChatService;
        }

        /// <summary>
        /// 获取环信历史记录
        /// </summary>
        /// <returns></returns>
        public async Task<bool> GatherChatDataAsync()
        {
            var token = await _cache.GetAsync<string>("ImToken");
            // var times = DateTime.Now.AddHours(-2).ToString("YYYYMMDDHH");
            var times = "2019112711";
            var headers = new Dictionary<string, string> { { "Authorization", "Bearer " + token } };
            var requestUrl = Address.GetImChatMassageUrl(times);
            var response = await HttpClientHelper.GetHeadersAsync(requestUrl, headers);
            //请求成功
            if (!response.IsSuccessStatusCode)
            {
                //token过期重新拉去
                if (response.StatusCode == HttpStatusCode.Unauthorized)
                {
                    var result = await GetTokenImAsync();
                    if (result)
                    {
                        headers = new Dictionary<string, string>
                           {{"Authorization", "Bearer " + await _cache.GetAsync<string>("ImToken")}};
                        requestUrl = Address.GetImChatMassageUrl(times);
                        response = await HttpClientHelper.GetHeadersAsync(requestUrl, headers);
                    }
                }
                else
                    return false;
            }

            //获取返回的内容
            var content = await response.Content.ReadAsStringAsync();
            var dataJson = JsonConvert.DeserializeObject<dynamic>(content);
            var url = dataJson["data"][0]["url"];
            //下载GZ解压包
            var gzUrl = await DecompressionGzip(url.ToString());
            //获取文本内容
            StreamReader sr = new StreamReader(gzUrl, Encoding.Default);
            string jsonText;
            while ((jsonText = sr.ReadLine()) != null)
            {
                await InsertChatHistory(jsonText);
            }
            return true;
        }

        /// <summary>
        /// 强制下线
        /// </summary>
        /// <param name="phone"></param>
        /// <returns></returns>
        public async Task<bool> DisconnectAsync(string phone)
        {
            var imServiceUrl = ConfigHelper.GetValue("ServiceAddress:ImUrl");
            var token = await _cache.GetAsync<string>("ImToken");
            var url = $"{imServiceUrl}/{phone}/disconnect";
            var headers = new Dictionary<string, string> { { "Authorization", "Bearer " + token } };
            var response = await HttpClientHelper.GetHeadersAsync(url, headers);
            if (response.IsSuccessStatusCode)
                return true;
            return false;
        }

        /// <summary>
        /// 解压GzZIP
        /// </summary>
        /// <returns></returns>
        public async Task<string> DecompressionGzip(string url)
        {
            var response = await HttpClientHelper.GetByteArrayAsync(url);
            string filePath;
            //获取路径
            var path = FileHelper.SaveFile(StringUtils.GetWebRootPath(_environment.WebRootPath), ".gz", response);
            //解压
            using (FileStream fr = File.OpenRead(path.AbsolutePath))
            {
                using (GZipStream gz = new GZipStream(fr, CompressionMode.Decompress))
                {
                    filePath = FileHelper.GetSavePath(StringUtils.GetWebRootPath(_environment.WebRootPath), ".txt")
                        .AbsolutePath;
                    using (FileStream fw = File.OpenWrite(filePath))
                    {

                        byte[] by = new byte[1024 * 1024];
                        int r = gz.Read(by, 0, by.Length);
                        while (r > 0)
                        {
                            fw.Write(by, 0, r);
                            r = gz.Read(by, 0, r);
                        }
                    }
                }
            }
            return filePath;
        }

        /// <summary>
        /// 分析并插入
        /// </summary>
        /// <param name="json"></param>
        /// <returns></returns>
        public async Task<bool> InsertChatHistory(string json)
        {
            var dataJson = JsonConvert.DeserializeObject<dynamic>(json);
            //获取 单聊 或者 群聊
            var chatType = dataJson.chat_type;
            //获取发起人的imId
            var imId = dataJson.from.ToString();
            var toImId = dataJson.to.ToString();
            //获取用户
            var user = await _userRepository.GetByPhoneAsync(imId);
            var request = new ChatRecordInRequest
            {
                ChatType = chatType.ToString().Equals("chat") ? 1 : 2,
                SendUserId = user.Id
            };
            if (request.ChatType == 1)
            {
                var toUser = await _userRepository.GetByPhoneAsync(imId);
                request.ReceiveUserId = toUser.Id.ToString();
            }
            else
            {
                var toGroupChat = _groupChatRepository.GetGroupChatByImIdAsync(int.Parse(toImId));
                request.ReceiveUserId = toGroupChat.GroupChatImId;
            }

            foreach (var bodies in dataJson.payload.bodies)
            {
                var typeName = bodies.type.ToString();
                if (typeName.Equals("txt"))
                    request.MsgType = 1;
                if (typeName.Equals("loc"))
                    request.MsgType = 6;
                if (typeName.Equals("audio"))
                    request.MsgType = 5;
                if (typeName.Equals("video"))
                    request.MsgType = 4;
                if (typeName.Equals("file"))
                    request.MsgType = 3;
                if (typeName.Equals("loc"))
                    request.MsgType = 6;
                if (typeName.Equals("img"))
                    request.MsgType = 2;
                //判断是否是文本
                if (request.MsgType == 1)
                {
                    string msg = bodies.msg.ToString();
                    request.Content = msg;
                }
                else if (request.MsgType == 6)
                {
                    string msg = bodies.lat.ToString() + "," + bodies.lng.ToString();
                    request.Content = msg;
                }
                else
                {
                    //获取用户数据
                    var url = bodies.url.ToString();
                    var fileName = bodies.filename.ToString();
                    var fileType = bodies.type.ToString().Equals("img")
                        ? "image"
                        : (string)Path.GetExtension(fileName);
                    //下载
                    var response = await HttpClientHelper.GetByteArrayAsync(url);
                    //获取路径
                    var path = FileHelper.SaveFile(StringUtils.GetWebRootPath(_environment.WebRootPath), fileName,
                        response);
                    var fileLibrary = new Entity.FileLibrary
                    { FileName = fileName, FileType = fileType, FileUrl = path.RelativePath };
                    //file
                    var fileLibraryId = await _fileLibraryRepository.InsertAsync(fileLibrary);
                    request.Content = fileLibraryId.ToString();
                }

                //保存
                await _chatRecordRepository.InsertAsync(request);
            }

            return true;
        }

        /// <summary>
        /// 获取token
        /// </summary>
        /// <returns></returns>
        public async Task<bool> GetTokenImAsync()
        {
            var imServiceUrl = ConfigHelper.GetValue("ServiceAddress:ImUrl");
            var grantType = ConfigHelper.GetValue("ServiceAddress:GrantType");
            var clientId = ConfigHelper.GetValue("ServiceAddress:ClientId");
            var clientSecret = ConfigHelper.GetValue("ServiceAddress:ClientSecret");
            var requestUrl = $"{imServiceUrl}/token";
            var jsonObj = new
            {
                grant_type = grantType,
                client_id = clientId,
                client_secret = clientSecret
            };
            var response = await HttpClientHelper.PostAsync(requestUrl, jsonObj);
            if (!response.IsSuccessStatusCode)
            {
                return false;
            }
            var key = "ImToken";
            var tokenJson = await response.Content.ReadAsStringAsync();
            var dataJsonDynamic = JsonConvert.DeserializeObject<dynamic>(tokenJson);

            string value = dataJsonDynamic.access_token.ToString();

            await _cache.SetAsync<string>(key, value, new DistributedCacheEntryOptions
            {
                AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(Convert.ToInt32(dataJsonDynamic.expires_in))
            });

            return true;
        }

    }
}
