using FrontendWebApi.Models;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Repository.BackendRepository.Interface;
using Repository.FrontendRepository.Interface;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Threading.Tasks;

namespace FrontendWebApi.ApiControllers
{
    public class ReceiveDataDeliveryController : Controller
    {
        private readonly IBackendRepository backendRepository;
        private readonly IFrontendRepository frontendRepository;
        private readonly ILogger<ReceiveDataDeliveryController> logger;
        private string fileSaveAsPath = "";

        public class ReceiveData
        {
            public int Id { get; set; }
            public string TargetTable { get; set; }
            public string Mode { get; set; }
            public string TargetData { get; set; }
            public List<FileInfo> FileInfos { get; set; }
        }
        public class FileInfo
        {
            public string Folder { get; set; }
            public string OriginalFileName { get; set; }
            public string FileName { get; set; }
            public IFormFile File { get; set; }
        }

        public ReceiveDataDeliveryController
        (
            ILogger<ReceiveDataDeliveryController> logger,
            IBackendRepository backendRepository,
            IFrontendRepository frontendRepository,
            IConfiguration configuration
        )
        {
            this.logger = logger;
            this.backendRepository = backendRepository;
            this.frontendRepository = frontendRepository;

            fileSaveAsPath = configuration.GetValue<string>("FileSaveASPath");
        }

        [HttpPost]
        [Route("api/ReceiveDataDelivery/GetData")]
        public async Task<ActionResult<ApiResult<string>>> GetData(ReceiveData receiveData)
        {
            ApiResult<string> apiResult = new ApiResult<string>();

            //logger.LogInformation("傳入的內容:{0}", System.Text.Json.JsonSerializer.Serialize(receiveData));

            var gotoListDictionary = new List<string>() { "insert_list", "update_list", "purge_specify_insert", "purge_all_insert" };

            try
            {
                //解析要記錄的資料
                if (!string.IsNullOrEmpty(receiveData.TargetData))
                {
                    Dictionary<string, object> targetDataDic = new Dictionary<string, object>();
                    List<Dictionary<string, object>> targetDataListDic = new List<Dictionary<string, object>>();

                    var json = receiveData.TargetData.ToString();
                    if (!gotoListDictionary.Contains(receiveData.Mode.ToLower()))
                    {
                        targetDataDic = JsonConvert.DeserializeObject<Dictionary<string, object>>(receiveData.TargetData);
                    }
                    else
                    {
                        targetDataListDic = JsonConvert.DeserializeObject<List<Dictionary<string, object>>>(receiveData.TargetData);
                    }

                    //找出pk,確保資料派送要儲存的紀錄
                    var pk_sql = $@"SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE 
                                    WHERE TABLE_SCHEMA = 'taipei_dome'
                                        AND TABLE_NAME = @TargetTable
                                    ORDER BY COLUMN_NAME";
                    var pks = await frontendRepository.GetAllAsync<string>(pk_sql, new { TargetTable = receiveData.TargetTable });

                    switch (receiveData.Mode.ToLower())
                    {
                        case "insert": //儲存資料(單筆)
                            await frontendRepository.AddOneFromDataDelivery(receiveData.Id, pks ,targetDataDic, receiveData.TargetTable);
                            break;

                        case "insert_list": //儲存資料(多筆)
                            await frontendRepository.AddMutiFromDataDelivery(receiveData.Id, pks, targetDataListDic, receiveData.TargetTable);
                            break;

                        case "update": //更新資料
                        case "delete": //軟刪除資料
                            await frontendRepository.UpdateOneFromDataDelivery(receiveData.Id, pks, targetDataDic, receiveData.TargetTable);
                            break;

                        case "update_list":
                            await frontendRepository.UpdateListFromDataDelivery(receiveData.Id, pks, targetDataListDic, receiveData.TargetTable);
                            break;

                        case "purge_specify_insert": //依據條件實際刪除再新增
                            await frontendRepository.PurgeSpecifyInsertFromDataDelivery(receiveData.Id, pks, targetDataListDic, receiveData.TargetTable);
                            break;

                        case "purge_all_insert": //刪除全部再新增
                            await frontendRepository.PurgeAllInsertFromDataDelivery(receiveData.Id, pks, targetDataListDic, receiveData.TargetTable);
                            break;

                        case "purge": //實際刪除資料
                            await frontendRepository.PurgeOneFromDataDelivery(receiveData.Id, pks, targetDataDic, receiveData.TargetTable);
                            break;
                    }
                }

                if (receiveData.FileInfos != null && receiveData.FileInfos.Count > 0)
                {
                    //儲存檔案
                    FolderFunction folderFunction = new FolderFunction();
                    foreach (var fileInfo in receiveData.FileInfos)
                    {
                        //刪除原本檔案
                        if (!string.IsNullOrEmpty(fileInfo.OriginalFileName))
                        {
                            folderFunction.DeleteFile(Path.Combine(fileSaveAsPath, fileInfo.Folder, fileInfo.OriginalFileName));
                        }

                        //判斷資料夾是否存在
                        folderFunction.CreateFolder(Path.Combine(fileSaveAsPath, fileInfo.Folder), 0);

                        var fullPath = Path.Combine(fileSaveAsPath, fileInfo.Folder, fileInfo.FileName);

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

                apiResult.Code = "0000";
            }
            catch (Exception exception)
            {
                apiResult.Code = "9999";
                logger.LogError("【ReceiveDataDelivery/GetData】" + exception.ToString());
                return BadRequest(apiResult);
            }
            return Ok(apiResult);
        }
    }
}