using Infrastructure;
using Infrastructure.Extensions;
using Infrastructure.Helpers;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using OpenAuth.App.BaseApp.Base;
using OpenAuth.App.Interface;
using OpenAuth.App.ServiceApp.GoView.Request;
using OpenAuth.App.ServiceApp.GoView.Response;
using OpenAuth.Repository;
using OpenAuth.Repository.Domain;
using OpenAuth.Repository.Domain.GoView;
using SqlSugar;

namespace OpenAuth.App.ServiceApp.GoView;

public class GoViewProjectApp : SqlSugarBaseApp<GoviewProject, SugarDbContext>
{
    private ILogger<FileApp> _logger;
    private string _filePath;
    private string _dbFilePath; //数据库中的文件路径
    private string _dbThumbnail; //数据库中的缩略图路径

    public GoViewProjectApp(IOptions<AppSetting> setOptions, ISugarUnitOfWork<SugarDbContext> unitWork,
        ISimpleClient<GoviewProject> repository,
        IAuth auth, ILogger<FileApp> logger) : base(unitWork, repository, auth)
    {
        _logger = logger;
        _filePath = setOptions.Value.UploadPath;
        if (string.IsNullOrEmpty(_filePath))
        {
            _filePath = AppContext.BaseDirectory;
        }
    }

    public async Task<Response<bool>> DeleteProject(string ids)
    {
        var idArray = ids.Split(",");
        var flag = await Repository.DeleteByIdsAsync(idArray);
        return new Response<bool> { Code = 200, Result = flag, Message = flag ? "删除成功" : "删除失败" };
    }

    public async Task<Response<bool>> UpdateProject(GoviewProject project)
    {
        var exist = await Repository.AsQueryable().CountAsync(a => a.Id == project.Id);
        if (exist == 0)
        {
            return new Response<bool> { Code = 500, Message = "项目不存在" };
        }

        var flag = await Repository.AsUpdateable(project).IgnoreNullColumns().ExecuteCommandAsync();
        return new Response<bool>
            { Code = 200, Result = flag > 0, Message = flag > 0 ? "修改成功" : "修改失败" };
    }

    public async Task<Response<GoviewProject>> Create(GoviewProject project)
    {
        project.State = -1;
        project.CreateTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
        var userId = _auth.GetUserId();
        project.CreateUserId = userId;
        project.Id = Guid.NewGuid().ToString();
        var flag = await Repository.InsertAsync(project);
        return new Response<GoviewProject>
            { Code = 200, Result = flag ? project : null, Message = flag ? "创建成功" : "创建失败" };
    }

    public async Task<Response<bool>> Publish(GoViewProjectRequest req)
    {
        var prj = new GoviewProject
        {
            Id = req.Id,
            State = req.State
        };
        var flag = await Repository.AsUpdateable(prj).IgnoreNullColumns().ExecuteCommandAsync() > 0;
        return new Response<bool> { Code = 200, Result = flag, Message = flag ? "操作成功" : "操作失败" };
    }

    public async Task<Response<PageInfo<List<GoviewProject>>>> List(GoViewProjectPage page)
    {
        RefAsync<int> total = 0;
        var list = await Repository.AsQueryable()
            .WhereIF(page.state != null, a => a.State == page.state)
            .ToPageListAsync(page.page, page.limit, total);
        return new Response<PageInfo<List<GoviewProject>>>()
        {
            Result = new PageInfo<List<GoviewProject>>
            {
                Items = list,
                Total = total
            }
        };
    }

    public async Task<Response<ProjectResponse>> GetData(string projectId)
    {
        var prj = await Repository.AsQueryable().SingleAsync(a => a.Id == projectId);
        if (prj == null)
        {
            return new Response<ProjectResponse>()
            {
                Message = "项目不存在",
                Code = 500
            };
        }

        var vo = prj.MapTo<ProjectResponse>();
        var data = await Repository.ChangeRepository<SugarRepositiry<GoviewProjectData>>().AsQueryable()
            .SingleAsync(a => a.ProjectId == projectId);

        if (data != null)
        {
            vo.Content = data.Content;
        }

        return new Response<ProjectResponse>()
        {
            Result = vo
        };
    }

    public async Task<Response<bool>> SaveData(GoviewProjectData data)
    {
        // 更新还是保存，
        var project = await Repository.AsQueryable().SingleAsync(a => a.Id == data.ProjectId);
        if (project == null)
        {
            throw new Exception("项目不存在");
        }

        var prjData = await Repository
            .ChangeRepository<SugarRepositiry<GoviewProjectData>>()
            .AsQueryable()
            .SingleAsync(a => a.ProjectId == data.ProjectId);
        bool flag;
        if (prjData == null)
        {
            data.Id = Guid.NewGuid().ToString();
            flag = await Repository.ChangeRepository<SugarRepositiry<GoviewProjectData>>().InsertAsync(data);
        }
        else
        {
            data.Id = prjData.Id;
            flag = await Repository
                .ChangeRepository<SugarRepositiry<GoviewProjectData>>()
                .AsUpdateable(data)
                .IgnoreNullColumns()
                .ExecuteCommandAsync() > 0;
        }

        return new Response<bool> { Code = 200, Result = flag, Message = flag ? "数据保存成功" : "数据保存失败" };
    }

    #region 组件数据

    /// <summary>
    /// 获取组件集合
    /// </summary>
    /// <param name="page"></param>
    /// <returns></returns>
    public async Task<Response<PageInfo<List<GoviewComponent>>>> GetComponentList(GoViewProjectPage page)
    {
        RefAsync<int> total = 0;
        var list = await Repository.ChangeRepository<SugarRepositiry<GoviewComponent>>().AsQueryable()
            .WhereIF(!string.IsNullOrEmpty(page.key), r => r.ComponentName.Contains(page.key))
            .ToPageListAsync(page.page, page.limit, total);
        return new Response<PageInfo<List<GoviewComponent>>>()
        {
            Result = new PageInfo<List<GoviewComponent>>
            {
                Items = list,
                Total = total
            }
        };
    }

    /// <summary>
    /// 获取组件数据
    /// </summary>
    /// <param name="componentId"></param>
    /// <returns></returns>
    public async Task<Response<GoviewComponent>> GetComponentData(string componentId)
    {
        var data = await Repository.ChangeRepository<SugarRepositiry<GoviewComponent>>().AsQueryable()
            .SingleAsync(a => a.Id == componentId);

        return new Response<GoviewComponent>()
        {
            Result = data
        };
    }

    /// <summary>
    /// 保存组件数据
    /// </summary>
    /// <param name="data"></param>
    /// <returns></returns>
    /// <exception cref="Exception"></exception>
    public async Task<Response<bool>> SaveComponentData(GoviewComponent data)
    {
        // 更新还是保存，  
        var comData = await Repository
            .ChangeRepository<SugarRepositiry<GoviewComponent>>()
            .AsQueryable()
            .SingleAsync(a => a.Id == data.Id);
        bool flag;
        if (comData == null)
        {
            data.Id = Guid.NewGuid().ToString();
            data.CreateUserId = _auth.GetUserId();
            data.CreateTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
            flag = await Repository.ChangeRepository<SugarRepositiry<GoviewComponent>>().InsertAsync(data);
        }
        else
        {
            data.Id = comData.Id;
            flag = await Repository
                .ChangeRepository<SugarRepositiry<GoviewComponent>>()
                .AsUpdateable(data)
                .IgnoreColumns(a => new { a.CreateTime, a.CreateUserId })
                .IgnoreNullColumns()
                .ExecuteCommandAsync() > 0;
        }

        return new Response<bool> { Code = 200, Result = flag, Message = flag ? "数据保存成功" : "数据保存失败" };
    }

    /// <summary>
    /// 删除组件
    /// </summary>
    /// <param name="ids"></param>
    /// <returns></returns>
    public async Task<Response<bool>> DeleteComponent(string ids)
    {
        var idArray = ids.Split(",");
        var flag = await Repository.ChangeRepository<SugarRepositiry<GoviewComponent>>().DeleteByIdsAsync(idArray);
        return new Response<bool> { Code = 200, Result = flag, Message = flag ? "删除成功" : "删除失败" };
    }

    #endregion

    public IList<SysUploadFile> Add(IFormFileCollection files, string groupName)
    {
        if (!_auth.CheckLogin())
        {
            throw new Exception("必需登录才能上传附件");
        }

        var result = new List<SysUploadFile>();
        foreach (var file in files)
        {
            result.Add(Add(file, groupName));
        }

        return result;
    }

    public SysUploadFile Add(IFormFile file, string groupName)
    {
        if (file != null)
        {
            _logger.LogInformation("收到新文件: " + file.FileName);
            _logger.LogInformation("收到新文件: " + file.Length);
        }
        else
        {
            _logger.LogWarning("收到新文件为空");
        }

        if (file != null && file.Length > 0)
        {
            using (var binaryReader = new BinaryReader(file.OpenReadStream()))
            {
                var fileName = Path.GetFileName(file.FileName);
                var data = binaryReader.ReadBytes((int)file.Length);
                SaveFile(fileName, data);
                var filedb = new SysUploadFile
                {
                    Id = SnowFlakeSingle.instance.getID(),
                    FilePath = _dbFilePath,
                    Thumbnail = _dbThumbnail,
                    FileName = fileName,
                    FileSize = file.Length.ToInt(),
                    CreateUserName = _auth.GetUserName(),
                    FileType = Path.GetExtension(fileName),
                    Extension = Path.GetExtension(fileName),
                    CreateTime = DateTime.Now,
                };
                Repository.ChangeRepository<SugarRepositiry<SysUploadFile>>().Insert(filedb);
                var image = new GoviewImage
                {
                    FileId = filedb.Id,
                    GroupName = groupName
                };
                Repository.ChangeRepository<SugarRepositiry<GoviewImage>>().Insert(image);
                return filedb;
            }
        }
        else
        {
            throw new Exception("文件过大");
        }
    }

    /// <summary>
    /// 存储文件，如果是图片文件则生成缩略图
    /// </summary>
    /// <param name="fileName"></param>
    /// <param name="fileBuffers"></param>
    /// <exception cref="Exception"></exception>
    private void SaveFile(string fileName, byte[] fileBuffers)
    {
        string folder = DateTime.Now.ToString("yyyyMMdd");

        //判断文件是否为空
        if (string.IsNullOrEmpty(fileName))
        {
            throw new Exception("文件名不能为空");
        }

        //判断文件是否为空
        if (fileBuffers.Length < 1)
        {
            throw new Exception("文件不能为空");
        }

        var uploadPath = Path.Combine(_filePath, folder);
        _logger.LogInformation("文件写入：" + uploadPath);
        if (!Directory.Exists(uploadPath))
        {
            Directory.CreateDirectory(uploadPath);
        }

        var ext = Path.GetExtension(fileName).ToLower();
        string newName = GenerateId.GenerateOrderNumber() + ext;

        using (var fs = new FileStream(Path.Combine(uploadPath, newName), FileMode.Create))
        {
            fs.Write(fileBuffers, 0, fileBuffers.Length);
            fs.Close();

            //生成缩略图
            if (ext.Contains(".jpg") || ext.Contains(".jpeg") || ext.Contains(".png") || ext.Contains(".bmp") ||
                ext.Contains(".gif"))
            {
                string thumbnailName = GenerateId.GenerateOrderNumber() + ext;
                ImgHelper.MakeThumbnail(Path.Combine(uploadPath, newName), Path.Combine(uploadPath, thumbnailName));
                _dbThumbnail = Path.Combine(folder, thumbnailName);
            }


            _dbFilePath = Path.Combine(folder, newName);
        }
    }

    public IList<SysUploadFile> GetImage(GoViewImagePage req)
    {
        var list = Repository.ChangeRepository<SugarRepositiry<SysUploadFile>>()
            .AsQueryable()
            .InnerJoin<GoviewImage>((a, b) => a.Id.Equals(b.FileId))
            .WhereIF(!string.IsNullOrEmpty(req.GroupName), (a, b) => b.GroupName.Equals(req.GroupName))
            .Select<SysUploadFile>()
            .ToList();
        return list;
    }

    public bool DeleteImage(string ids)
    {
        if (string.IsNullOrEmpty(ids))
        {
            return false;
        }

        var idArray = ids.Split(",").Select(a => a.ToLong());
        // 向goviewimage中查询
        var list = Repository.ChangeRepository<SugarRepositiry<GoviewImage>>()
            .AsQueryable()
            .Where(a => idArray.Contains(a.FileId))
            .Select(a => a.FileId.ToString())
            .ToArray();
        Repository.ChangeRepository<SugarRepositiry<GoviewImage>>()
            .DeleteByIds(list);
        return Repository.ChangeRepository<SugarRepositiry<SysUploadFile>>()
            .DeleteByIds(list);
    }

    public Response<IList<string>> GetImageGroupList()
    {
        var list = Repository.ChangeRepository<SugarRepositiry<GoviewImage>>()
            .AsQueryable()
            .GroupBy(a => a.GroupName)
            .Select(a => a.GroupName)
            .ToList();
        return new Response<IList<string>>
        {
            Result = list
        };
    }

    public string GetParamByKey(string key)
    {
        var result = Repository.ChangeRepository<SugarRepositiry<GoViewParam>>()
            .AsQueryable()
            .Where(a => a.ParamName.Equals(key))
            .Select(a => a.ParamValue)
            .Single();
        return result;
    }

    public bool AddParam(string key, string mainPage)
    {
        var result = new GoViewParam
        {
            ParamName = key,
            ParamValue = mainPage,
            CreateTime = DateTime.Now
        };

        return Repository.ChangeRepository<SugarRepositiry<GoViewParam>>().InsertOrUpdate(result);
    }

    /// <summary>
    /// 保存自定义组件
    /// </summary>
    /// <param name="data"></param>
    /// <returns></returns>
    public async Task<bool> SaveCustomComponent(CustomComponentReq data)
    {
        // 保存
        var record = new GoviewCustomComponent
        {
            Id = Guid.NewGuid().ToString(),
            Content = data.Content,
        };
        return await Repository.ChangeRepository<SugarRepositiry<GoviewCustomComponent>>().InsertAsync(record);
    }


    public async Task<Response<PageInfo<List<GoviewCustomComponent>>>> GetCustomComponentList(PageReq req)
    {
        return new Response<PageInfo<List<GoviewCustomComponent>>>
        {
            Result = new PageInfo<List<GoviewCustomComponent>>
            {
                Items = await Repository.ChangeRepository<SugarRepositiry<GoviewCustomComponent>>()
                    .AsQueryable()
                    .ToPageListAsync(req.page, req.limit),
                Total = await Repository.ChangeRepository<SugarRepositiry<GoviewCustomComponent>>()
                    .AsQueryable()
                    .CountAsync()
            }
        };
    }

    public async Task<bool> DeleteCustomComponent(string ids)
    {
        var idArray = ids.Split(",");
        var result = await Repository.ChangeRepository<SugarRepositiry<GoviewCustomComponent>>()
            .DeleteByIdsAsync(idArray);
        return result;
    }
}