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) {
    let redisClient;
    try {
      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, "ไม่พบข้อมูลบุคคลนี้ในระบบ");
      }
    }

    // Query ตำแหน่งรักษาการโดยใช้ service ที่มีอยู่
    const orgRevision = await this.orgRevisionRepository.findOne({
      select: ["id"],
      where: {
        orgRevisionIsDraft: false,
        orgRevisionIsCurrent: true,
      },
    });

    const actingData = await actingPositionService.getActingPositionsWithPrivilege(
      profile.id,
      orgRevision?.id
    );

    // ใช้ cache key เดิม และตรวจสอบสถานะ acting ทุกครั้ง
    let reply = await getAsync("role_" + 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,
          },
        });
      }

      // ตรวจสอบว่ามีสิทธิ์อย่างน้อยหนึ่งอย่าง (posMaster หรือ acting position)
      if (!posMaster && !actingData.isAct) {
        throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลสิทธิ์");
      }

      let getDetail: any = null;
      let roleAttrData: any[] = [];

      if (posMaster) {
        getDetail = await this.authRoleRepo.findOne({
          select: ["id", "roleName", "roleDescription"],
          where: { id: posMaster.authRoleId },
        });

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

        roleAttrData = await this.authRoleAttrRepo.find({
          select: [
            "authSysId",
            "parentNode",
            "attrOwnership",
            "attrIsCreate",
            "attrIsList",
            "attrIsGet",
            "attrIsUpdate",
            "attrIsDelete",
            "attrPrivilege",
          ],
          where: { authRoleId: getDetail.id },
        });
      } else {
        // ถ้าไม่มี posMaster แต่มี acting: สร้าง getDetail เปล่าๆ
        getDetail = {
          id: null,
          roleName: "Acting",
          roleDescription: "สิทธิ์จากตำแหน่งรักษาการ",
        };
      }

      // ถ้า User มีตำแหน่งรักษาการ ให้รวมสิทธิ์
      if (actingData.isAct && actingData.posMasterActs.length > 0) {
        // ดึง authRoleId ของทุกตำแหน่งรักษาการ
        const actingAuthRoleIds = await this.posMasterActRepo
          .createQueryBuilder("posMasterAct")
          .leftJoin("posMasterAct.posMaster", "posMaster")
          .select("posMaster.authRoleId", "authRoleId")
          .leftJoin("posMasterAct.posMasterChild", "posMasterChild")
          .leftJoin("posMasterChild.current_holder", "profile")
          .where("profile.id = :profileId", { profileId: profile.id })
          .andWhere("posMaster.orgRevisionId = :orgRevisionId", { orgRevisionId: orgRevision?.id })
          .getRawMany();

        // ดึง AuthRoleAttr ทั้งหมดของ acting roles
        const actingRoleIds = actingAuthRoleIds.map(x => x.authRoleId).filter(id => id != null);
        const actingRoleAttrs = await this.authRoleAttrRepo.find({
          select: [
            "authSysId",
            "parentNode",
            "attrOwnership",
            "attrIsCreate",
            "attrIsList",
            "attrIsGet",
            "attrIsUpdate",
            "attrIsDelete",
            "attrPrivilege",
          ],
          where: { authRoleId: In(actingRoleIds) as any },
        });

        // สร้าง map ของ authSysId -> สิทธิ์ที่ดีที่สุดจาก acting
        const actingPermissionMap = new Map<string, any>();

        // ลำดับความสำคัญของ privilege (มากไปน้อย)
        const privilegePriority: Record<string, number> = {
          "OWNER": 7,
          "PARENT": 6,
          "ROOT": 5,
          "BROTHER": 4,
          "CHILD": 3,
          "NORMAL": 2,
          "SPECIFIC": 1,
          "null": 0,
        };

        // ฟังก์ชันเปรียบเทียบ privilege
        const getHigherPrivilege = (priv1: string | null, priv2: string | null): string | null => {
          const p1 = priv1 ?? "null";
          const p2 = priv2 ?? "null";
          const priority1 = privilegePriority[p1] ?? 0;
          const priority2 = privilegePriority[p2] ?? 0;
          return priority1 >= priority2 ? priv1 : priv2;
        };

        // ฟังก์ชันเปรียบเทียบ ownership (OWNER > STAFF > null)
        const getHigherOwnership = (own1: string | null, own2: string | null): string | null => {
          // OWNER สูงสุด
          if (own1 === "OWNER" || own2 === "OWNER") return "OWNER";
          // STAFF รองลงมา
          if (own1 === "STAFF" || own2 === "STAFF") return "STAFF";
          return null;
        };

        for (const attr of actingRoleAttrs) {
          const key = attr.authSysId;
          if (!actingPermissionMap.has(key)) {
            actingPermissionMap.set(key, attr);
          } else {
            // รวมสิทธิ์: ใช้ OR logic สำหรับ CRUD
            // สำหรับ attrOwnership และ attrPrivilege ใช้ค่าที่ใหญ่ที่สุด
            const existing = actingPermissionMap.get(key);
            actingPermissionMap.set(key, {
              ...attr,
              attrIsCreate: existing.attrIsCreate || attr.attrIsCreate,
              attrIsList: existing.attrIsList || attr.attrIsList,
              attrIsGet: existing.attrIsGet || attr.attrIsGet,
              attrIsUpdate: existing.attrIsUpdate || attr.attrIsUpdate,
              attrIsDelete: existing.attrIsDelete || attr.attrIsDelete,
              attrPrivilege: getHigherPrivilege(attr.attrPrivilege, existing.attrPrivilege),
              parentNode: attr.parentNode, // ใช้ parentNode ของ acting role
              attrOwnership: getHigherOwnership(attr.attrOwnership, existing.attrOwnership),
            });
          }
        }

        // รวมกับสิทธิ์พื้นฐานของ User
        // สำหรับระบบที่อยู่ใน acting: ใช้สิทธิ์จาก acting
        // สำหรับระบบที่ไม่อยู่ใน acting: ใช้สิทธิ์พื้นฐาน
        const mergedRoleAttrs = roleAttrData.map((baseAttr) => {
          const actingAttr = actingPermissionMap.get(baseAttr.authSysId);
          if (actingAttr) {
            // ระบบนี้มีสิทธิ์จาก acting - ใช้ค่าจาก acting role
            return {
              ...baseAttr,
              parentNode: actingAttr.parentNode,
              attrOwnership: getHigherOwnership(actingAttr.attrOwnership, baseAttr.attrOwnership),
              attrIsCreate: actingAttr.attrIsCreate || baseAttr.attrIsCreate,
              attrIsList: actingAttr.attrIsList || baseAttr.attrIsList,
              attrIsGet: actingAttr.attrIsGet || baseAttr.attrIsGet,
              attrIsUpdate: actingAttr.attrIsUpdate || baseAttr.attrIsUpdate,
              attrIsDelete: actingAttr.attrIsDelete || baseAttr.attrIsDelete,
              attrPrivilege: getHigherPrivilege(actingAttr.attrPrivilege, baseAttr.attrPrivilege),
              // เพิ่ม metadata เพื่อระบุว่ามาจาก acting
              _isActing: true,
            };
          }
          // เก็บสิทธิ์พื้นฐานสำหรับระบบที่ไม่ได้รักษาการ
          return baseAttr;
        });

        // เพิ่มระบบที่มีเฉพาะใน acting roles
        for (const [authSysId, actingAttr] of actingPermissionMap) {
          if (!roleAttrData.find(a => a.authSysId === authSysId)) {
            mergedRoleAttrs.push({
              ...actingAttr,
              _isActing: true,
            });
          }
        }

        reply = {
          ...getDetail,
          roles: mergedRoleAttrs,
          isActing: true, // Flag ระบุสถานะ acting
        };
      } else {
        // ไม่มี acting - ใช้ response เดิม
        reply = {
          ...getDetail,
          roles: roleAttrData,
          isActing: false,
        };
      }
      redisClient.setex("role_" + profile.id, 86400, JSON.stringify(reply));
    }
    return new HttpSuccess(reply);
    } finally {
      if (redisClient) {
        redisClient.quit();
      }
    }
  }

  @Get("menu")
  public async listAuthSys(@Request() request: RequestWithUser) {
    const orgRevision = await this.orgRevisionRepository.findOne({
      select: ["id"],
      where: {
        orgRevisionIsDraft: false,
        orgRevisionIsCurrent: true,
      },
    });
    let redisClient;
    try {
      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, "ไม่พบข้อมูลบุคคลนี้ในระบบ");
      }
    }

    // Query ตำแหน่งรักษาการ
    const actingData = await actingPositionService.getActingPositionsWithPrivilege(
      profile.id,
      orgRevision?.id
    );

    // ใช้ cache key เดิม
    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,
          },
        });
      }

      // ตรวจสอบว่ามีสิทธิ์อย่างน้อยหนึ่งอย่าง (posMaster หรือ acting position)
      if (!posMaster && !actingData.isAct) {
        throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลสิทธิ์");
      }

      let authRole: any = null;
      let roleAttrData: any[] = [];

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

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

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

        // ดึง roleAttrData ของ user ปกติ
        roleAttrData = await this.authRoleAttrRepo.find({
          select: ["authSysId", "parentNode"],
          where: { authRoleId: authRole.id, attrIsList: true },
        });
      }

      // ถ้ามี acting positions ให้รวมสิทธิ์
      if (actingData.isAct && actingData.posMasterActs.length > 0) {
        // ดึง authRoleId ของทุกตำแหน่งรักษาการ
        const actingAuthRoleIds = await this.posMasterActRepo
          .createQueryBuilder("posMasterAct")
          .leftJoin("posMasterAct.posMaster", "posMaster")
          .select("posMaster.authRoleId", "authRoleId")
          .leftJoin("posMasterAct.posMasterChild", "posMasterChild")
          .leftJoin("posMasterChild.current_holder", "profile")
          .where("profile.id = :profileId", { profileId: profile.id })
          .andWhere("posMaster.orgRevisionId = :orgRevisionId", { orgRevisionId: orgRevision?.id })
          .getRawMany();

        // ดึง AuthRoleAttr ทั้งหมดของ acting roles (เฉพาะที่มี attrIsList: true)
        const actingRoleIds = actingAuthRoleIds.map(x => x.authRoleId).filter(id => id != null);
        const actingRoleAttrs = await this.authRoleAttrRepo.find({
          select: ["authSysId", "parentNode"],
          where: { authRoleId: In(actingRoleIds) as any, attrIsList: true },
        });

        // รวม authSysId และ parentNode จาก acting เข้ากับ base
        // สำหรับระบบที่มีในทั้งสอง ให้ใช้ค่าของ acting (parentNode)
        for (const actingAttr of actingRoleAttrs) {
          const existingIndex = roleAttrData.findIndex(x => x.authSysId === actingAttr.authSysId);
          if (existingIndex >= 0) {
            // ระบบนี้มีใน base ด้วย -> ใช้ parentNode ของ acting
            roleAttrData[existingIndex].parentNode = actingAttr.parentNode;
          } else {
            // ระบบนี้มีเฉพาะใน acting -> เพิ่มเข้าไป
            roleAttrData.push(actingAttr);
          }
        }
      }

      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);
    } finally {
      if (redisClient) {
        redisClient.quit();
      }
    }
  }

  /**
   * 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,
  ) {
    let redisClient;
    try {
      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);
    } finally {
      if (redisClient) {
        redisClient.quit();
      }
    }
  }

  @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,
      },
    });
    let redisClient;
    try {
      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);
    } finally {
      if (redisClient) {
        redisClient.quit();
      }
    }
  }

  public async getPermissionFunc(@Request() request: RequestWithUser) {
    let redisClient;
    try {
      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, "ไม่พบข้อมูลบุคคลนี้ในระบบ");
      }
    }

    // Query ตำแหน่งรักษาการ
    const orgRevision = await this.orgRevisionRepository.findOne({
      select: ["id"],
      where: {
        orgRevisionIsDraft: false,
        orgRevisionIsCurrent: true,
      },
    });

    const actingData = await actingPositionService.getActingPositionsWithPrivilege(
      profile.id,
      orgRevision?.id
    );

    // ใช้ cache key เดิม
    let reply = await getAsync("role_" + 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,
          },
        });
      }

      // ตรวจสอบว่ามีสิทธิ์อย่างน้อยหนึ่งอย่าง (posMaster หรือ acting position)
      if (!posMaster && !actingData.isAct) {
        throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลสิทธิ์");
      }

      let getDetail: any = null;
      let roleAttrData: any[] = [];

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

        roleAttrData = await this.authRoleAttrRepo.find({
          select: [
            "authSysId",
            "parentNode",
            "attrOwnership",
            "attrIsCreate",
            "attrIsList",
            "attrIsGet",
            "attrIsUpdate",
            "attrIsDelete",
            "attrPrivilege",
          ],
          where: { authRoleId: getDetail.id },
        });
      } else {
        // ถ้าไม่มี posMaster แต่มี acting: สร้าง getDetail เปล่าๆ
        getDetail = {
          id: null,
          roleName: "Acting",
          roleDescription: "สิทธิ์จากตำแหน่งรักษาการ",
        };
      }

      // ถ้ามี acting positions ให้รวมสิทธิ์
      if (actingData.isAct && actingData.posMasterActs.length > 0) {
        // ดึง authRoleId ของทุกตำแหน่งรักษาการ
        const actingAuthRoleIds = await this.posMasterActRepo
          .createQueryBuilder("posMasterAct")
          .leftJoin("posMasterAct.posMaster", "posMaster")
          .select("posMaster.authRoleId", "authRoleId")
          .leftJoin("posMasterAct.posMasterChild", "posMasterChild")
          .leftJoin("posMasterChild.current_holder", "profile")
          .where("profile.id = :profileId", { profileId: profile.id })
          .andWhere("posMaster.orgRevisionId = :orgRevisionId", { orgRevisionId: orgRevision?.id })
          .getRawMany();

        // ดึง AuthRoleAttr ทั้งหมดของ acting roles
        const actingRoleIds = actingAuthRoleIds.map(x => x.authRoleId).filter(id => id != null);
        const actingRoleAttrs = await this.authRoleAttrRepo.find({
          select: [
            "authSysId",
            "parentNode",
            "attrOwnership",
            "attrIsCreate",
            "attrIsList",
            "attrIsGet",
            "attrIsUpdate",
            "attrIsDelete",
            "attrPrivilege",
          ],
          where: { authRoleId: In(actingRoleIds) as any },
        });

        // ลำดับความสำคัญของ privilege (มากไปน้อย)
        const privilegePriority: Record<string, number> = {
          "OWNER": 7,
          "PARENT": 6,
          "ROOT": 5,
          "BROTHER": 4,
          "CHILD": 3,
          "NORMAL": 2,
          "SPECIFIC": 1,
          "null": 0,
        };

        // ฟังก์ชันเปรียบเทียบ privilege
        const getHigherPrivilege = (priv1: string | null, priv2: string | null): string | null => {
          const p1 = priv1 ?? "null";
          const p2 = priv2 ?? "null";
          const priority1 = privilegePriority[p1] ?? 0;
          const priority2 = privilegePriority[p2] ?? 0;
          return priority1 >= priority2 ? priv1 : priv2;
        };

        // ฟังก์ชันเปรียบเทียบ ownership (OWNER > STAFF > null)
        const getHigherOwnership = (own1: string | null, own2: string | null): string | null => {
          if (own1 === "OWNER" || own2 === "OWNER") return "OWNER";
          if (own1 === "STAFF" || own2 === "STAFF") return "STAFF";
          return null;
        };

        // สร้าง map ของ authSysId -> สิทธิ์ที่ดีที่สุดจาก acting
        const actingPermissionMap = new Map<string, any>();

        for (const attr of actingRoleAttrs) {
          const key = attr.authSysId;
          if (!actingPermissionMap.has(key)) {
            actingPermissionMap.set(key, attr);
          } else {
            const existing = actingPermissionMap.get(key);
            actingPermissionMap.set(key, {
              ...attr,
              attrIsCreate: existing.attrIsCreate || attr.attrIsCreate,
              attrIsList: existing.attrIsList || attr.attrIsList,
              attrIsGet: existing.attrIsGet || attr.attrIsGet,
              attrIsUpdate: existing.attrIsUpdate || attr.attrIsUpdate,
              attrIsDelete: existing.attrIsDelete || attr.attrIsDelete,
              attrPrivilege: getHigherPrivilege(attr.attrPrivilege, existing.attrPrivilege),
              parentNode: attr.parentNode,
              attrOwnership: getHigherOwnership(attr.attrOwnership, existing.attrOwnership),
            });
          }
        }

        // รวมกับสิทธิ์พื้นฐานของ User
        const mergedRoleAttrs = roleAttrData.map((baseAttr) => {
          const actingAttr = actingPermissionMap.get(baseAttr.authSysId);
          if (actingAttr) {
            return {
              ...baseAttr,
              parentNode: actingAttr.parentNode,
              attrOwnership: getHigherOwnership(actingAttr.attrOwnership, baseAttr.attrOwnership),
              attrIsCreate: actingAttr.attrIsCreate || baseAttr.attrIsCreate,
              attrIsList: actingAttr.attrIsList || baseAttr.attrIsList,
              attrIsGet: actingAttr.attrIsGet || baseAttr.attrIsGet,
              attrIsUpdate: actingAttr.attrIsUpdate || baseAttr.attrIsUpdate,
              attrIsDelete: actingAttr.attrIsDelete || baseAttr.attrIsDelete,
              attrPrivilege: getHigherPrivilege(actingAttr.attrPrivilege, baseAttr.attrPrivilege),
              _isActing: true,
            };
          }
          return baseAttr;
        });

        // เพิ่มระบบที่มีเฉพาะใน acting roles
        for (const [authSysId, actingAttr] of actingPermissionMap) {
          if (!roleAttrData.find(a => a.authSysId === authSysId)) {
            mergedRoleAttrs.push({
              ...actingAttr,
              _isActing: true,
            });
          }
        }

        reply = {
          ...getDetail,
          roles: mergedRoleAttrs,
        };
      } else {
        reply = {
          ...getDetail,
          roles: roleAttrData,
        };
      }

      redisClient.setex("role_" + profile.id, 86400, JSON.stringify(reply));
    }
    return reply;
    } finally {
      if (redisClient) {
        redisClient.quit();
      }
    }
  }

  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) {
    let redisClient;
    try {
      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, "ไม่พบข้อมูลบุคคลนี้ในระบบ");
      }
    }

    // Query ตำแหน่งรักษาการ
    const orgRevision = await this.orgRevisionRepository.findOne({
      select: ["id"],
      where: {
        orgRevisionIsDraft: false,
        orgRevisionIsCurrent: true,
      },
    });

    const actingData = await actingPositionService.getActingPositionsWithPrivilege(
      profile.id,
      orgRevision?.id
    );

    // ใช้ cache key เดิม
    let reply = await getAsync("posMaster_" + profile.id);
    if (reply != null) {
      reply = JSON.parse(reply);
    } else {
      let privilege = await this.Permission(request, system, action);

      // ถ้ากำลังรักษาการ ให้ดึง org จาก acting position
      if (actingData.isAct) {
        // ดึงข้อมูล permission เพื่อเช็คว่าระบบนี้มาจาก acting หรือไม่
        const permData: any = await this.getPermissionFunc(request);
        const role = permData.roles.find((r: any) => r.authSysId === system);

        if (role && role._isActing) {
          // ระบบนี้มาจาก acting position ดึง org จาก acting
          const actingOrgData = await this.getActingOrgScope(profile.id, orgRevision?.id, system, profileType);
          reply = {
            orgRootId: actingOrgData.orgRootId,
            orgChild1Id: actingOrgData.orgChild1Id,
            orgChild2Id: actingOrgData.orgChild2Id,
            orgChild3Id: actingOrgData.orgChild3Id,
            orgChild4Id: actingOrgData.orgChild4Id,
            privilege: privilege,
          };
        } else {
          // ระบบนี้มาจากตำแหน่งปกติ ใช้ org ปกติ
          reply = await this.getBaseOrgScope(profile.id, orgRevision?.id, profileType, privilege);
        }
      } else {
        // ไม่มี acting ใช้ org ปกติ
        reply = await this.getBaseOrgScope(profile.id, orgRevision?.id, profileType, privilege);
      }

      redisClient.setex("posMaster_" + profile.id, 86400, JSON.stringify(reply));
    }
    return reply;
    } finally {
      if (redisClient) {
        redisClient.quit();
      }
    }
  }

  // Helper method: ดึง org scope จากตำแหน่งปกติ
  private async getBaseOrgScope(profileId: string, orgRevisionId: string | undefined, profileType: string, privilege: any) {
    if (profileType == "OFFICER") {
      const posMaster = await this.posMasterRepository.findOne({
        where: {
          current_holderId: profileId,
          orgRevisionId: orgRevisionId,
        },
      });
      if (!posMaster) {
        return {
          orgRootId: null,
          orgChild1Id: null,
          orgChild2Id: null,
          orgChild3Id: null,
          orgChild4Id: null,
          privilege: privilege,
        };
      } else {
        return {
          orgRootId: posMaster.orgRootId,
          orgChild1Id: posMaster.orgChild1Id,
          orgChild2Id: posMaster.orgChild2Id,
          orgChild3Id: posMaster.orgChild3Id,
          orgChild4Id: posMaster.orgChild4Id,
          privilege: privilege,
        };
      }
    } else {
      const posMaster = await this.posMasterEmpRepository.findOne({
        where: {
          current_holderId: profileId,
          orgRevisionId: orgRevisionId,
        },
      });
      if (!posMaster) {
        return {
          orgRootId: null,
          orgChild1Id: null,
          orgChild2Id: null,
          orgChild3Id: null,
          orgChild4Id: null,
          privilege: privilege,
        };
      } else {
        return {
          orgRootId: posMaster.orgRootId,
          orgChild1Id: posMaster.orgChild1Id,
          orgChild2Id: posMaster.orgChild2Id,
          orgChild3Id: posMaster.orgChild3Id,
          orgChild4Id: posMaster.orgChild4Id,
          privilege: privilege,
        };
      }
    }
  }

  // Helper method: ดึง org scope จาก acting position ที่มีสิทธิ์ในระบบนั้น
  private async getActingOrgScope(profileId: string, orgRevisionId: string | undefined, system: string, profileType: string) {
    const repo = profileType === "OFFICER" ? this.posMasterRepository : this.posMasterEmpRepository;

    const actingOrgData = await this.posMasterActRepo
      .createQueryBuilder("posMasterAct")
      .leftJoin("posMasterAct.posMaster", "posMaster")
      .select([
        "posMaster.orgRootId",
        "posMaster.orgChild1Id",
        "posMaster.orgChild2Id",
        "posMaster.orgChild3Id",
        "posMaster.orgChild4Id",
      ])
      .leftJoin("posMasterAct.posMasterChild", "posMasterChild")
      .leftJoin("posMasterChild.current_holder", "profile")
      .where("profile.id = :profileId", { profileId })
      .andWhere("posMaster.orgRevisionId = :orgRevisionId", { orgRevisionId })
      .orderBy("posMasterAct.posMasterOrder", "ASC")
      .getRawOne();

    if (!actingOrgData) {
      // ไม่พบ acting position คืนค่า null
      return {
        orgRootId: null,
        orgChild1Id: null,
        orgChild2Id: null,
        orgChild3Id: null,
        orgChild4Id: null,
      };
    }

    return {
      orgRootId: actingOrgData.orgRootId,
      orgChild1Id: actingOrgData.orgChild1Id,
      orgChild2Id: actingOrgData.orgChild2Id,
      orgChild3Id: actingOrgData.orgChild3Id,
      orgChild4Id: actingOrgData.orgChild4Id,
    };
  }

  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) {
    let redisClient;
    try {
      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);
    } finally {
      if (redisClient) {
        redisClient.quit();
      }
    }
  }
}
