using Dapper;
using SolarPower.Helper;
using SolarPower.Models;
using SolarPower.Models.Role;
using SolarPower.Repository.Interface;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Threading.Tasks;

namespace SolarPower.Repository.Implement
{
    public class RoleRepository : RepositoryBase<Role>, IRoleRepository
    {
        public RoleRepository(IDatabaseHelper databaseHelper) : base(databaseHelper)
        {
            tableName = "role";
        }

        /// <summary>
        /// 取得下拉式公司角色選單，須為Deleted: 0
        /// </summary>
        /// <param name="filter"></param>
        /// <returns></returns>
        public async Task<List<RoleSelectItemList>> GetRoleSelectOptionListAsync(int companyId)
        {
            List<RoleSelectItemList> result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                try
                {
                    var sql = $"SELECT Id AS Value, Name AS Text FROM `{tableName}` WHERE Deleted = 0 AND CompanyId = @CompanyId";

                    result = (await conn.QueryAsync<RoleSelectItemList>(sql, new { CompanyId = companyId })).ToList();
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                return result;
            }
        }

        /// <summary>
        /// 取得當前使用者的角色資訊
        /// </summary>
        /// <param name="account"></param>
        /// <returns></returns>
        public MyRole GetMyRoleInfoById(int id)
        {
            MyRole result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                conn.Open();
                try
                {
                    var sql = $"SELECT * FROM `{tableName}` WHERE Deleted = 0 AND Id = @Id";

                    result = conn.QueryFirstOrDefault<MyRole>(sql, new { Id = id });

                    //查詢該角色可使用的權限
                    var sql_auth = @"SELECT ControlName FROM role_auth ra
                                        LEFT JOIN auth_page ap ON ra.AuthCode = ap.AuthCode
                                        WHERE ra.Id = @Id";

                    result.Auths = conn.Query<string>(sql_auth, new { Id = id }).ToList();
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                finally
                {
                    conn.Close();
                }
                return result;
            }
        }

        /// <summary>
        /// 取得單一公司角色，須為Deleted: 0
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<Role> GetOneRoleAsync(int id)
        {
            Role result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                conn.Open();
                try
                {
                    var sql = $"SELECT * FROM `{tableName}` WHERE Deleted = 0 AND Id = @Id";

                    result = await conn.QueryFirstOrDefaultAsync<Role>(sql, new { Id = id });
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                finally
                {
                    conn.Close();
                }
                return result;
            }
        }

        /// <summary>
        /// 透過搜尋條件，查詢過濾後的使用者
        /// </summary>
        /// <param name="filter"></param>
        /// <returns></returns>
        public async Task<List<RoleDateTable>> GetAllByFilterAsync(PostRoleFilter filter)
        {
            List<RoleDateTable> result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                try
                {
                    var sql = @$"SELECT
                                    r.*,
                                    c.Name AS CompanyName,
                                    u.Name AS CreatorName
                                    FROM `{tableName}` r
                                    LEFT JOIN company c ON r.CompanyId = c.Id
                                    LEFT JOIN user u ON r.CreatedBy = u.Id
                                    WHERE r.Deleted = 0 
                                    AND c.Deleted = 0
                                    AND r.CompanyId = @SelectedCompanyId";

                    if (!string.IsNullOrEmpty(filter.Name))
                    {
                        sql += @" AND Name LIKE CONCAT('%', @Name, '%')";
                    }

                    result = (await conn.QueryAsync<RoleDateTable>(sql, filter)).ToList();
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                return result;
            }
        }

        /// <summary>
        /// 修改角色資料
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public async Task UpdateRoleAsync(UpdateRole entity, List<string> properties)
        {
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                conn.Open();
                using (var trans = conn.BeginTransaction())
                {
                    try
                    {
                        var sql = GenerateUpdateQuery(properties);

                        await conn.ExecuteAsync(sql, entity, trans);

                        trans.Commit();
                    }
                    catch (Exception exception)
                    {
                        trans.Rollback();
                        throw exception;
                    }
                    finally
                    {
                        conn.Close();
                    }
                }
            }
        }

        /// <summary>
        /// 透過角色編號，取得所有權限功能
        /// </summary>
        /// <param name="roleId"></param>
        /// <returns></returns>
        public async Task<List<RoleAuthDataTable>> GetAllAuthByRoleIdAsync(int roleId)
        {
            List<RoleAuthDataTable> result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                try
                {
                    var sql = @$"SELECT
                                    ra.*,
                                    r.Name AS RoleName,
                                    c.Name AS CompanyName,
                                    u.Name AS CreatorName,
                                    ap.SubName AS AuthPageSubName,
                                    ap.TagName AS AuthPageTagName
                                    FROM role_auth ra
                                    LEFT JOIN `role` r ON ra.Id = r.Id
                                    LEFT JOIN auth_page ap ON ra.AuthCode = ap.AuthCode
                                    LEFT JOIN user u ON ra.CreatedBy = u.Id
                                    LEFT JOIN company c ON r.CompanyId = c.Id
                                    WHERE r.Deleted = 0 
                                    AND c.Deleted = 0
                                    AND r.Id = @SelectedRoleId";

                    result = (await conn.QueryAsync<RoleAuthDataTable>(sql, new { SelectedRoleId = roleId })).ToList();
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                return result;
            }
        }

        /// <summary>
        /// 透過公司編號，取得被賦予的權限池
        /// </summary>
        /// <param name="roleId"></param>
        /// <returns></returns>
        public async Task<List<CompanyAuthPage>> GetAllCompanyAuthPageAsync(int companyId)
        {
            List<CompanyAuthPage> result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                try
                {
                    var sql = @$"SELECT
                                    cap.*,
                                    ap.MainName AS AuthPageMainName,
                                    ap.SubName AS AuthPageSubName
                                    FROM company_auth_page cap
                                    LEFT JOIN auth_page ap ON cap.AuthCode = ap.AuthCode
                                    WHERE cap.CompanyId = @CompanyId";

                    result = (await conn.QueryAsync<CompanyAuthPage>(sql, new { CompanyId = companyId })).ToList();
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                return result;
            }
        }

        /// <summary>
        /// 查詢公司權限池裡面該角色尚未擁有的權限
        /// </summary>
        /// <param name="post"></param>
        /// <returns></returns>
        public async Task<List<AuthPage>> GetRoleNotAuthPageAsync(PostRoleAuthFilter post)
        {
            List<AuthPage> result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                try
                {
                    var sql = @$"SELECT ap2.AuthCode, ap2.MainName, ap2.SubName, ap2.TagName
                                    FROM 
                                    (
	                                    SELECT cap.CompanyId, cap.AuthCode, ap.MainName, ap.SubName, ap.TagName , ap.ControlName 
	                                    FROM company_auth_page cap
	                                    LEFT JOIN auth_page ap ON cap.AuthCode = ap.AuthCode
	                                    WHERE cap.CompanyId = @CompanyId
                                    ) ap2
                                    LEFT JOIN role_auth ra ON ap2.AuthCode = ra.AuthCode AND ra.Id = @RoleId
                                    WHERE ra.AuthCode IS NULL
                                ";

                    result = (await conn.QueryAsync<AuthPage>(sql, new { CompanyId = post.SelectedCompanyId, RoleId = post.SelectedRoleId})).ToList();
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                return result;
            }
        }

        /// <summary>
        /// 新增角色權限
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="properties"></param>
        /// <returns></returns>
        public async Task<int> AddRoleAuthAsync(List<RoleAuth> entity, List<string> properties)
        {
            int count;
            using (IDbConnection conn = _databaseHelper.GetConnection())
            {
                conn.Open();
                try
                {
                    string sql = $"INSERT INTO role_auth (Id, AuthCode, CreatedBy) VALUES (@Id, @AuthCode, @CreatedBy)";

                    count = await conn.ExecuteAsync(sql, entity);
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                finally
                {
                    conn.Close();
                }

                return count;
            }
        }

        public async Task PurgeOneRoleAuthAsync(int roleId, string authCode)
        {
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                conn.Open();
                using (var trans = conn.BeginTransaction())
                {
                    try
                    {
                        var sql = $"DELETE FROM role_auth WHERE Id = @RoleId AND AuthCode = @AuthCode";

                        await conn.ExecuteAsync(sql, new { RoleId = roleId, AuthCode = authCode }, trans);

                        trans.Commit();
                    }
                    catch (Exception exception)
                    {
                        trans.Rollback();
                        throw exception;
                    }
                    finally
                    {
                        conn.Close();
                    }
                }
            }
        }
    }
}
