using FrontendWebApi.Models;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Repository.BackendRepository.Implement;
using System.Collections.Generic;
using System.Threading.Tasks;
using System;
using System.Linq;
using System.Web;
using Repository.BackendRepository.Interface;
using Repository.FrontendRepository.Interface;
using System.IO;
using static Microsoft.Extensions.Logging.EventSource.LoggingEventSource;

namespace FrontendWebApi.ApiControllers
{
    //[Route("api/[controller]")]
    //[ApiController]
    public class GraphManageController : MyBaseApiController<GraphManageController>
    {
        private readonly IBackendRepository backendRepository;
        private readonly IFrontendRepository frontendRepository;
        private string graph_manage_layer = "graph_manage_layer";
        private string graph_manage_layer1 = "graph_manage_layer1";
        private string graph_manage_layer2 = "graph_manage_layer2";

        private string graphManageFileSaveAsPath = "";

        public GraphManageController(IBackendRepository backendRepository, IFrontendRepository frontendRepository)
        {
            this.backendRepository = backendRepository;
            this.frontendRepository = frontendRepository;
            graphManageFileSaveAsPath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "upload", "graph_manage");
        }

       
        /// <summary>
        /// 圖資類別列表
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult<List<GraphManageTree>>> GraphManageTreeList()
        {
            ApiResult<List<GraphManageTree>> apiResult = new ApiResult<List<GraphManageTree>>();
            List<GraphManageTree> gmTree = new List<GraphManageTree>();

            try
            {
                var sqlString = @$"select * from graph_manage_tree 
                                    where deleted = 0
                                    order by id asc";

                gmTree = await backendRepository.GetAllAsync<GraphManageTree>(sqlString);

                apiResult.Code = "0000";
                apiResult.Data = gmTree;
            }
            catch (Exception exception)
            {
                apiResult.Code = "9999";
                apiResult.Msg = "系統內部錯誤,請聯絡管理者。";
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
            }

            return apiResult;
        }

        /// <summary>
        /// 新增圖資類別
        /// </summary>
        /// <param name="gv"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult<string>> SaveGraphManageTree([FromBody] GraphManageTree gmTree)
        {
            ApiResult<string> apiResult = new ApiResult<string>();

            try
            {
                Dictionary<string, object> newGmTree = new Dictionary<string, object>();
                var system_priority = backendRepository.GetOneAsync<string>("select priority from graph_manage_tree where deleted = 0 order by priority desc limit 1").Result;
                newGmTree.Add("@deleted", 0);
                newGmTree.Add("@name", gmTree.name);
                newGmTree.Add("@parent_id", gmTree.parent_id);
                newGmTree.Add("@remark", "圖資管理-" + gmTree.name);
                newGmTree.Add("@priority", Int32.Parse(system_priority) + 1);
              
                newGmTree.Add("@created_by", myUser.userinfo_guid);
                newGmTree.Add("@created_at", DateTime.Now);

                var id = await backendRepository.AddOneByCustomTableReturnId(newGmTree, "graph_manage_tree");
                apiResult.Code = "0000";
                apiResult.Data = id.ToString();
            }
            catch (Exception exception)
            {
                apiResult.Code = "9999";
                apiResult.Msg = "系統內部錯誤,請聯絡管理者。";
                string json = System.Text.Json.JsonSerializer.Serialize(gmTree);
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + json);
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
            }

            return apiResult;
        }

        /// <summary>
        /// 編輯圖資類別
        /// </summary>
        /// <param name="gv"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult<string>> EditGraphManageTree([FromBody] GraphManageTree gmTree)
        {
            ApiResult<string> apiResult = new ApiResult<string>();
            var gm = await backendRepository.GetOneAsync<GraphInsInfo>("select * from graph_manage_tree where id = @id and deleted = 0", new { @id = gmTree.id });

            if (gm == null)
            {
                apiResult.Code = "0002";
                apiResult.Data = "無法找到圖資";
                return apiResult;
            }

            try
            {
                Dictionary<string, object> newGmTree = new Dictionary<string, object>();
                
                newGmTree.Add("@name", gmTree.name);
                newGmTree.Add("@remark", "圖資管理-" + gmTree.name);
                newGmTree.Add("@updated_by", myUser.userinfo_guid);
                newGmTree.Add("@updated_at", DateTime.Now);

                await backendRepository.UpdateOneByCustomTable(newGmTree, "graph_manage_tree", "id = " + gmTree.id);
                apiResult.Code = "0000";
                apiResult.Data = "編輯成功";
            }
            catch (Exception exception)
            {
                apiResult.Code = "9999";
                apiResult.Msg = "系統內部錯誤,請聯絡管理者。";
                string json = System.Text.Json.JsonSerializer.Serialize(gmTree);
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + json);
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
            }

            return apiResult;
        }

        /// <summary>
        /// 刪除圖資類別
        /// </summary>
        /// <param name="gv"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult<string>> DelGraphManageTree([FromBody] GraphManageTree gmTree)
        {
            ApiResult<string> apiResult = new ApiResult<string>();

            try
            {
                var sqlString = @$"UPDATE graph_manage_tree SET deleted = 1, updated_at = @time, updated_by = @user WHERE id = @id";

                var param = new { @id = gmTree.id, @time = DateTime.Now, @user = myUser.userinfo_guid };

                await backendRepository.ExecuteSql(sqlString, param);
                apiResult.Code = "0000";
                apiResult.Data = "刪除成功";
            }
            catch (Exception exception)
            {
                apiResult.Code = "9999";
                apiResult.Msg = "系統內部錯誤,請聯絡管理者。";
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
            }

            return apiResult;
        }

        [HttpPost]
        public async Task<ApiResult<List<GraphList>>> GraManList([FromBody] GraphInfo gi)
        {
            ApiResult<List<GraphList>> apiResult = new ApiResult<List<GraphList>>();
            List<GraphList> graManList = new List<GraphList>();
            try
            {
                var param = new { layer_id = gi.layer_id , graph_manage_layer = graph_manage_layer, keyWord = gi.keyWord };
                if (gi.keyWord != null && !string.IsNullOrEmpty(gi.keyWord))
                {
                    graManList = await backendRepository.GetAllAsync<GraphList>(@$"SELECT gm.*
                                    FROM graph_manage gm
                                    JOIN graph_manage_tree gmtree ON gmtree.id = @layer_id and gmtree.deleted = 0
                                    WHERE gm.deleted = 0
                                            AND (gm.code like '%{gi.keyWord}%' OR gm.name like '%@keyWord%' OR gm.oriOrgName like '%@keyWord%' OR gm.donOrgName like '%@keyWord%')
                                    ORDER BY gm.priority, gm.created_at desc", param);
                }
                else
                {
                    var sqlString = @$"SELECT gm.*
                                    FROM graph_manage gm
                                    JOIN graph_manage_tree gmtree ON gmtree.id = @layer_id and gmtree.deleted = 0
                                    WHERE gm.deleted = 0 and gm.layer_id = @layer_id
                                    ORDER BY gm.priority, gm.created_at desc";

                    graManList = await backendRepository.GetAllAsync<GraphList>(sqlString, param);
                }

                apiResult.Code = "0000";
                apiResult.Data = graManList;
            }
            catch (Exception exception)
            {
                apiResult.Code = "9999";
                apiResult.Msg = "系統內部錯誤,請聯絡管理者。";
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
            }

            return apiResult;
        }

        [HttpPost]
        public async Task<ApiResult<GraphList>> GraManRead([FromBody] GraphInfo gi)
        {
            ApiResult<GraphList> apiResult = new ApiResult<GraphList>();
            GraphList graManList = new GraphList();
            try
            {
                var sqlString = @$"SELECT *
                                    FROM graph_manage gm
                                    JOIN graph_manage_tree gmtree ON convert(gmtree.id, nchar) = gm.layer_id and gmtree.deleted = 0
                                    WHERE gm.id = @id AND gm.deleted = 0
                                    ORDER BY gm.priority, gm.created_at desc";

                var param = new { @id = gi.id, @graph_manage_layer = graph_manage_layer };

                graManList = await backendRepository.GetOneAsync<GraphList>(sqlString, param);

                if (graManList == null)
                {
                    apiResult.Code = "0002";
                    apiResult.Msg = "找不到圖資";
                    return apiResult;
                }

                apiResult.Code = "0000";
                apiResult.Data = graManList;
            }
            catch (Exception exception)
            {
                apiResult.Code = "9999";
                apiResult.Msg = "系統內部錯誤,請聯絡管理者。";
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
            }

            return apiResult;
        }

        [HttpPost]
        public async Task<ApiResult<string>> DelOneGraMan([FromBody] GraphInfo gi)
        {
            ApiResult<string> apiResult = new ApiResult<string>();

            try
            {
                var sqlString = @$"UPDATE graph_manage SET deleted = 1, updated_at = @time, updated_by = @user WHERE id = @id";

                var param = new { @id = gi.id, @time = DateTime.Now, @user = myUser.userinfo_guid };

                await backendRepository.ExecuteSql(sqlString, param);
                apiResult.Code = "0000";
                apiResult.Data = "刪除成功";
            }
            catch (Exception exception)
            {
                apiResult.Code = "9999";
                apiResult.Msg = "系統內部錯誤,請聯絡管理者。";
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
            }

            return apiResult;
        }

        [HttpPost]
        public async Task<ApiResult<string>> EdtOneGraMan([FromForm] GraphInsInfo gii)
        {
            ApiResult<string> apiResult = new ApiResult<string>();

            try
            {
                if (gii.oriOrgName == "null")
                {
                    gii.oriOrgName = null;
                }
                if (gii.donOrgName == "null")
                {
                    gii.donOrgName = null;
                }
                if (gii.oriSavName == "null")
                {
                    gii.oriSavName = null;
                }
                if (gii.donSavName == "null")
                {
                    gii.donSavName = null;
                }
                var sWhere = $@"deleted = 0 and id != @id and code = @code and layer_id = @layer_id";
                var gm = await backendRepository.GetOneAsync<GraphInsInfo>("graph_manage", sWhere, new { @id = gii.id, @code = gii.code, @layer_id = gii.layer_id});

                if (gm != null)
                {
                    apiResult.Code = "0002";
                    apiResult.Data = "無法找到圖資";
                    return apiResult;
                }

                sWhere = @$"deleted = 0 AND id = @id";
                gm = await backendRepository.GetOneAsync<GraphInsInfo>("graph_manage", sWhere, new { @id = gii.id });

                if (gm == null)
                {
                    apiResult.Code = "0001";
                    apiResult.Data = "無法找到圖資";
                    return apiResult;
                }

                Dictionary<string, object> graph_manage = new Dictionary<string, object>();

                //edit file
                //原設計圖修改
                var new_guid = Guid.NewGuid();
                long? fileSize = gm.oriSize ?? null;
                //刪除原本檔案
                if (gm.oriSavName != null && gii.oriSavName != gm.oriSavName)
                {
                    FolderFunction folderFunction = new FolderFunction();
                    folderFunction.DeleteFile(Path.Combine(graphManageFileSaveAsPath, gm.oriSavName));
                    fileSize = null;
                }

                string fileName = gii.oriSavName ?? null;
                
                if (gii.oriOrgName != null && gii.oriFile != null)
                {
                    fileName = new_guid + "." + gii.oriOrgName.Split('.')[1];

                    var fullPath = Path.Combine(graphManageFileSaveAsPath, fileName);

                    using (var stream = new FileStream(fullPath, FileMode.Create))
                    {
                        gii.oriFile.CopyTo(stream);
                    }
                    fileSize = gii.oriFile.Length;
                    
                }

                graph_manage.Add("@oriSize", fileSize);
                graph_manage.Add("@oriOrgName", gii.oriOrgName);
                graph_manage.Add("@oriSavName", fileName);

                fileName = gii.donSavName ?? null;
                //竣工圖修改
                new_guid = Guid.NewGuid();
                fileSize = gm.donSize ?? null;
                //刪除原本檔案
                if (gm.donSavName != null && gii.donSavName != gm.donSavName)
                {
                    var folderFunction = new FolderFunction();
                    folderFunction.DeleteFile(Path.Combine(graphManageFileSaveAsPath, gm.donSavName));
                    fileSize = null;
                }

                if (gii.donOrgName != null && gii.donFile != null)
                {
                    fileName = new_guid + "." + gii.donOrgName.Split('.')[1];

                    var fullPath = Path.Combine(graphManageFileSaveAsPath, fileName);

                    using (var stream = new FileStream(fullPath, FileMode.Create))
                    {
                        gii.donFile.CopyTo(stream);
                    }
                    fileSize = gii.donFile.Length;
                }

                graph_manage.Add("@donSize", fileSize);
                graph_manage.Add("@donOrgName", gii.donOrgName);
                graph_manage.Add("@donSavName", fileName);

                graph_manage.Add("@code", gii.code);
                graph_manage.Add("@name", gii.name);
                //graph_manage.Add("@main_system_tag", gii.main_system_tag);
                //graph_manage.Add("@sub_system_tag", gii.sub_system_tag);
                graph_manage.Add("@layer_id", gii.layer_id);
                graph_manage.Add("@updated_at", DateTime.Now);
                graph_manage.Add("@updated_by", myUser.userinfo_guid);
                //graph_manage.Add("@priority", gii.priority);

                await backendRepository.UpdateOneByCustomTable(graph_manage, "graph_manage", "id = " + gii.id);
                apiResult.Code = "0000";
                apiResult.Data = "修改成功";
            }
            catch (Exception exception)
            {
                apiResult.Code = "9999";
                apiResult.Msg = "系統內部錯誤,請聯絡管理者。";
                string json = System.Text.Json.JsonSerializer.Serialize(gii);
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + json);
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
            }

            return apiResult;
        }

        [HttpPost]
        public async Task<ApiResult<string>> SaveGraMan([FromForm] GraphInsInfo gii)
        {
            ApiResult<string> apiResult = new ApiResult<string>();

            try
            {
                if (gii.oriOrgName == "null") {
                    gii.oriOrgName = null;
                }
                if (gii.donOrgName == "null")
                {
                    gii.donOrgName = null;
                }

                var sWhere = @$"deleted = 0 AND code = @code AND layer_id = @layer_id";
                var gm = await backendRepository.GetOneAsync<GraphInsInfo>("graph_manage", sWhere, new { @code = gii.code, @layer_id = gii.layer_id});

                if (gm != null)
                {
                    apiResult.Code = "0002";
                    apiResult.Data = "已有相同的編碼";
                    return apiResult;
                }

                Dictionary<string, object> graph_manage = new Dictionary<string, object>();
                
                //save file
                if (gii.oriOrgName != null || gii.donOrgName != null)
                {
                    if (!System.IO.Directory.Exists(graphManageFileSaveAsPath))
                        System.IO.Directory.CreateDirectory(graphManageFileSaveAsPath);

                    if (gii.oriOrgName != null)
                    {
                        var new_guid = Guid.NewGuid();

                        var fileName = new_guid + "." + gii.oriOrgName.Split('.')[1];

                        var fullPath = Path.Combine(graphManageFileSaveAsPath, fileName);

                        using (var stream = new FileStream(fullPath, FileMode.Create))
                        {
                            gii.oriFile.CopyTo(stream);
                        }

                        graph_manage.Add("@oriSize", gii.oriFile.Length);
                        graph_manage.Add("@oriOrgName", gii.oriOrgName);
                        graph_manage.Add("@oriSavName", fileName);
                    }

                    if (gii.donOrgName != null)
                    {
                        var new_guid = Guid.NewGuid();

                        var fileName = new_guid + "." + gii.donOrgName.Split('.')[1];

                        var fullPath = Path.Combine(graphManageFileSaveAsPath, fileName);

                        using (var stream = new FileStream(fullPath, FileMode.Create))
                        {
                            gii.donFile.CopyTo(stream);
                        }

                        graph_manage.Add("@donSize", gii.donFile.Length);
                        graph_manage.Add("@donOrgName", gii.donOrgName);
                        graph_manage.Add("@donSavName", fileName);
                    }
                }

                var newPriority = await backendRepository.GetCurrentPriority("graph_manage");
                graph_manage.Add("@code", gii.code);
                //graph_manage.Add("@main_system_tag", gii.main_system_tag);
                //graph_manage.Add("@sub_system_tag", gii.sub_system_tag);
                graph_manage.Add("@layer_id", gii.layer_id);
                graph_manage.Add("@name", gii.name);
                graph_manage.Add("@deleted", 0);
                graph_manage.Add("@priority", newPriority + 1);
                graph_manage.Add("@created_by", myUser.userinfo_guid);
                graph_manage.Add("@created_at", DateTime.Now);

                await backendRepository.AddOneByCustomTable(graph_manage, "graph_manage");
                apiResult.Code = "0000";
                apiResult.Data = "新增成功";
            }
            catch (Exception exception)
            {
                apiResult.Code = "9999";
                apiResult.Msg = "系統內部錯誤,請聯絡管理者。";
                string json = System.Text.Json.JsonSerializer.Serialize(gii);
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + json);
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
            }

            return apiResult;
        }

    }
}