using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using SolarPower.Models;
using SolarPower.Models.Company;
using SolarPower.Models.Role;
using SolarPower.Repository.Interface;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;

namespace SolarPower.Controllers
{
    public class CompanyController : MyBaseController<CompanyController>
    {
        private readonly ICompanyRepository companyRepository;
        private readonly IRoleRepository roleRepository;
        private string logoPath = "/upload/company_logo/";
        private string logoSaveAsPath = "";

        public CompanyController(
            ICompanyRepository companyRepository,
            IRoleRepository roleRepository
            ) : base()
        {
            this.companyRepository = companyRepository;
            this.roleRepository = roleRepository;

            logoSaveAsPath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "upload", "company_logo");
        }

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

        /// <summary>
        /// 取得下拉式公司選單，須為Deleted: 0
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public async Task<ApiResult<List<CompanySelectItemList>>> GetCompanySelectOptionListAsync()
        {
            ApiResult<List<CompanySelectItemList>> apiResult = new ApiResult<List<CompanySelectItemList>>();

            try
            {
                var companySelectItemLists = new List<CompanySelectItemList>();

                if (!IsPlatformLayer(myUser.Role.Layer))
                {
                    companySelectItemLists = await companyRepository.GetCompanySelectOptionListAsync(myUser.CompanyId);
                }
                else
                {
                    companySelectItemLists = await companyRepository.GetCompanySelectOptionListAsync(0);
                }

                apiResult.Code = "0000";
                apiResult.Data = companySelectItemLists;
            }
            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<ActionResult> CompanyListAsync(PostCompanyFilter post)
        {
            ApiResult<List<CompanyDataTable>> apiResult = new ApiResult<List<CompanyDataTable>>();

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

            List<CompanyDataTable> companies = null;

            try
            {

                if (!IsPlatformLayer(myUser.Role.Layer))
                {   //如果身分為公司管理員 或 公司使用者，就只能看自己公司的資料
                    post.SelectedCompanyId = myUser.CompanyId;
                }

                companies = await companyRepository.GetAllByFilterAsync(post);

                foreach (var company in companies)
                {
                    //替換logo src
                    if (!string.IsNullOrEmpty(company.Logo))
                    {
                        company.Logo = logoPath + company.Logo;
                    }
                    else
                    {
                        company.Logo = logoPath + "default.png";
                    }

                    //找出當前狀態正常使用者人數
                    var registerNumber = await companyRepository.GetNormalUserNumberByCompanyIdAsync(company.Id);

                    company.RegisterRatio = registerNumber.ToString() + " / " + company.RegisterUpperLimit.ToString();

                    if (IsPlatformLayer(myUser.Role.Layer))
                    {   //平台 可以使用
                        if(company.Id == 1)
                        {   //平台公司不能被刪
                            company.Function = @"
                                <button type='button' class='btn btn-success btn-pills waves-effect waves-themed company-auth-btn'>權限池</button>
                                <button type='button' class='btn btn-primary btn-pills waves-effect waves-themed edit-btn'>修改</button>";
                        }
                        else
                        {
                            company.Function = @"
                                <button type='button' class='btn btn-success btn-pills waves-effect waves-themed company-auth-btn'>權限池</button>
                                <button type='button' class='btn btn-primary btn-pills waves-effect waves-themed edit-btn'>修改</button>
                                <button type='button' class='btn btn-danger btn-pills waves-effect waves-themed del-btn'>刪除</button>";
                        }
                    }
                    else
                    {
                        company.Function = @"
                            <button type='button' class='btn btn-primary btn-pills waves-effect waves-themed edit-btn'>修改</button>";
                    }
                }
                totalRecords = companies.Count();
                recFilter = companies.Count();

                apiResult.Code = "0000";
                apiResult.Data = companies;
            }
            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="id"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult<Company>> GetOneCompany(int id)
        {
            ApiResult<Company> apiResult = new ApiResult<Company>();

            Company company = null;

            try
            {
                company = await companyRepository.GetOneAsync(id);

                if (company == null)
                {
                    apiResult.Code = "9996";
                    apiResult.Msg = errorCode.GetString(apiResult.Code);
                    return apiResult;
                }
                else if (company.Id != myUser.CompanyId)
                {
                    if (!IsPlatformLayer(myUser.Role.Layer))
                    {
                        apiResult.Code = "9993";
                        apiResult.Msg = errorCode.GetString(apiResult.Code);
                        return apiResult;
                    }
                }

                //替換logo src
                if (!string.IsNullOrEmpty(company.Logo))
                {
                    company.Logo = logoPath + company.Logo;
                }
                else
                {
                    company.Logo = logoPath + "default.png";
                }

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

            }
            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>> SaveCompany([FromForm] PostCompany post)
        {
            ApiResult<string> apiResult = new ApiResult<string>();

            Company company = null;

            try
            {
                company = await companyRepository.GetOneAsync(post.Id);

                if (company == null)
                {

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

                    #region 新增公司

                    //先檢查統編是否已被使用
                    var exist = await companyRepository.GetOneNormalSimpleCompanyByTaxIDNumber(post.TaxIDNumber);

                    if (exist != null)
                    {
                        apiResult.Code = "9995";
                        apiResult.Msg = errorCode.GetString(apiResult.Code);
                        return apiResult;
                    }

                    company = new Company()
                    {
                        Name = post.Name,
                        TaxIDNumber = post.TaxIDNumber,
                        Phone = post.Phone,
                        Address = post.Address,
                        RegisterUpperLimit = post.RegisterUpperLimit,
                        CreatedBy = myUser.Id
                    };

                    List<string> properties = new List<string>()
                    {
                        "Name",
                        "TaxIDNumber",
                        "Phone",
                        "Address",
                        "CreatedBy",
                    };

                    if (IsPlatformLayer(myUser.Role.Layer))
                    {   //超級使用者 或 平台人員可以修改 公司的註冊上限人數
                        properties.Add("RegisterUpperLimit");
                    }

                    var id = await companyRepository.AddOneAsync(company, properties);

                    UpdateCompany updateCompany;

                    #region 處理公司Logo圖片
                    if (post.LogoFile != null)
                    {
                        var split = post.LogoFile.FileName.Split(".");
                        var fileName = id + "." + split[split.Length - 1];

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

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

                        updateCompany = new UpdateCompany()
                        {
                            Id = id,
                            Logo = fileName
                        };

                        properties = new List<string>()
                        {
                            "Id",
                            "Logo"
                        };

                        await companyRepository.UpdateCompany(updateCompany, properties);
                    }
                    #endregion

                    #region 幫別間公司新增"公司管理員"之角色
                    Role role = new Role()
                    {
                        CompanyId = id,
                        Name = "公司管理員",
                        Layer = 2,
                        CreatedBy = myUser.Id,
                    };

                    List<string> roleProperties = new List<string>()
                    {
                        "CompanyId",
                        "Name",
                        "Layer",
                        "CreatedBy",
                    };


                    var roleId = await roleRepository.AddOneAsync(role, roleProperties);
                    #endregion

                    #region 幫別間公司加入所有權限
                    var companyAuths = (await companyRepository.GetCompanyAuthByCompanyId(id)).Where(x=> x.CheckAuth == 0).Select(x => x.AuthCode).ToList();
                    
                    List<CompanyAuth> insertCompanyAuths = new List<CompanyAuth>();
                    foreach (var checkAuth in companyAuths)
                    {
                        CompanyAuth companyAuth = new CompanyAuth();
                        companyAuth.CompanyId = id;
                        companyAuth.AuthCode = checkAuth;
                        companyAuth.CreatedBy = myUser.Id;

                        insertCompanyAuths.Add(companyAuth);
                    }

                    List<string> companyAuthProperties = new List<string>()
                    {
                        "CompanyId",
                        "AuthCode",
                        "CreatedBy",
                    };

                    await companyRepository.AddCompanyAuthAsync(insertCompanyAuths, companyAuthProperties);
                    #endregion

                    #region 幫別間公司管理員加入所有權限
                    List<RoleAuth> roleAuths = new List<RoleAuth>();

                    foreach (var checkAuth in companyAuths)
                    {
                        RoleAuth roleAuth = new RoleAuth();
                        roleAuth.Id = roleId;
                        roleAuth.AuthCode = checkAuth;
                        roleAuth.CreatedBy = myUser.Id;

                        roleAuths.Add(roleAuth);
                    }

                    List<string> roleAuthProperties = new List<string>()
                    {
                        "Id",
                        "AuthCode",
                        "CreatedBy",
                    };

                    await roleRepository.AddRoleAuthAsync(roleAuths, roleAuthProperties);
                    #endregion


                    #region 新增公司DB及Table，公司DB編號規則 solar_com_(公司編號共四碼)，ex：solar_com0001

                    var siteDBFormat = "solar_com{0}";

                    var siteDB = String.Format(siteDBFormat, id.ToString().Trim().PadLeft(4, '0'));
                    //修改
                    updateCompany = new UpdateCompany()
                    {
                        Id = id,
                        SiteDB = siteDB,
                    };

                    properties = new List<string>()
                    {
                        "Id",
                        "SiteDB"
                    };

                    await companyRepository.UpdateCompany(updateCompany, properties);

                    await companyRepository.CreatCompanyDB(siteDB);
                    #endregion

                    apiResult.Code = "0000";
                    apiResult.Msg = "儲存成功";
                    #endregion
                }
                else
                {
                    #region 修改公司

                    //先檢查統編是否已被使用
                    var exist = await companyRepository.GetOneNormalSimpleCompanyByTaxIDNumber(post.TaxIDNumber);
                    if (exist != null && exist.Id != company.Id)
                    {
                        apiResult.Code = "9995";
                        apiResult.Msg = errorCode.GetString(apiResult.Code);
                        return apiResult;
                    }

                    UpdateCompany update = new UpdateCompany()
                    {
                        Id = post.Id,
                        Name = post.Name,
                        TaxIDNumber = post.TaxIDNumber,
                        Phone = post.Phone,
                        Address = post.Address,
                        RegisterUpperLimit = post.RegisterUpperLimit,
                        UpdatedBy = myUser.Id,
                    };

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

                    if (IsPlatformLayer(myUser.Role.Layer))
                    {   //平台人員可以修改 公司的註冊上限人數
                        properties.Add("RegisterUpperLimit");
                    }

                    await companyRepository.UpdateCompany(update, properties);

                    //處裡公司Logo圖片
                    if (post.LogoFile != null)
                    {
                        var split = post.LogoFile.FileName.Split(".");
                        var fileName = company.Id + "." + split[split.Length - 1];

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

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

                        update = new UpdateCompany()
                        {
                            Id = company.Id,
                            Logo = fileName
                        };

                        properties = new List<string>()
                        {
                            "Id",
                            "Logo"
                        };

                        await companyRepository.UpdateCompany(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>> DeleteOneCompany(int id)
        {
            ApiResult<string> apiResult = new ApiResult<string>();

            Company company = null;

            try
            {
                company = await companyRepository.GetOneCompany(id);

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

                await companyRepository.DeleteOne(company.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;
        }

        /// <summary>
        /// 透過公司編號，取得公司權限池
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<ActionResult> GetCompanyAuthByCompanyId(int id)
        {
            ApiResult<List<CompanyAuthDataTable>> apiResult = new ApiResult<List<CompanyAuthDataTable>>();

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

            List<CompanyAuthDataTable> companyAuths = null;

            try
            {
                companyAuths = await companyRepository.GetCompanyAuthByCompanyId(id);

                totalRecords = companyAuths.Count();
                recFilter = companyAuths.Count();

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

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

            return result;
        }

        public async Task<ApiResult<string>> SaveCompanyAuth(PostCompanyAuth post)
        {
            ApiResult<string> apiResult = new ApiResult<string>();

            Company company = null;

            try
            {
                company = await companyRepository.GetOneAsync(post.SelectedCompanyId);

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

                List<CompanyAuthDataTable> origCompanyAuths = null; //原先的公司權限池

                origCompanyAuths = await companyRepository.GetCompanyAuthByCompanyId(post.SelectedCompanyId);

                origCompanyAuths = origCompanyAuths.Where(x => x.CheckAuth == 1).ToList();

                //判斷新進來的資料是否要歸類到新增 or 刪除
                #region 刪除公司權限池

                //找出要刪除的
                List<CompanyAuth> deletedCompanyAuthStrs = origCompanyAuths.Where(x => !post.CheckAuths.Contains(x.AuthCode)).Select(x => new CompanyAuth { CompanyId = company.Id, AuthCode = x.AuthCode }).ToList();

                //刪除權限池
                await companyRepository.PurgeCompanyAuth(deletedCompanyAuthStrs);

                //同時刪除該公司底下擁有這些權限的角色
                await companyRepository.PurgeCompanyRoleAuth(company.Id, deletedCompanyAuthStrs);

                #endregion

                #region 新增公司權限池

                //找出要新增的
                if (post.CheckAuths != null)
                {
                    List<string> insertCompanyAuthStrs = post.CheckAuths.Where(x => !origCompanyAuths.Select(y => y.AuthCode).Contains(x)).ToList();

                    List<CompanyAuth> insertCompanyAuths = new List<CompanyAuth>();

                    foreach (var checkAuth in insertCompanyAuthStrs)
                    {
                        CompanyAuth companyAuth = new CompanyAuth();
                        companyAuth.CompanyId = company.Id;
                        companyAuth.AuthCode = checkAuth;
                        companyAuth.CreatedBy = myUser.Id;

                        insertCompanyAuths.Add(companyAuth);
                    }

                    List<string> properties = new List<string>()
                    {
                        "CompanyId",
                        "AuthCode",
                        "CreatedBy",
                    };

                    await companyRepository.AddCompanyAuthAsync(insertCompanyAuths, properties);
                }
                #endregion

                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;
        }

        /// <summary>
        /// 透過公司編號，取得該公司剩餘可註冊的人數
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<ApiResult<int>> GetRemainingRegisterNumber(int id)
        {
            ApiResult<int> apiResult = new ApiResult<int>();

            Company company = null;

            try
            {
                company = await companyRepository.GetOneCompany(id);

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

                var registerNumber = await companyRepository.GetRegisterNumberByCompanyId(id);



                apiResult.Code = "0000";
                apiResult.Msg = errorCode.GetString(apiResult.Code);
                apiResult.Data = company.RegisterUpperLimit - registerNumber;
            }
            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;
        }
    }
}
