
using Dapper;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using SolarPower.Models;
using SolarPower.Models.PowerStation;
using SolarPower.Models.User;
using SolarPower.Repository.Interface;
using SolarPower.Services.Interface;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Threading.Tasks;

namespace SolarPower.Controllers
{
    public class UserController : MyBaseController<UserController>
    {

        private readonly IUserRepository userRepository;
        private readonly ISendEmailService sendEmailService;
        private readonly IPowerStationRepository powerStationRepository;
        private string logoPath = "/upload/company_logo/";
        public UserController(IUserRepository userRepository,
                              ISendEmailService sendEmailService,
                              IPowerStationRepository powerStationRepository) : base()
        {
            this.userRepository = userRepository;
            this.sendEmailService = sendEmailService;
            this.powerStationRepository = powerStationRepository;
        }

        public IActionResult Index()
        {
            return View();
        }

        /// <summary>
        /// 取得個人資訊
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult<User>> GetPersonalInfo()
        {
            ApiResult<User> apiResult = new ApiResult<User>();

            try
            {
                var user = await userRepository.GetOneAsync(myUser.Id);

                apiResult.Code = "0000";
                apiResult.Data = user;
            }
            catch (Exception exception)
            {
                apiResult.Code = "9999";
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
            }

            apiResult.Msg = errorCode.GetString(apiResult.Code);
            return apiResult;
        }

        /// <summary>
        /// 修改個人資料
        /// </summary>
        /// <param name="post"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult<string>> SavePersonalInfoAsync(PostPersonalInfo post)
        {
            ApiResult<string> apiResult = new ApiResult<string>();

            User user = null;
            try
            {
                user = await userRepository.GetOneAsync(myUser.Id);

                if (user == null)
                {
                    apiResult.Code = "9998";
                    apiResult.Msg = errorCode.GetString(apiResult.Code);
                    return apiResult;
                }

                UpdateUser update = new UpdateUser()
                {
                    Name = post.Name,
                    Email = post.Email,
                    Phone = post.Phone,
                    UpdatedBy = myUser.Id,
                    Id = user.Id
                };

                List<string> properties = new List<string>()
                {
                    "Name",
                    "Email",
                    "Phone",
                    "UpdatedBy",
                    "UpdatedAt",
                    "Id"
                };

                await userRepository.UpdatePersonInfo(update, properties);

                apiResult.Code = "0000";
                apiResult.Msg = "修改成功";
            }
            catch (Exception exception)
            {
                apiResult.Code = "9999";
                string json = System.Text.Json.JsonSerializer.Serialize(post);
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + json);
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
            }

            return apiResult;
        }

        /// <summary>
        /// 變更密碼
        /// </summary>
        /// <param name="post"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult<string>> ChangePasswordAsync(PostChangePassword post)
        {
            ApiResult<string> apiResult = new ApiResult<string>();

            User user = null;
            try
            {
                user = await userRepository.GetOneAsync(myUser.Id);

                if (user == null)
                {
                    apiResult.Code = "9998";
                    apiResult.Msg = errorCode.GetString(apiResult.Code);
                    return apiResult;
                }

                EDFunction edFunction = new EDFunction();

                if (string.Compare(user.Password, edFunction.GetSHA256Encryption(post.OldPassword)) != 0)
                {
                    apiResult.Code = "0001";
                    apiResult.Msg = "密碼錯誤，請重新輸入。";
                    return apiResult;
                }

                if (string.Compare(post.NewPassword, post.AgainPassword) != 0)
                {
                    apiResult.Code = "0001";
                    apiResult.Msg = "新密碼輸入不一致，請重新輸入。";
                    return apiResult;
                }

                UpdatePassword update = new UpdatePassword()
                {
                    Password = edFunction.GetSHA256Encryption(post.NewPassword),
                    UpdatedBy = myUser.Id,
                    Id = user.Id
                };

                List<string> properties = new List<string>()
                {
                    "Password",
                    "UpdatedBy",
                    "UpdatedAt",
                    "Id"
                };

                await userRepository.UpdatePassword(update, properties);

                apiResult.Code = "0000";
                apiResult.Msg = "修改成功";
            }
            catch (Exception exception)
            {
                apiResult.Code = "9999";
                string json = System.Text.Json.JsonSerializer.Serialize(post);
                Logger.LogError("【" + controllerName + "/" + actionName + "】");
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
            }

            return apiResult;
        }

        /// <summary>
        /// 帳號管理列表
        /// </summary>
        /// <param name="post"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ActionResult> UserListAsync(PostUserFilter post)
        {
            ApiResult<List<UserDateTable>> apiResult = new ApiResult<List<UserDateTable>>();

            int totalRecords = 0; //總資料筆數
            int recFilter = 0; //過濾後資料筆數

            List<UserDateTable> users = null;

            try
            {
                users = await userRepository.GetAllByFilterAsync(post);
                totalRecords = users.Count();
                recFilter = users.Count();

                apiResult.Code = "0000";
                apiResult.Data = users;
            }
            catch (Exception exception)
            {
                apiResult.Code = "9999";
                string json = System.Text.Json.JsonSerializer.Serialize(post);
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + json);
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
            }


            apiResult.Msg = errorCode.GetString(apiResult.Code);
            var result = Json(new
            {
                recordsTotal = totalRecords,
                recordsFiltered = recFilter,
                data = apiResult
            });

            return result;
        }

        /// <summary>
        /// 取得單一使用者
        /// </summary>
        /// <param name="guid"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult<SimpleUser>> GetOneUser(int id)
        {
            ApiResult<SimpleUser> apiResult = new ApiResult<SimpleUser>();

            SimpleUser simpleUser = null;

            try
            {
                simpleUser = await userRepository.GetOneSimpleUser(id);

                if (simpleUser == null)
                {
                    apiResult.Code = "9998";
                    apiResult.Msg = errorCode.GetString(apiResult.Code);
                    return apiResult;
                }

                apiResult.Code = "0000";
                apiResult.Data = simpleUser;

            }
            catch (Exception exception)
            {
                apiResult.Code = "9999";
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + "Id=" + id);
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
            }

            apiResult.Msg = errorCode.GetString(apiResult.Code);
            return apiResult;
        }

        /// <summary>
        /// 新增 / 修改 使用者
        /// </summary>
        /// <param name="post"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult<string>> SaveUser(PostUser post)
        {
            ApiResult<string> apiResult = new ApiResult<string>();

            User user = null;

            try
            {
                user = await userRepository.GetOneAsync(post.Id);

                if (user == null)
                {

                    if (post.Id != 0)
                    {
                        apiResult.Code = "9998";
                        apiResult.Msg = errorCode.GetString(apiResult.Code);
                        return apiResult;
                    }

                    #region 新增使用者
                    //判斷帳號 是否已存在
                    var exist = await userRepository.GetOneByAccountAsync(post.Account);
                    if(exist != null)
                    {
                        apiResult.Code = "9986";
                        apiResult.Msg = errorCode.GetString(apiResult.Code);
                        return apiResult;
                    }

                    EDFunction edFunction = new EDFunction();

                    //隨機產生亂數密碼
                    Random random = new Random((int)DateTime.Now.Ticks);
                    const string chars = "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghjkmnpqrstuvwxyz23456789";
                    string random_password = new string(Enumerable.Repeat(chars, 8).Select(s => s[random.Next(chars.Length)]).ToArray());

                    var newPassword = edFunction.GetSHA256Encryption(random_password);

                    user = new User()
                    {
                        CompanyId = post.CompanyId,
                        Name = post.Name,
                        Email = post.Email,
                        Account = post.Account,
                        Password = newPassword,
                        RoleId = post.RoleId,
                        Phone = post.Phone,
                        CreatedBy = myUser.Id,
                    };

                    List<string> properties = new List<string>()
                    {
                        "CompanyId",
                        "Name",
                        "Email",
                        "Account",
                        "Password",
                        "RoleId",
                        "Phone",
                        "CreatedBy",
                    };

                    await userRepository.AddAsync(user, properties);

                    var sendSubject = "新增帳號成功";
                    var sendContent = $"您的新密碼為：{random_password}";

                    List<string> recipientEmails = new List<string>()
                    {
                        user.Email
                    };

                    sendEmailService.Send(recipientEmails, sendSubject, sendContent);

                    apiResult.Code = "0000";
                    apiResult.Msg = "儲存成功";
                    #endregion
                }
                else
                {
                    #region 修改使用者
                    UpdateUser update = new UpdateUser()
                    {
                        Id = post.Id,
                        Name = post.Name,
                        Email = post.Email,
                        Phone = post.Phone,
                        UpdatedBy = myUser.Id,
                    };


                    List<string> properties = new List<string>()
                    {
                        "Id",
                        "Name",
                        "Email",
                        "Phone",
                        "UpdatedBy",
                    };

                    await userRepository.UpdatePersonInfo(update, properties);

                    apiResult.Code = "0000";
                    apiResult.Msg = "儲存成功";
                    #endregion
                }
            }
            catch (Exception exception)
            {
                apiResult.Code = "9999";
                apiResult.Msg = errorCode.GetString(apiResult.Code);
                string json = System.Text.Json.JsonSerializer.Serialize(post);
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + json);
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
            }

            return apiResult;
        }

        /// <summary>
        /// 軟刪除單一使用者
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult<string>> DeleteOneUser(int id)
        {
            ApiResult<string> apiResult = new ApiResult<string>();

            SimpleUser user = null;

            try
            {
                user = await userRepository.GetOneSimpleUser(id);

                if (user == null)
                {
                    apiResult.Code = "9998";
                    apiResult.Msg = errorCode.GetString(apiResult.Code);
                    return apiResult;
                }

                await userRepository.DeleteOne(user.Id);

                apiResult.Code = "0000";
                apiResult.Msg = "刪除成功";
            }
            catch (Exception exception)
            {
                apiResult.Code = "9999";
                apiResult.Msg = errorCode.GetString(apiResult.Code);
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + "Id=" + id);
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
            }

            return apiResult;
        }

        [HttpPost]
        public async Task<ApiResult<List<UserPowerStation>>> GetUserPowerStation(int id)
        {
            ApiResult<List<UserPowerStation>> apiResult = new ApiResult<List<UserPowerStation>>();

            List<UserPowerStation> userPowerStations = null;

            try
            {
                userPowerStations = await userRepository.GetUserPowerStationAsync(id);

                if (userPowerStations == null)
                {
                    apiResult.Code = "9988";
                    apiResult.Msg = errorCode.GetString(apiResult.Code);
                    return apiResult;
                }

                apiResult.Code = "0000";
                apiResult.Data = userPowerStations;
            }
            catch (Exception exception)
            {
                apiResult.Code = "9999";
                apiResult.Msg = errorCode.GetString(apiResult.Code);
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + "Id=" + id);
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
            }

            return apiResult;
        }

        [HttpPost]
        public async Task<ApiResult<string>> DeleteOneUserPowerStation(int id)
        {
            ApiResult<string> apiResult = new ApiResult<string>();

            try
            {
                var userPowerStation = userRepository.GetOneUserPowerStationAsync(id);

                if (userPowerStation == null)
                {
                    apiResult.Code = "9988";
                    apiResult.Msg = errorCode.GetString(apiResult.Code);
                    return apiResult;
                }

                await userRepository.DeleteOneUserPowerStationAsync(id);

                apiResult.Code = "0000";
                apiResult.Msg = "刪除成功";
            }
            catch (Exception exception)
            {
                apiResult.Code = "9999";
                apiResult.Msg = errorCode.GetString(apiResult.Code);
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + "Id=" + id);
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
            }

            return apiResult;
        }

        [HttpPost]
        public async Task<ApiResult<List<UserPowerStation>>> GetUserCompanyPowerStation(int id)
        {
            ApiResult<List<UserPowerStation>> apiResult = new ApiResult<List<UserPowerStation>>();

            SimpleUser user = null;

            try
            {
                user = await userRepository.GetOneSimpleUser(id);

                if (user == null)
                {
                    apiResult.Code = "9998";
                    apiResult.Msg = errorCode.GetString(apiResult.Code);
                    return apiResult;
                }

                var companyPowerStation = await userRepository.GetCompanyPowerStationAsync(user.CompanyId, user.Id);

                apiResult.Code = "0000";
                apiResult.Data = companyPowerStation;
            }
            catch (Exception exception)
            {
                apiResult.Code = "9999";
                apiResult.Msg = errorCode.GetString(apiResult.Code);
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + "Id=" + id);
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
            }

            return apiResult;
        }

        [HttpPost]
        public async Task<ApiResult<string>> SaveUserPowerStation(PostUserPowerStation post)
        {
            ApiResult<string> apiResult = new ApiResult<string>();

            SimpleUser user = null;

            try
            {
                user = await userRepository.GetOneSimpleUser(post.UserId);

                if (user == null)
                {
                    apiResult.Code = "9998";
                    apiResult.Msg = errorCode.GetString(apiResult.Code);
                    return apiResult;
                }

                if (!IsPlatformLayer(myUser.Role.Layer))
                {   //如果身分為公司管理員 或 公司使用者，就只能改自己公司的資料
                    
                    if(user.CompanyId != myUser.CompanyId)
                    {
                        apiResult.Code = "9993";
                        apiResult.Msg = errorCode.GetString(apiResult.Code);
                        return apiResult;
                    }
                }

                List<PowerStationOperationPersonnel> insertOperationPersonnels = new List<PowerStationOperationPersonnel>();

                PowerStationOperationPersonnel operationPersonnel = new PowerStationOperationPersonnel();
                operationPersonnel.PowerStationId = post.PowerStationId;
                operationPersonnel.UserId = post.UserId;
                operationPersonnel.CreatedBy = myUser.Id;

                insertOperationPersonnels.Add(operationPersonnel);

                List<string> operationPersonnelProperties = new List<string>()
                {
                    "PowerStationId",
                    "UserId",
                    "CreatedBy",
                };

                await powerStationRepository.AddOperationPersonnelAsync(insertOperationPersonnels, operationPersonnelProperties);

                apiResult.Code = "0000";
                apiResult.Msg = "新增成功";
            }
            catch (Exception exception)
            {
                apiResult.Code = "9999";
                apiResult.Msg = errorCode.GetString(apiResult.Code);
                string json = System.Text.Json.JsonSerializer.Serialize(post);
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + json);
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
            }

            return apiResult;
        }
    }
}
