import { Controller, Get, Path, Request, Route, Security, Tags } from "tsoa";
import { AppDataSource } from "../database/data-source";
import { RequestWithUser } from "../middlewares/user";
import HttpError from "../interfaces/http-error";
import HttpStatus from "../interfaces/http-status";
import HttpSuccess from "../interfaces/http-success";
import { AuthRole } from "../entities/AuthRole";
import { AuthRoleAttr } from "../entities/AuthRoleAttr";
import { PosMaster } from "../entities/PosMaster";
import { Profile } from "../entities/Profile";
import { AuthSys } from "../entities/AuthSys";
import { promisify } from "util";
import { In } from "typeorm";
import permission from "../interfaces/permission";
import { ProfileEmployee } from "../entities/ProfileEmployee";
import { EmployeePosMaster } from "../entities/EmployeePosMaster";
import { OrgRevision } from "../entities/OrgRevision";
import { PosMasterAct } from "../entities/PosMasterAct";
import { actingPositionService } from "../services/ActingPositionService";
const REDIS_HOST = process.env.REDIS_HOST;
const REDIS_PORT = process.env.REDIS_PORT;

@Route("api/v1/org/permission")
@Tags("Permission")
@Security("bearerAuth")
export class PermissionController extends Controller {
  private profileRepo = AppDataSource.getRepository(Profile);
  private profileEmployeeRepo = AppDataSource.getRepository(ProfileEmployee);
  private posMasterRepository = AppDataSource.getRepository(PosMaster);
  private posMasterEmpRepository = AppDataSource.getRepository(EmployeePosMaster);
  private authRoleRepo = AppDataSource.getRepository(AuthRole);
  private authRoleAttrRepo = AppDataSource.getRepository(AuthRoleAttr);
  private authSysRepo = AppDataSource.getRepository(AuthSys);
  private orgRevisionRepository = AppDataSource.getRepository(OrgRevision);
  private posMasterActRepo = AppDataSource.getRepository(PosMasterAct);
  private redis = require("redis");

  @Get("")
  public async getPermission(@Request() request: RequestWithUser) {
    const redisClient = await this.redis.createClient({
      host: REDIS_HOST,
      port: REDIS_PORT,
    });
    const getAsync = promisify(redisClient.get).bind(redisClient);

    let profile: any = await this.profileRepo.findOne({
      select: ["id"],
      where: { keycloak: request.user.sub },
    });
    if (!profile) {
      profile = await this.profileEmployeeRepo.findOne({
        select: ["id"],
        where: { keycloak: request.user.sub },
      });
      if (!profile) {
        throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลบุคคลนี้ในระบบ");
      }
    }

    let reply = await getAsync("role_" + profile.id);
    if (reply != null) {
      reply = JSON.parse(reply);
    } else {
      const orgRevision = await this.orgRevisionRepository.findOne({
        select: ["id"],
        where: {
          orgRevisionIsDraft: false,
          orgRevisionIsCurrent: true,
        },
      });
      let posMaster: any = await this.posMasterRepository.findOne({
        select: ["authRoleId"],
        where: {
          current_holderId: profile.id,
          orgRevisionId: orgRevision?.id,
        },
      });
      if (!posMaster) {
        posMaster = await this.posMasterEmpRepository.findOne({
          select: ["authRoleId"],
          where: {
            current_holderId: profile.id,
            orgRevisionId: orgRevision?.id,
          },
        });
        if (!posMaster) {
          throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลสิทธิ์");
        }
      }
      const getDetail = await this.authRoleRepo.findOne({
        select: ["id", "roleName", "roleDescription"],
        where: { id: posMaster.authRoleId },
      });

      if (!getDetail) {
        throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูล");
      }

      const roleAttrData = await this.authRoleAttrRepo.find({
        select: [
          "authSysId",
          "parentNode",
          "attrOwnership",
          "attrIsCreate",
          "attrIsList",
          "attrIsGet",
          "attrIsUpdate",
          "attrIsDelete",
          "attrPrivilege",
        ],
        where: { authRoleId: getDetail.id },
      });

      reply = {
        ...getDetail,
        roles: roleAttrData,
      };
      redisClient.setex("role_" + profile.id, 86400, JSON.stringify(reply));
    }
    return new HttpSuccess(reply);
  }

  @Get("menu")
  public async listAuthSys(@Request() request: RequestWithUser) {
    const orgRevision = await this.orgRevisionRepository.findOne({
      select: ["id"],
      where: {
        orgRevisionIsDraft: false,
        orgRevisionIsCurrent: true,
      },
    });
    const redisClient = await this.redis.createClient({
      host: REDIS_HOST,
      port: REDIS_PORT,
    });
    const getAsync = promisify(redisClient.get).bind(redisClient);

    let profileType = "OFFICER";
    let profile: any = await this.profileRepo.findOne({
      select: ["id"],
      where: { keycloak: request.user.sub },
    });
    if (!profile) {
      profileType = "EMPLOYEE";
      profile = await this.profileEmployeeRepo.findOne({
        select: ["id"],
        where: { keycloak: request.user.sub },
      });
      if (!profile) {
        throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลบุคคลนี้ในระบบ");
      }
    }

    let reply = await getAsync("menu_" + profile.id);
    if (reply != null) {
      reply = JSON.parse(reply);
    } else {
      let posMaster: any = await this.posMasterRepository.findOne({
        select: ["authRoleId"],
        where: {
          current_holderId: profile.id,
          orgRevisionId: orgRevision?.id,
        },
      });
      if (!posMaster) {
        posMaster = await this.posMasterEmpRepository.findOne({
          select: ["authRoleId"],
          where: {
            current_holderId: profile.id,
            orgRevisionId: orgRevision?.id,
          },
        });
        if (!posMaster) {
          throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลสิทธิ์");
        }
      }

      if (!posMaster.authRoleId) {
        throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลสิทธิ์");
      }

      const authRole = await this.authRoleRepo.findOne({
        select: ["id"],
        where: { id: posMaster.authRoleId },
      });

      if (!authRole) {
        throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลสิทธิ์");
      }
      const roleAttrData = await this.authRoleAttrRepo.find({
        select: ["authSysId", "parentNode"],
        where: { authRoleId: authRole.id, attrIsList: true },
      });
      const parentNode = roleAttrData.map((x) => x.parentNode);
      const authSysId = roleAttrData.map((x) => x.authSysId);
      const sysId = parentNode.concat(authSysId);

      const getList = await this.authSysRepo.find({
        select: ["id", "parentId", "sysName", "sysDescription", "icon", "path", "order"],
        where: {
          id: In(sysId),
        },
        order: { order: "ASC" },
      });

      const getListChild = await this.authSysRepo.find({
        select: ["id", "parentId", "sysName", "sysDescription", "icon", "path", "order"],
        where: {
          parentId: In(sysId),
        },
        order: { order: "ASC" },
      });

      reply = await getList
        .filter((x) => x.parentId == null)
        .sort((a, b) => a.order - b.order)
        .map((item) => {
          return {
            ...item,
            children: getList
              .filter((x) => x.parentId == item.id)
              .sort((a, b) => a.order - b.order)
              .map((item2) => {
                return {
                  ...item2,
                  children: getListChild
                    .filter((x) => x.parentId == item2.id)
                    .sort((a, b) => a.order - b.order),
                };
              }),
          };
        });

      redisClient.setex("menu_" + profile.id, 86400, JSON.stringify(reply));
    }

    return new HttpSuccess(reply);
  }

  /**
   * API ดึงข้อมูลระบบจากตำแหน่งรักษาการ
   * @summary ดึงข้อมูลระบบจากตำแหน่งรักษาการ
   * @param {string} system  authSysId ของระบบที่ต้องการตรวจสอบ
   */
  @Get("acting/{system}")
  public async getSystemsActing(@Request() request: RequestWithUser, @Path() system: string) {
    let profile: any = await this.profileRepo.findOne({
      select: ["id"],
      where: { keycloak: request.user.sub },
    });
    if (!profile) {
      profile = await this.profileEmployeeRepo.findOne({
        select: ["id"],
        where: { keycloak: request.user.sub },
      });
      if (!profile) {
        throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลบุคคลนี้ในระบบ");
      }
    }

    const orgRevision = await this.orgRevisionRepository.findOne({
      select: ["id"],
      where: {
        orgRevisionIsDraft: false,
        orgRevisionIsCurrent: true,
      },
    });

    const posMasterActs = await this.posMasterActRepo
      .createQueryBuilder("posMasterAct")
      .leftJoinAndSelect("posMasterAct.posMaster", "posMaster")
      .addSelect(["posMaster.authRoleId", "posMaster.posMasterNo"])
      .leftJoinAndSelect("posMaster.orgRoot", "orgRoot")
      .leftJoinAndSelect("posMaster.orgChild1", "orgChild1")
      .leftJoinAndSelect("posMaster.orgChild2", "orgChild2")
      .leftJoinAndSelect("posMaster.orgChild3", "orgChild3")
      .leftJoinAndSelect("posMaster.orgChild4", "orgChild4")
      .leftJoinAndSelect("posMasterAct.posMasterChild", "posMasterChild")
      .leftJoinAndSelect("posMasterChild.current_holder", "profileChild")
      .where("profileChild.id = :profileId", { profileId: profile.id })
      .andWhere("posMaster.orgRevisionId = :orgRevisionId", { orgRevisionId: orgRevision?.id })
      .getMany();

    if (posMasterActs.length === 0) {
      return new HttpSuccess([]);
    }

    const results = await Promise.all(
      posMasterActs.map(async (act) => {
        if (!act.posMaster?.authRoleId) {
          return null;
        }

        const roleAttrData = await this.authRoleAttrRepo.findOne({
          select: [
            "authSysId",
            "parentNode",
            "attrOwnership",
            "attrIsCreate",
            "attrIsList",
            "attrIsGet",
            "attrIsUpdate",
            "attrIsDelete",
            "attrPrivilege",
          ],
          where: { authRoleId: act.posMaster.authRoleId, authSysId: system },
        });

        if (!roleAttrData) {
          return null;
        }

        // const holder = act.posMaster;
        // const posNo = !holder
        //   ? null
        //   : holder.orgChild4 != null
        //     ? `${holder.orgChild4.orgChild4ShortName} ${holder.posMasterNo}`
        //     : holder.orgChild3 != null
        //       ? `${holder.orgChild3.orgChild3ShortName} ${holder.posMasterNo}`
        //       : holder.orgChild2 != null
        //         ? `${holder.orgChild2.orgChild2ShortName} ${holder.posMasterNo}`
        //         : holder.orgChild1 != null
        //           ? `${holder.orgChild1.orgChild1ShortName} ${holder.posMasterNo}`
        //           : holder.orgRoot != null
        //             ? `${holder.orgRoot.orgRootShortName} ${holder.posMasterNo}`
        //             : null;

        return {
          ...roleAttrData,
          actingProfileId: act.posMaster.current_holderId,
          // posNo: posNo,
        };
      })
    );

    const filteredResults = results.filter((r) => r !== null);

    return new HttpSuccess(filteredResults);
  }

  /**
   * API permission (dotnet api)
   * @summary permission (dotnet api)
   * @param {string} action  action
   * @param {string} system  authSysId
   */
  @Get("dotnet/{action}/{system}")
  public async dotnet(
    @Request() req: RequestWithUser,
    @Path() action: string,
    @Path() system: string,
  ) {
    if (!["CREATE", "DELETE", "GET", "LIST", "UPDATE"].includes(action)) {
      throw new HttpError(HttpStatus.NOT_FOUND, "Action ไม่ถูกต้อง");
    }

    let res = await new permission().Permission(req, system.toLocaleUpperCase(), action);
    return new HttpSuccess(res);
  }

  /**
   * API permission with acting positions
   * @summary permission with acting positions (dotnet api)
   * @param {string} action  action
   * @param {string} system  authSysId
   */
  @Get("dotnet-acting/{action}/{system}")
  public async dotnetActing(
    @Request() req: RequestWithUser,
    @Path() action: string,
    @Path() system: string,
  ) {
    if (!["CREATE", "DELETE", "GET", "LIST", "UPDATE"].includes(action)) {
      throw new HttpError(HttpStatus.NOT_FOUND, "Action ไม่ถูกต้อง");
    }
    // ดึง privilege ตามปกติ
    let privilege = await new permission().Permission(req, system.toLocaleUpperCase(), action);

    // ดึงข้อมูล profile และ orgRevision
    let profile: any = await this.profileRepo.findOne({
      select: ["id"],
      where: { keycloak: req.user.sub },
    });

    if (!profile) {
      profile = await this.profileEmployeeRepo.findOne({
        select: ["id"],
        where: { keycloak: req.user.sub },
      });
      if (!profile) {
        throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลบุคคลนี้ในระบบ");
      }
    }

    const orgRevision = await this.orgRevisionRepository.findOne({
      select: ["id"],
      where: {
        orgRevisionIsDraft: false,
        orgRevisionIsCurrent: true,
      },
    });

    // ดึงข้อมูลตำแหน่งที่รักษาการ
    const actingData = await actingPositionService.getActingPositionsWithPrivilege(
      profile.id,
      orgRevision?.id,
      action,
      system.toLocaleUpperCase()
    );

    // ส่งค่ากลับเหมือน dotnet endpoint แต่เพิ่ม isAct และ posMasterActs
    return new HttpSuccess({
      privilege,
      isAct: actingData.isAct,
      posMasterActs: actingData.posMasterActs,
    });
  }

  /**
   * API permission (dotnet api)
   * @summary permission (dotnet api)
   * @param {string} action  action
   * @param {string} system  authSysId
   */
  @Get("dotnet-org/{action}/{system}/{profileId}")
  public async dotnetOrg(
    @Request() req: RequestWithUser,
    @Path() action: string,
    @Path() system: string,
  ) {
    if (!["CREATE", "DELETE", "GET", "LIST", "UPDATE"].includes(action)) {
      throw new HttpError(HttpStatus.NOT_FOUND, "Action ไม่ถูกต้อง");
    }

    let res = await new permission().PermissionOrg(req, system.toLocaleUpperCase(), action);
    return new HttpSuccess(res);
  }

  /**
   * API permission (dotnet api)
   * @summary permission (dotnet api)
   * @param {string} action  action
   * @param {string} system  authSysId
   * @param {string} profileId  profileId
   */
  @Get("dotnet-user/{action}/{system}/{profileId}")
  public async dotnetUser(
    @Request() req: RequestWithUser,
    @Path() action: string,
    @Path() system: string,
    @Path() profileId: string,
  ) {
    if (!["CREATE", "DELETE", "GET", "LIST", "UPDATE"].includes(action)) {
      throw new HttpError(HttpStatus.NOT_FOUND, "Action ไม่ถูกต้อง");
    }

    let res = await new permission().PermissionOrgByUser(
      req,
      system.toLocaleUpperCase(),
      action,
      profileId,
    );
    return new HttpSuccess(res);
  }

  @Get("org/{system}/{action}")
  public async listAuthSysOrg(
    @Request() request: RequestWithUser,
    @Path() system: string,
    @Path() action: string,
  ) {
    const redisClient = await this.redis.createClient({
      host: REDIS_HOST,
      port: REDIS_PORT,
    });
    const getAsync = promisify(redisClient.get).bind(redisClient);

    let profileType = "OFFICER";
    let profile: any = await this.profileRepo.findOne({
      select: ["id"],
      where: { keycloak: request.user.sub },
    });
    if (!profile) {
      profileType = "EMPLOYEE";
      profile = await this.profileEmployeeRepo.findOne({
        select: ["id"],
        where: { keycloak: request.user.sub },
      });
      if (!profile) {
        throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลบุคคลนี้ในระบบ");
      }
    }

    let privilege = await this.Permission(request, system, action);
    let reply = await getAsync("posMaster_" + profile.id);
    if (reply != null) {
      reply = JSON.parse(reply);
      reply.privilege = privilege;
    } else {
      const orgRevision = await this.orgRevisionRepository.findOne({
        select: ["id"],
        where: {
          orgRevisionIsDraft: false,
          orgRevisionIsCurrent: true,
        },
      });
      if (profileType == "OFFICER") {
        const posMaster = await this.posMasterRepository.findOne({
          where: {
            current_holderId: profile.id,
            orgRevisionId: orgRevision?.id,
          },
        });
        if (!posMaster) {
          reply = {
            orgRootId: null,
            orgChild1Id: null,
            orgChild2Id: null,
            orgChild3Id: null,
            orgChild4Id: null,
            privilege: privilege,
          };
        } else {
          reply = {
            orgRootId: posMaster.orgRootId,
            orgChild1Id: posMaster.orgChild1Id,
            orgChild2Id: posMaster.orgChild2Id,
            orgChild3Id: posMaster.orgChild3Id,
            orgChild4Id: posMaster.orgChild4Id,
            privilege: privilege,
          };
        }
        redisClient.setex("posMaster_" + profile.id, 86400, JSON.stringify(reply));
      } else {
        const posMaster = await this.posMasterEmpRepository.findOne({
          where: {
            current_holderId: profile.id,
            orgRevisionId: orgRevision?.id,
          },
        });
        if (!posMaster) {
          reply = {
            orgRootId: null,
            orgChild1Id: null,
            orgChild2Id: null,
            orgChild3Id: null,
            orgChild4Id: null,
            privilege: privilege,
          };
        } else {
          reply = {
            orgRootId: posMaster.orgRootId,
            orgChild1Id: posMaster.orgChild1Id,
            orgChild2Id: posMaster.orgChild2Id,
            orgChild3Id: posMaster.orgChild3Id,
            orgChild4Id: posMaster.orgChild4Id,
            privilege: privilege,
          };
        }
        redisClient.setex("posMaster_" + profile.id, 86400, JSON.stringify(reply));
      }
    }

    return new HttpSuccess(reply);
  }

  @Get("user/{system}/{action}/{id}")
  public async listOrgUser(
    @Request() request: RequestWithUser,
    @Path() system: string,
    @Path() action: string,
    @Path() id: string,
  ) {
    const orgRevision = await this.orgRevisionRepository.findOne({
      select: ["id"],
      where: {
        orgRevisionIsDraft: false,
        orgRevisionIsCurrent: true,
      },
    });
    const redisClient = await this.redis.createClient({
      host: REDIS_HOST,
      port: REDIS_PORT,
    });
    const getAsync = promisify(redisClient.get).bind(redisClient);

    let org = this.PermissionOrg(request, system, action);
    let reply = await getAsync("user_" + id);
    if (reply != null) {
      reply = JSON.parse(reply);
      reply.org = org;
    } else {
      let profileType = "OFFICER";
      let profile: any = await this.profileRepo.findOne({
        select: ["id"],
        where: { id: id },
      });
      if (!profile) {
        profileType = "EMPLOYEE";
        profile = await this.profileEmployeeRepo.findOne({
          select: ["id"],
          where: { id: id },
        });
        if (!profile) {
          throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลบุคคลนี้ในระบบ");
        }
      }
      if (profileType == "OFFICER") {
        const posMaster = await this.posMasterRepository.findOne({
          where: {
            current_holderId: profile.id,
            orgRevisionId: orgRevision?.id,
          },
        });
        if (!posMaster) {
          reply = {
            orgRootId: null,
            orgChild1Id: null,
            orgChild2Id: null,
            orgChild3Id: null,
            orgChild4Id: null,
            org: org,
          };
        } else {
          reply = {
            orgRootId: posMaster.orgRootId,
            orgChild1Id: posMaster.orgChild1Id,
            orgChild2Id: posMaster.orgChild2Id,
            orgChild3Id: posMaster.orgChild3Id,
            orgChild4Id: posMaster.orgChild4Id,
            org: org,
          };
        }
        redisClient.setex("user_" + profile.id, 86400, JSON.stringify(reply));
      } else {
        const posMaster = await this.posMasterEmpRepository.findOne({
          where: {
            current_holderId: profile.id,
            orgRevisionId: orgRevision?.id,
          },
        });
        if (!posMaster) {
          reply = {
            orgRootId: null,
            orgChild1Id: null,
            orgChild2Id: null,
            orgChild3Id: null,
            orgChild4Id: null,
            org: org,
          };
        } else {
          reply = {
            orgRootId: posMaster.orgRootId,
            orgChild1Id: posMaster.orgChild1Id,
            orgChild2Id: posMaster.orgChild2Id,
            orgChild3Id: posMaster.orgChild3Id,
            orgChild4Id: posMaster.orgChild4Id,
            org: org,
          };
        }
        redisClient.setex("user_" + profile.id, 86400, JSON.stringify(reply));
      }
    }

    return new HttpSuccess(reply);
  }

  public async getPermissionFunc(@Request() request: RequestWithUser) {
    const redisClient = await this.redis.createClient({
      host: REDIS_HOST,
      port: REDIS_PORT,
    });
    const getAsync = promisify(redisClient.get).bind(redisClient);

    let profile: any = await this.profileRepo.findOne({
      select: ["id"],
      where: { keycloak: request.user.sub },
    });
    if (!profile) {
      profile = await this.profileEmployeeRepo.findOne({
        select: ["id"],
        where: { keycloak: request.user.sub },
      });
      if (!profile) {
        throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลบุคคลนี้ในระบบ");
      }
    }

    let reply = await getAsync("role_" + profile.id);
    if (reply != null) {
      reply = JSON.parse(reply);
    } else {
      const orgRevision = await this.orgRevisionRepository.findOne({
        select: ["id"],
        where: {
          orgRevisionIsDraft: false,
          orgRevisionIsCurrent: true,
        },
      });
      let posMaster: any = await this.posMasterRepository.findOne({
        select: ["authRoleId"],
        where: {
          current_holderId: profile.id,
          orgRevisionId: orgRevision?.id,
        },
      });
      if (!posMaster) {
        posMaster = await this.posMasterEmpRepository.findOne({
          select: ["authRoleId"],
          where: {
            current_holderId: profile.id,
            orgRevisionId: orgRevision?.id,
          },
        });
        if (!posMaster) {
          throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลสิทธิ์");
        }
      }

      const getDetail = await this.authRoleRepo.findOne({
        select: ["id", "roleName", "roleDescription"],
        where: { id: posMaster.authRoleId },
      });
      if (!getDetail) {
        throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูล");
      }

      const roleAttrData = await this.authRoleAttrRepo.find({
        select: [
          "authSysId",
          "parentNode",
          "attrOwnership",
          "attrIsCreate",
          "attrIsList",
          "attrIsGet",
          "attrIsUpdate",
          "attrIsDelete",
          "attrPrivilege",
        ],
        where: { authRoleId: getDetail.id },
      });

      reply = {
        ...getDetail,
        roles: roleAttrData,
      };
      redisClient.setex("role_" + profile.id, 86400, JSON.stringify(reply));
    }
    return reply;
  }

  public async Permission(req: RequestWithUser, system: string, action: string) {
    // if (
    //   req.headers.hasOwnProperty("api_key") &&
    //   req.headers["api_key"] &&
    //   req.headers["api_key"] == process.env.API_KEY
    // ) {
    //   return null;
    // }
    let x: any = await this.getPermissionFunc(req);
    let permission = false;
    let role = x.roles.find((x: any) => x.authSysId == system);
    if (!role) throw "ไม่มีสิทธิ์เข้าระบบ";
    if (role.attrOwnership == "OWNER") return "OWNER";
    if (action.trim().toLocaleUpperCase() == "CREATE") permission = role.attrIsCreate;
    if (action.trim().toLocaleUpperCase() == "DELETE") permission = role.attrIsDelete;
    if (action.trim().toLocaleUpperCase() == "GET") permission = role.attrIsGet;
    if (action.trim().toLocaleUpperCase() == "LIST") permission = role.attrIsList;
    if (action.trim().toLocaleUpperCase() == "UPDATE") permission = role.attrIsUpdate;
    if (permission == false) throw "ไม่มีสิทธิ์ใช้งานระบบนี้";
    return role.attrPrivilege;
  }

  public async listAuthSysOrgFunc(request: RequestWithUser, system: string, action: string) {
    const redisClient = await this.redis.createClient({
      host: REDIS_HOST,
      port: REDIS_PORT,
    });
    const getAsync = promisify(redisClient.get).bind(redisClient);

    let profileType = "OFFICER";
    let profile: any = await this.profileRepo.findOne({
      select: ["id"],
      where: { keycloak: request.user.sub },
    });
    if (!profile) {
      profileType = "EMPLOYEE";
      profile = await this.profileEmployeeRepo.findOne({
        select: ["id"],
        where: { keycloak: request.user.sub },
      });
      if (!profile) {
        throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลบุคคลนี้ในระบบ");
      }
    }

    let reply = await getAsync("posMaster_" + profile.id);
    if (reply != null) {
      reply = JSON.parse(reply);
    } else {
      let privilege = await this.Permission(request, system, action);
      const orgRevision = await this.orgRevisionRepository.findOne({
        select: ["id"],
        where: {
          orgRevisionIsDraft: false,
          orgRevisionIsCurrent: true,
        },
      });
      if (profileType == "OFFICER") {
        const posMaster = await this.posMasterRepository.findOne({
          where: {
            current_holderId: profile.id,
            orgRevisionId: orgRevision?.id,
          },
        });
        if (!posMaster) {
          reply = {
            orgRootId: null,
            orgChild1Id: null,
            orgChild2Id: null,
            orgChild3Id: null,
            orgChild4Id: null,
            privilege: privilege,
          };
        } else {
          reply = {
            orgRootId: posMaster.orgRootId,
            orgChild1Id: posMaster.orgChild1Id,
            orgChild2Id: posMaster.orgChild2Id,
            orgChild3Id: posMaster.orgChild3Id,
            orgChild4Id: posMaster.orgChild4Id,
            privilege: privilege,
          };
        }
        redisClient.setex("posMaster_" + profile.id, 86400, JSON.stringify(reply));
      } else {
        const posMaster = await this.posMasterEmpRepository.findOne({
          where: {
            current_holderId: profile.id,
            orgRevisionId: orgRevision?.id,
          },
        });
        if (!posMaster) {
          reply = {
            orgRootId: null,
            orgChild1Id: null,
            orgChild2Id: null,
            orgChild3Id: null,
            orgChild4Id: null,
            privilege: privilege,
          };
        } else {
          reply = {
            orgRootId: posMaster.orgRootId,
            orgChild1Id: posMaster.orgChild1Id,
            orgChild2Id: posMaster.orgChild2Id,
            orgChild3Id: posMaster.orgChild3Id,
            orgChild4Id: posMaster.orgChild4Id,
            privilege: privilege,
          };
        }
        redisClient.setex("posMaster_" + profile.id, 86400, JSON.stringify(reply));
      }
    }
    return reply;
  }

  public async PermissionOrg(req: RequestWithUser, system: string, action: string) {
    let x: any = await this.listAuthSysOrgFunc(req, system, action);
    let privilege = x.privilege;

    let data: any = {
      root: [null],
      child1: [null],
      child2: [null],
      child3: [null],
      child4: [null],
    };
    let node = 4;
    if (x.orgChild1Id == null) {
      node = 0;
    } else if (x.orgChild2Id == null) {
      node = 1;
    } else if (x.orgChild3Id == null) {
      node = 2;
    } else if (x.orgChild4Id == null) {
      node = 3;
    }
    if (privilege == "ROOT") {
      data = {
        root: [x.orgRootId],
        child1: null,
        child2: null,
        child3: null,
        child4: null,
      };
    } else if (privilege == "PARENT") {
      data = {
        // root: [x.orgRootId],
        // child1: [null],
        root: null,
        child1: null,
        child2: null,
        child3: null,
        child4: null,
      };
    } else if (privilege == "CHILD") {
      data = {
        root: node >= 0 ? [x.orgRootId] : null,
        child1: node >= 1 ? [x.orgChild1Id] : null,
        child2: node >= 2 ? [x.orgChild2Id] : null,
        child3: node >= 3 ? [x.orgChild3Id] : null,
        child4: node >= 4 ? [x.orgChild4Id] : null,
      };
    } else if (privilege == "BROTHER") {
      data = {
        // root: node >= 0 ? null : null,
        root: node >= 0 ? [x.orgRootId] : null,
        child1: node >= 2 ? [x.orgChild1Id] : null,
        child2: node >= 3 ? [x.orgChild2Id] : null,
        child3: node >= 4 ? [x.orgChild3Id] : null,
      };
    } else if (privilege == "NORMAL") {
      data = {
        root: [x.orgRootId],
        child1: [x.orgChild1Id],
        child2: [x.orgChild2Id],
        child3: [x.orgChild3Id],
        child4: [x.orgChild4Id],
      };
    } else if (privilege == "SPECIFIC") {
    } else if (privilege == "OWNER") {
      data = {
        root: null,
        child1: null,
        child2: null,
        child3: null,
        child4: null,
      };
    }

    return data;
  }

  @Get("checkOrg/{keycloakId}")
  public async checkOrg(@Path() keycloakId: string) {
    const redisClient = await this.redis.createClient({
      host: REDIS_HOST,
      port: REDIS_PORT,
    });
    // const getAsync = promisify(redisClient.get).bind(redisClient);

    // let profileType = "OFFICER";
    let profile: any = await this.profileRepo.findOne({
      select: ["id"],
      where: { keycloak: keycloakId },
    });
    // if (!profile) {
    //   profileType = "EMPLOYEE";
    //   profile = await this.profileEmployeeRepo.findOne({
    //     select: ["id"],
    //     where: { keycloak: keycloakId },
    //   });
    //   if (!profile) {
    //     throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลบุคคลนี้ในระบบ");
    //   }
    // }
    let reply: any;
    const orgRevision = await this.orgRevisionRepository.findOne({
      select: ["id"],
      where: {
        orgRevisionIsDraft: false,
        orgRevisionIsCurrent: true,
      },
    });
    // if (profileType == "OFFICER") {
    const posMaster = await this.posMasterRepository.findOne({
      where: {
        current_holderId: profile.id,
        orgRevisionId: orgRevision?.id,
      },
    });
    if (!posMaster) {
      reply = {
        orgRootId: null,
        orgChild1Id: null,
        orgChild2Id: null,
        orgChild3Id: null,
        orgChild4Id: null,
      };
    } else {
      reply = {
        orgRootId: posMaster.orgRootId,
        orgChild1Id: posMaster.orgChild1Id,
        orgChild2Id: posMaster.orgChild2Id,
        orgChild3Id: posMaster.orgChild3Id,
        orgChild4Id: posMaster.orgChild4Id,
      };
    }
    redisClient.setex("org_" + profile.id, 86400, JSON.stringify(reply)); //Create Redis
    // } else {
    //   const posMaster = await this.posMasterEmpRepository.findOne({
    //     where: {
    //       current_holderId: profile.id,
    //       orgRevisionId: orgRevision?.id,
    //     },
    //   });
    //   if (!posMaster) {
    //     reply = {
    //       orgRootId: null,
    //       orgChild1Id: null,
    //       orgChild2Id: null,
    //       orgChild3Id: null,
    //       orgChild4Id: null,
    //     };
    //   } else {
    //     reply = {
    //       orgRootId: posMaster.orgRootId,
    //       orgChild1Id: posMaster.orgChild1Id,
    //       orgChild2Id: posMaster.orgChild2Id,
    //       orgChild3Id: posMaster.orgChild3Id,
    //       orgChild4Id: posMaster.orgChild4Id,
    //     };
    //   }
    //   redisClient.setex("org_" + profile.id, 86400, JSON.stringify(reply));
    // }

    return new HttpSuccess(reply);
  }
}
