import amqp from "amqplib";
import { AppDataSource } from "../database/data-source";
import { Command } from "../entities/Command";
import { chunkArray, commandTypePath } from "../interfaces/utils";
import CallAPI from "../interfaces/call-api";
import HttpError from "../interfaces/http-error";
import HttpStatusCode from "../interfaces/http-status";
import { PosMaster } from "../entities/PosMaster";
import { Profile } from "../entities/Profile";
import { EmployeePosMaster } from "../entities/EmployeePosMaster";
import { EmployeeTempPosMaster } from "../entities/EmployeeTempPosMaster";
import { ProfileEmployee } from "../entities/ProfileEmployee";
import { OrgRevision } from "../entities/OrgRevision";
import { EmployeePosition } from "../entities/EmployeePosition";
import { OrgChild1 } from "../entities/OrgChild1";
import { OrgChild2 } from "../entities/OrgChild2";
import { OrgChild3 } from "../entities/OrgChild3";
import { OrgChild4 } from "../entities/OrgChild4";
import { OrgRoot } from "../entities/OrgRoot";
import { PosMasterAssign } from "../entities/PosMasterAssign";
import { Position } from "../entities/Position";
import { In, Not } from "typeorm";
import { PosMasterAct } from "../entities/PosMasterAct";
import { PermissionOrg } from "../entities/PermissionOrg";
import { sendWebSocket } from "./webSocket";
import { CreatePosMasterHistoryOfficer } from "./PositionService";
import { PayloadSendNoti } from "../interfaces/utils";

export let sendToQueue: (payload: any) => void;
export let sendToQueueOrg: (payload: any) => void;
export let sendToQueueOrgDraft: (payload: any) => void;
export let sendToQueueCommandNoti: (payload: any) => void;
export async function init() {
  //----> (1) Producer
  if (
    !process.env.AMQ_URL ||
    !process.env.AMQ_QUEUE ||
    !process.env.AMQ_QUEUE_ORG ||
    !process.env.AMQ_QUEUE_ORG_DRAFT ||
    !process.env.AMQ_QUEUE_COMMAND_NOTI
  )
    return;

  const {
    AMQ_URL: url,
    AMQ_QUEUE: queue,
    AMQ_QUEUE_ORG: queue_org,
    AMQ_QUEUE_ORG_DRAFT: queue_org_draft,
    AMQ_QUEUE_COMMAND_NOTI: queue_command_noti,
  } = process.env; //----> (1.2) get url and queue from .env

  const connection = await amqp.connect(url); //----> (1.3) set up url with amqp protocol

  console.log(connection ? "[AMQ] Connection success" : "[AMQ] Connection failed");

  const channel = await connection.createChannel(); //----> (1.4) create Channel

  console.log(channel ? "[AMQ] Create channel success" : "[AMQ] Create channel failed");

  channel.assertQueue(queue, { durable: true }), //----> (1.5) assert queue and set durable (if "true" save to disk on RabbitMQ)
    channel.assertQueue(queue_org, { durable: true }),
    channel.assertQueue(queue_org_draft, { durable: true }),
    channel.assertQueue(queue_command_noti, { durable: true }),
    channel.prefetch(1);

  sendToQueue = (payload: any, persistent = true) => {
    //----> (2) sendQueue To RabbitMQ and set persistent (if "true" redo the failed queue when server run again)
    channel.sendToQueue(queue, Buffer.from(JSON.stringify(payload)), {
      persistent,
    });
  };

  sendToQueueOrg = (payload: any, persistent = true) => {
    channel.sendToQueue(queue_org, Buffer.from(JSON.stringify(payload)), { persistent });
  };

  sendToQueueOrgDraft = (payload: any, persistent = true) => {
    channel.sendToQueue(queue_org_draft, Buffer.from(JSON.stringify(payload)), { persistent });
  };

  sendToQueueCommandNoti = (payload: any, persistent = true) => {
    channel.sendToQueue(queue_command_noti, Buffer.from(JSON.stringify(payload)), { persistent });
  };

  console.log("[AMQ] Listening for message...");
  createConsumer(queue, channel, handler), //----> (3) Process Consumer
  createConsumer(queue_org, channel, handler_org);
  createConsumer(queue_org_draft, channel, handler_org_draft);
  createConsumer(queue_command_noti, channel, handler_command_noti);
  // createConsumer(queue2, channel, handler2);
}

let retries = 0;

function createConsumer( //----> consumer
  queue: string,
  channel: amqp.Channel,
  handler: (msg: amqp.ConsumeMessage) => Promise<boolean> | boolean,
) {
  channel.consume(
    queue,
    async (msg) => {
      if (!msg) return;
      if ((await handler(msg)) || retries++ >= 3) {
        retries = 0;
        console.log("[AMQ] Process Consumer success");
        return channel.ack(msg);
      }
      console.log("[AMQ] Process Consumer failed");
      return await new Promise((resolve) => setTimeout(() => resolve(channel.nack(msg)), 3000));
    },
    { noAck: false },
  );
}

async function handler(msg: amqp.ConsumeMessage): Promise<boolean> {
  //----> condition before process consumer
  // const repo = AppDataSource.getRepository(Command);
  // const { data, token, user } = JSON.parse(msg.content.toString());
  // const { id, status, lastUpdateUserId, lastUpdateFullName, lastUpdatedAt } = data;
  // const command = await repo.findOne({
  //   where: { id: id },
  //   relations: ["commandType", "commandRecives"],
  // });
  // if (!command) return true;
  // let waiting_message = `ระบบทำการออกคำสั่งเลขที่ ${command.commandNo}/${command.commandYear + 543}`;
  // let success_message = `ระบบออกคำสั่งเลขที่ ${command.commandNo}/${command.commandYear + 543} เสร็จสิ้น`;
  // let error_message = `ระบบออกคำสั่งเลขที่ ${command.commandNo}/${command.commandYear + 543} ผิดพลาด`
  // if(command.commandType?.code == "C-PM-47"){
  //   waiting_message = `ระบบทำการออกคำสั่งเลขที่ ${command.commandNo}`;
  //   success_message = `ระบบออกคำสั่งเลขที่ ${command.commandNo} เสร็จสิ้น`;
  //   error_message = `ระบบออกคำสั่งเลขที่ ${command.commandNo} ผิดพลาด`;
  // }
  // if (user) {
  //   sendWebSocket(
  //     "send-command-notification",
  //     {
  //       success: true,
  //       message: waiting_message,
  //       payload: command,
  //     },
  //     { userId: user?.sub },
  //   ).catch(console.error);
  // }
  // const path = commandTypePath(command.commandType.code);
  // if (path == null) throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบประเภทคำสั่งนี้ในระบบ");
  // return await new CallAPI()
  //  //chunk 50
  //   .PostData(
  //     {
  //       headers: { authorization: token },
  //     },
  //     path + "/excecute",
  //     {
  //       refIds: command.commandRecives //chunk
  //         .filter((x) => x.refId != null)
  //         .map((x) => ({
  //           refId: x.refId,
  //           commandNo: command.commandNo,
  //           commandYear: command.commandYear,
  //           commandId: command.id,
  //           remark: command.positionDetail,
  //           amount: x.amount,
  //           amountSpecial: x.amountSpecial,
  //           positionSalaryAmount: x.positionSalaryAmount,
  //           mouthSalaryAmount: x.mouthSalaryAmount,
  //           commandCode: command.commandType.commandCode,
  //           commandName: command.commandType.name,
  //           commandDateAffect: command.commandExcecuteDate,
  //           commandDateSign: command.commandAffectDate,
  //         })),
  //     },
  //     false,
  //   )
  //   .then(async (res) => {
  //     console.log("[AMQ] Excecute Command Success");
  //     Object.assign(command, { status, lastUpdateUserId, lastUpdateFullName, lastUpdatedAt });
  //     const result = await repo.save(command).catch((e) => console.log(e));
  //     if (user) {
  //       sendWebSocket(
  //         "send-command-notification",
  //         {
  //           success: true,
  //           message: success_message,
  //           payload: command,
  //         },
  //         { userId: user?.sub },
  //       ).catch(console.error);
  //     }
  //     return !!result;
  //   })
  //   .catch((e) => {
  //     console.error(e);
  //     if (user) {
  //       sendWebSocket(
  //         "send-command-notification",
  //         {
  //           success: false,
  //           message: error_message,
  //           payload: command,
  //         },
  //         { userId: user?.sub },
  //       ).catch(console.error);
  //     }
  //     return false;
  //   });
  const repo = AppDataSource.getRepository(Command);
  const { data, token, user } = JSON.parse(msg.content.toString());
  const { id, status, lastUpdateUserId, lastUpdateFullName, lastUpdatedAt } = data;

  const command = await repo.findOne({
    where: { id: id },
    relations: ["commandType", "commandRecives"],
  });
  if (!command) return true;

  let waiting_message = `ระบบทำการออกคำสั่งเลขที่ ${command.commandNo}/${command.commandYear + 543}`;
  let success_message = `ระบบออกคำสั่งเลขที่ ${command.commandNo}/${command.commandYear + 543} เสร็จสิ้น`;
  let error_message = `ระบบออกคำสั่งเลขที่ ${command.commandNo}/${command.commandYear + 543} ผิดพลาด`;

  if (command.commandType?.code == "C-PM-47") {
    waiting_message = `ระบบทำการออกคำสั่งเลขที่ ${command.commandNo}`;
    success_message = `ระบบออกคำสั่งเลขที่ ${command.commandNo} เสร็จสิ้น`;
    error_message = `ระบบออกคำสั่งเลขที่ ${command.commandNo} ผิดพลาด`;
  }

  if (user) {
    sendWebSocket(
      "send-command-notification",
      { success: true, message: waiting_message, payload: command },
      { userId: user?.sub },
    ).catch(console.error);
  }

  const path = commandTypePath(command.commandType.code);
  if (path == null) throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบประเภทคำสั่งนี้ในระบบ");

  try {
    const allRefIds = new Set<string>();
    const chunks = chunkArray(
      command.commandRecives
        .filter((x) => x.refId != null)
        .map((x) => {
          const key = `${x.refId}-${command.id}`;
          if (allRefIds.has(key)) {
            return null;
          }
          allRefIds.add(key);

          return {
            refId: x.refId,
            commandNo: command.commandNo,
            commandYear: command.commandYear,
            commandId: command.id,
            remark: command.positionDetail,
            amount: x.amount,
            amountSpecial: x.amountSpecial,
            positionSalaryAmount: x.positionSalaryAmount,
            mouthSalaryAmount: x.mouthSalaryAmount,
            commandCode: command.commandType.commandCode,
            commandName: command.commandType.name,
            commandDateAffect: command.commandExcecuteDate,
            commandDateSign: command.commandAffectDate,
          };
        })
        .filter(Boolean),
      20,
    );

    for (const chunk of chunks) {
      await new CallAPI().PostData(
        { headers: { authorization: token } },
        path + "/excecute",
        { refIds: chunk },
        false,
      );
    }

    Object.assign(command, { status, lastUpdateUserId, lastUpdateFullName, lastUpdatedAt });
    const result = await repo.save(command);

    if (user) {
      sendWebSocket(
        "send-command-notification",
        { success: true, message: success_message, payload: command },
        { userId: user?.sub },
      ).catch(console.error);
    }

    console.log("[AMQ] Excecute Command Success");
    return !!result;
  } catch (e) {
    console.error(e);
    if (user) {
      sendWebSocket(
        "send-command-notification",
        { success: false, message: error_message, payload: command },
        { userId: user?.sub },
      ).catch(console.error);
    }
    return false;
  }
}

// async function handler(msg: amqp.ConsumeMessage): Promise<boolean> {
//   const repo = AppDataSource.getRepository(Command);
//   const { data, token, user } = JSON.parse(msg.content.toString());
//   const { id, status, lastUpdateUserId, lastUpdateFullName, lastUpdatedAt } = data;

//   const command = await repo.findOne({
//     where: { id },
//     relations: ["commandType", "commandRecives"],
//   });

//   if (!command) return true;

//   if (user) {
//     sendWebSocket(
//       "send-command-notification",
//       {
//         success: true,
//         message: `ระบบทำการออกคำสั่งเลขที่ ${command.commandNo}/${command.commandYear + 543}`,
//         payload: command,
//       },
//       { userId: user?.sub },
//     ).catch(console.error);
//   }

//   const path = commandTypePath(command.commandType.code);
//   if (path == null) throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบประเภทคำสั่งนี้ในระบบ");

//   const recivers = command.commandRecives
//     .filter((x) => x.refId != null)
//     .map((x) => ({
//       refId: x.refId,
//       commandNo: command.commandNo,
//       commandYear: command.commandYear,
//       commandId: command.id,
//       remark: command.positionDetail,
//       amount: x.amount,
//       amountSpecial: x.amountSpecial,
//       positionSalaryAmount: x.positionSalaryAmount,
//       mouthSalaryAmount: x.mouthSalaryAmount,
//       commandCode: command.commandType.commandCode,
//       commandName: command.commandType.name,
//       commandDateAffect: command.commandExcecuteDate,
//       commandDateSign: command.commandAffectDate,
//     }));

//   const batchSize = 50;
//   const batches = Array.from({ length: Math.ceil(recivers.length / batchSize) }, (_, i) =>
//     recivers.slice(i * batchSize, i * batchSize + batchSize)
//   );

//   const api = new CallAPI();
//   try {
//     for (const batch of batches) {
//       await api.PostData(
//         { headers: { authorization: token } },
//         path + "/excecute",
//         { refIds: batch },
//         false
//       );
//     }

//     console.log("[AMQ] Excecute Command Success");
//     Object.assign(command, { status, lastUpdateUserId, lastUpdateFullName, lastUpdatedAt });
//     const result = await repo.save(command);

//     if (user) {
//       sendWebSocket(
//         "send-command-notification",
//         {
//           success: true,
//           message: `ระบบออกคำสั่งเลขที่ ${command.commandNo}/${command.commandYear + 543} เสร็จสิ้น`,
//           payload: command,
//         },
//         { userId: user?.sub },
//       ).catch(console.error);
//     }

//     return !!result;
//   } catch (e) {
//     console.error(e);
//     if (user) {
//       sendWebSocket(
//         "send-command-notification",
//         {
//           success: false,
//           message: `ระบบออกคำสั่งเลขที่ ${command.commandNo}/${command.commandYear + 543} ผิดพลาด`,
//           payload: command,
//         },
//         { userId: user?.sub },
//       ).catch(console.error);
//     }
//     return false;
//   }
// }

async function handler_command_noti(msg: amqp.ConsumeMessage): Promise<boolean> {
  const { data, token, user } = JSON.parse(msg.content.toString());
  const { profiles, command } = data;

  try {
    let profilesNotiRequest: Promise<any> | undefined;
    if (!(["C-PM-10"].includes(command.commandType.code))) {
      profilesNotiRequest = new CallAPI()
      .PostData(
        { headers: { authorization: token } },
        "/placement/noti/profiles",
        {
          subject: `${command.issue}`,
          body: `${command.issue}`,
          receiverUserIds: profiles,
          payload: "", // แนบไฟล์ (ถ้าจำเป็น)
          isSendMail: true,
          isSendInbox: true,
          isSendNotification: true,
        },
        false,
      )
      .catch((error) => {
        if (error.response) {
          // Server ตอบกลับ (มี status code 4xx หรือ 5xx)
          console.error("Error status:", error.response.status);
          console.error("Error data:", error.response.data);
          console.error("Error headers:", error.response.headers);
        } else if (error.request) {
          // ไม่มีการตอบกลับจาก server
          console.error("No response received:", error.request);
        } else {
          // เกิดข้อผิดพลาดอื่น เช่น โค้ด Axios ผิด
          console.error("Axios error:", error.message);
        }
        console.error("Full error object:", error);
      });
    }

    let profilesSend =
      command && command.commandSends.length > 0
        ? command.commandSends
            .filter((x: any) => x.profileId != null)
            .map((x: any) => ({
              receiverUserId: x.profileId,
              notiLink: "",
              isSendMail: x.commandSendCCs.map((x: any) => x.name == "EMAIL").length > 0,
              isSendInbox: x.commandSendCCs.map((x: any) => x.name == "INBOX").length > 0,
              isSendNotification: true,
            }))
        : [];
    const payloadStr = await PayloadSendNoti(command.id);        
    const profilesSendRequest = new CallAPI()
      .PostData(
        { headers: { authorization: token } },
        "/placement/noti/profiles-send",
        {
          subject: `${command.issue}`,
          body: `${command.issue}`,
          receiverUserIds: profilesSend,
          payload: payloadStr, // แนบไฟล์ (ถ้าจำเป็น)
        },
        false,
      )
      .catch((error) => {
        if (error.response) {
          // Server ตอบกลับ (มี status code 4xx หรือ 5xx)
          console.error("Error status:", error.response.status);
          console.error("Error data:", error.response.data);
          console.error("Error headers:", error.response.headers);
        } else if (error.request) {
          // ไม่มีการตอบกลับจาก server
          console.error("No response received:", error.request);
        } else {
          // เกิดข้อผิดพลาดอื่น เช่น โค้ด Axios ผิด
          console.error("Axios error:", error.message);
        }
        console.error("Full error object:", error);
      });

    /*เฉพาะคำสั่ง C-PM-10 ให้ตัด profilesNotiRequest ที่ส่ง noti ครั้งแรกออก*/
    if (["C-PM-10"].includes(command.commandType.code)) {
      await Promise.all([profilesSendRequest]);
    }
    else {
      await Promise.all([profilesNotiRequest!, profilesSendRequest]);
    }

    console.log("[AMQ] Send Notification Success");
    return true;
  } catch (error) {
    console.error("[AMQ] Error:", error);
    return false;
  }
}

async function handler_org(msg: amqp.ConsumeMessage): Promise<boolean> {
  //----> condition before process consume
  const repoPosmaster = AppDataSource.getRepository(PosMaster);
  const repoEmployeePosmaster = AppDataSource.getRepository(EmployeePosMaster);
  const repoEmployeeTempPosmaster = AppDataSource.getRepository(EmployeeTempPosMaster);
  const repoProfile = AppDataSource.getRepository(Profile);
  const repoProfileEmployee = AppDataSource.getRepository(ProfileEmployee);
  const employeePositionRepository = AppDataSource.getRepository(EmployeePosition);
  const repoOrgRevision = AppDataSource.getRepository(OrgRevision);
  const orgRootRepository = AppDataSource.getRepository(OrgRoot);
  const child1Repository = AppDataSource.getRepository(OrgChild1);
  const child2Repository = AppDataSource.getRepository(OrgChild2);
  const child3Repository = AppDataSource.getRepository(OrgChild3);
  const child4Repository = AppDataSource.getRepository(OrgChild4);
  const { data, token, user } = JSON.parse(msg.content.toString());
  const { id, status, lastUpdateUserId, lastUpdateFullName, lastUpdatedAt } = data;
  if (user) {
    sendWebSocket(
      "send-publish-org",
      {
        success: true,
        message: `ระบบกำลังทำการเผยแพร่โครงสร้างหน่วยงาน`,
      },
      { userId: user?.sub },
    ).catch(console.error);
  }
  const orgRevisionPublish = await repoOrgRevision
    .createQueryBuilder("orgRevision")
    .where("orgRevision.orgRevisionIsDraft = false")
    .andWhere("orgRevision.orgRevisionIsCurrent = true")
    .getOne();

  const orgRevisionDraft = await repoOrgRevision
    .createQueryBuilder("orgRevision")
    .where("orgRevision.orgRevisionIsDraft = true")
    .andWhere("orgRevision.orgRevisionIsCurrent = false")
    .getOne();
  if (orgRevisionPublish) {
    //เข้าเงื่อนไขจะเปลี่ยนสถานะ orgRevisionPublish เป็นไม่ใช่ current และไม่เป็น daft
    orgRevisionPublish.orgRevisionIsDraft = false;
    orgRevisionPublish.orgRevisionIsCurrent = false;
    await repoOrgRevision.save(orgRevisionPublish);
  }
  if (orgRevisionDraft) {
    //เข้าเงื่อนไขจะเปลี่ยนสถานะ orgRevisionDraft เป็นไม่ใช่ daft และเป็น current
    orgRevisionDraft.orgRevisionIsCurrent = true;
    orgRevisionDraft.orgRevisionIsDraft = false;
    await repoOrgRevision.save(orgRevisionDraft);
  }
  try {
    const posMaster = await repoPosmaster.find({
      where: { orgRevisionId: id },
      relations: [
        "orgRoot",
        "orgChild4",
        "orgChild3",
        "orgChild2",
        "orgChild1",
        "positions",
        "positions.posLevel",
        "positions.posType",
        "positions.posExecutive",
      ],
    });
    const _null: any = null;
    for (const item of posMaster) {
      if (item.next_holderId != null) {
        const profile = await repoProfile.findOne({
          where: { id: item.next_holderId == null ? "" : item.next_holderId },
        });
        if (profile != null && item.positions.length > 0) {
          let position = await item.positions.find((x) => x.positionIsSelected == true);
          if (position == null) {
            position = await item.positions.find((x) => x.posLevelId == profile?.posLevelId);
            if (position == null) {
              position = await item.positions.sort((a, b) => a.orderNo - b.orderNo)[0];
            }
          }

          profile.posLevelId = position?.posLevelId ?? _null;
          profile.posTypeId = position?.posTypeId ?? _null;
          profile.position = position?.positionName ?? _null;
          await repoProfile.save(profile);
        }
      }
      item.current_holderId = item.next_holderId;
      // item.conditionReason = _null;
      // if (item.current_holderId) {
      //   item.conditionReason = _null;
      //   item.isCondition = false;
      // }
      item.next_holderId = null;
      item.lastUpdateUserId = lastUpdateUserId;
      item.lastUpdateFullName = lastUpdateFullName;
      item.lastUpdatedAt = lastUpdatedAt;
      await repoPosmaster.save(item).catch((e) => console.log(e));
      await CreatePosMasterHistoryOfficer(item.id, null);
    }
    if (orgRevisionPublish != null && orgRevisionDraft != null) {
      //new main revision
      const before = null;

      //ทุก orgRoot และ orgChild ข้างล่างนี้จะเป็นตัวเก่าที่ไม่ได้เป็น current revision
      //cone tree
      // if (
      //   orgRevisionPublish.typeDraft.toUpperCase() == "ORG" ||
      //   orgRevisionPublish.typeDraft.toUpperCase() == "ORG_POSITION" ||
      //   orgRevisionPublish.typeDraft.toUpperCase() == "ORG_POSITION_PERSON" ||
      //   orgRevisionPublish.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" ||
      //   orgRevisionPublish.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE"
      // ) {
      //หา dna tree
      const orgRoot = await orgRootRepository.find({
        where: { orgRevisionId: orgRevisionPublish.id },
      });

      const orgChild1 = await child1Repository.find({
        where: { orgRevisionId: orgRevisionPublish.id },
      });

      const orgChild2 = await child2Repository.find({
        where: { orgRevisionId: orgRevisionPublish.id },
      });

      const orgChild3 = await child3Repository.find({
        where: { orgRevisionId: orgRevisionPublish.id },
      });

      const orgChild4 = await child4Repository.find({
        where: { orgRevisionId: orgRevisionPublish.id },
      });

      //หา dna posmaster ถ้าไม่มีให้เอาตัวเองเป็น dna
      const orgemployeePosMaster = await repoEmployeePosmaster.find({
        where: { orgRevisionId: orgRevisionPublish.id },
        relations: ["positions"],
      });

      let _orgemployeePosMaster: EmployeePosMaster[];
      //   if (
      //     requestBody.typeDraft.toUpperCase() == "ORG_POSITION" ||
      //     requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON" ||
      //     requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" ||
      //     requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE"
      //   ) {
      // _orgemployeePosMaster = orgemployeePosMaster.map((x) => ({
      //   ...x,
      //   ancestorDNA:
      //     x.ancestorDNA == null || x.ancestorDNA == "00000000-0000-0000-0000-000000000000"
      //       ? x.id
      //       : x.ancestorDNA,
      // }));
      // await repoEmployeePosmaster.save(_orgemployeePosMaster);
      const validProfileIds = new Set(
        (await repoProfileEmployee.find({ select: ["id"] })).map((p) => p.id),
      );

      _orgemployeePosMaster = orgemployeePosMaster.map((x) => ({
        ...x,
        current_holderId:
          x.current_holderId && validProfileIds.has(x.current_holderId) ? x.current_holderId : null,
        ancestorDNA:
          !x.ancestorDNA || x.ancestorDNA === "00000000-0000-0000-0000-000000000000"
            ? x.id
            : x.ancestorDNA,
      }));
      await repoEmployeePosmaster
        .createQueryBuilder()
        .insert()
        .into(EmployeePosMaster)
        .values(_orgemployeePosMaster)
        .orUpdate({
          conflict_target: ["id"],
          overwrite: ["ancestorDNA"],
        })
        .execute();

      //   }
      //หา dna posmaster ถ้าไม่มีให้เอาตัวเองเป็น dna
      const orgemployeeTempPosMaster = await repoEmployeeTempPosmaster.find({
        where: { orgRevisionId: orgRevisionPublish.id },
        relations: ["positions"],
      });

      let _orgemployeeTempPosMaster: EmployeeTempPosMaster[];
      //   if (
      //     requestBody.typeDraft.toUpperCase() == "ORG_POSITION" ||
      //     requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON" ||
      //     requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" ||
      //     requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE"
      //   ) {
      _orgemployeeTempPosMaster = orgemployeeTempPosMaster.map((x) => ({
        ...x,
        ancestorDNA:
          x.ancestorDNA == null || x.ancestorDNA == "00000000-0000-0000-0000-000000000000"
            ? x.id
            : x.ancestorDNA,
      }));
      // await repoEmployeeTempPosmaster.save(_orgemployeeTempPosMaster);
      await repoEmployeeTempPosmaster
        .createQueryBuilder()
        .insert()
        .into(EmployeeTempPosMaster)
        .values(_orgemployeeTempPosMaster)
        .orUpdate({
          conflict_target: ["id"],
          overwrite: ["ancestorDNA"],
        })
        .execute();
      //   }

      //create org
      orgRoot.forEach(async (x: any) => {
        var dataId = x.id;

        const orgRootCurrent = await orgRootRepository.find({
          where: { orgRevisionId: orgRevisionDraft.id },
        });

        const matchedOrgRoot = orgRootCurrent.find((i: OrgRoot) => {
          if (
            x.ancestorDNA === x.id || // ถ้า ancestorDNA ถูกตั้งเป็น id ตัวเอง
            x.ancestorDNA === null ||
            x.ancestorDNA === "00000000-0000-0000-0000-000000000000"
          ) {
            return (
              i.ancestorDNA === null || i.ancestorDNA === "00000000-0000-0000-0000-000000000000"
            );
          }
          return i.ancestorDNA === x.ancestorDNA;
        });

        // if (
        //   requestBody.typeDraft.toUpperCase() == "ORG_POSITION" ||
        //   requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON" ||
        //   requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" ||
        //   requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE"
        // ) {
        //create employeePosmaster
        await Promise.all(
          _orgemployeePosMaster
            .filter((x: EmployeePosMaster) => x.orgRootId == dataId && x.orgChild1Id == null)
            .map(async (item: any) => {
              delete item.id;
              const employeePosMaster = Object.assign(new EmployeePosMaster(), item);
              employeePosMaster.positions = [];
              // if (
              //   requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON" ||
              //   requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE"
              // ) {
              //   employeePosMaster.current_holderId = item.current_holderId;
              // } else {
              //   // employeePosMaster.next_holderId = null;
              //   employeePosMaster.isSit = false;
              // }
              // if (
              //   requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" ||
              //   requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE"
              // ) {
              //   employeePosMaster.authRoleId = item.authRoleId;
              // } else {
              //   employeePosMaster.authRoleId = null;
              // }
              //   employeePosMaster.current_holderId = null;
              employeePosMaster.orgRevisionId = orgRevisionDraft.id;
              employeePosMaster.orgRootId = matchedOrgRoot?.id ?? null;
              employeePosMaster.createdUserId = "";
              employeePosMaster.createdFullName = "System Administrator";
              employeePosMaster.createdAt = new Date();
              employeePosMaster.lastUpdateUserId = "";
              employeePosMaster.lastUpdateFullName = "System Administrator";
              employeePosMaster.lastUpdatedAt = new Date();
              await repoEmployeePosmaster.save(employeePosMaster);

              //create employeePosition
              item.positions.map(async (pos: any) => {
                delete pos.id;
                const employeePosition: EmployeePosition = Object.assign(
                  new EmployeePosition(),
                  pos,
                );
                employeePosition.posMasterId = employeePosMaster.id;
                //   if (
                //     requestBody.typeDraft.toUpperCase() == "ORG_POSITION" ||
                //     requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE"
                //   ) {
                //     employeePosition.positionIsSelected = false;
                //   }
                employeePosition.createdUserId = "";
                employeePosition.createdFullName = "System Administrator";
                employeePosition.createdAt = new Date();
                employeePosition.lastUpdateUserId = "";
                employeePosition.lastUpdateFullName = "System Administrator";
                employeePosition.lastUpdatedAt = new Date();
                await employeePositionRepository.save(employeePosition);
              });
            }),
        );
        //create employeeTempPosmaster
        await Promise.all(
          _orgemployeeTempPosMaster
            .filter((x: EmployeeTempPosMaster) => x.orgRootId == dataId && x.orgChild1Id == null)
            .map(async (item: any) => {
              delete item.id;
              const employeeTempPosMaster = Object.assign(new EmployeeTempPosMaster(), item);
              employeeTempPosMaster.positions = [];
              // if (
              //   requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON" ||
              //   requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE"
              // ) {
              //   employeeTempPosMaster.current_holderId = item.current_holderId;
              // } else {
              //   // employeeTempPosMaster.next_holderId = null;
              //   employeeTempPosMaster.isSit = false;
              // }
              // if (
              //   requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" ||
              //   requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE"
              // ) {
              //   employeeTempPosMaster.authRoleId = item.authRoleId;
              // } else {
              //   employeeTempPosMaster.authRoleId = null;
              // }
              //   employeeTempPosMaster.current_holderId = null;
              employeeTempPosMaster.orgRevisionId = orgRevisionDraft.id;
              employeeTempPosMaster.orgRootId = matchedOrgRoot?.id ?? null;
              employeeTempPosMaster.createdUserId = "";
              employeeTempPosMaster.createdFullName = "System Administrator";
              employeeTempPosMaster.createdAt = new Date();
              employeeTempPosMaster.lastUpdateUserId = "";
              employeeTempPosMaster.lastUpdateFullName = "System Administrator";
              employeeTempPosMaster.lastUpdatedAt = new Date();
              await repoEmployeeTempPosmaster.save(employeeTempPosMaster);

              //create employeePosition
              item.positions.map(async (pos: any) => {
                delete pos.id;
                const employeePosition: EmployeePosition = Object.assign(
                  new EmployeePosition(),
                  pos,
                );
                employeePosition.posMasterTempId = employeeTempPosMaster.id;
                //   if (
                //     requestBody.typeDraft.toUpperCase() == "ORG_POSITION" ||
                //     requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE"
                //   ) {
                //     employeePosition.positionIsSelected = false;
                //   }
                employeePosition.createdUserId = "";
                employeePosition.createdFullName = "System Administrator";
                employeePosition.createdAt = new Date();
                employeePosition.lastUpdateUserId = "";
                employeePosition.lastUpdateFullName = "System Administrator";
                employeePosition.lastUpdatedAt = new Date();
                await employeePositionRepository.save(employeePosition);
              });
            }),
        );
        // }

        //create org
        orgChild1
          .filter((x: OrgChild1) => x.orgRootId == dataId)
          .forEach(async (x: any) => {
            var data1Id = x.id;
            const orgChild1Current = await child1Repository.find({
              where: { orgRevisionId: orgRevisionDraft.id },
            });

            const matchedOrgChild1 = orgChild1Current.find((i: OrgChild1) => {
              if (
                x.ancestorDNA === x.id || // ถ้า ancestorDNA ถูกตั้งเป็น id ตัวเอง
                x.ancestorDNA === null ||
                x.ancestorDNA === "00000000-0000-0000-0000-000000000000"
              ) {
                return (
                  i.ancestorDNA === null || i.ancestorDNA === "00000000-0000-0000-0000-000000000000"
                );
              }
              return i.ancestorDNA === x.ancestorDNA;
            });
            // ("[in case Child1] ancestorDNA", `${x.orgChild1Id == matchedOrgChild1?.id}`);
            // if (
            //   requestBody.typeDraft.toUpperCase() == "ORG_POSITION" ||
            //   requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON" ||
            //   requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" ||
            //   requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE"
            // ) {
            //create employeePosmaster
            await Promise.all(
              _orgemployeePosMaster
                .filter((x: EmployeePosMaster) => x.orgChild1Id == data1Id && x.orgChild2Id == null)
                .map(async (item: any) => {
                  delete item.id;
                  // console.log("[in case Child1] orgChild1Id == data1Id");
                  const employeePosMaster = Object.assign(new EmployeePosMaster(), item);
                  employeePosMaster.positions = [];
                  // if (
                  //   requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON" ||
                  //   requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE"
                  // ) {
                  //   employeePosMaster.current_holderId = item.current_holderId;
                  // } else {
                  //   // employeePosMaster.next_holderId = null;
                  //   employeePosMaster.isSit = false;
                  // }
                  // if (
                  //   requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" ||
                  //   requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE"
                  // ) {
                  //   employeePosMaster.authRoleId = item.authRoleId;
                  // } else {
                  //   employeePosMaster.authRoleId = null;
                  // }
                  //   employeePosMaster.current_holderId = null;
                  employeePosMaster.orgRevisionId = orgRevisionDraft.id;
                  employeePosMaster.orgRootId = matchedOrgRoot?.id ?? null;
                  employeePosMaster.orgChild1Id = matchedOrgChild1?.id ?? null;
                  employeePosMaster.createdUserId = "";
                  employeePosMaster.createdFullName = "System Administrator";
                  employeePosMaster.createdAt = new Date();
                  employeePosMaster.lastUpdateUserId = "";
                  employeePosMaster.lastUpdateFullName = "System Administrator";
                  employeePosMaster.lastUpdatedAt = new Date();
                  await repoEmployeePosmaster.save(employeePosMaster);

                  //create employeePosition
                  item.positions.map(async (pos: any) => {
                    delete pos.id;
                    const employeePosition: EmployeePosition = Object.assign(
                      new EmployeePosition(),
                      pos,
                    );
                    employeePosition.posMasterId = employeePosMaster.id;
                    //   if (
                    //     requestBody.typeDraft.toUpperCase() == "ORG_POSITION" ||
                    //     requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE"
                    //   ) {
                    //     employeePosition.positionIsSelected = false;
                    //   }
                    employeePosition.createdUserId = "";
                    employeePosition.createdFullName = "System Administrator";
                    employeePosition.createdAt = new Date();
                    employeePosition.lastUpdateUserId = "";
                    employeePosition.lastUpdateFullName = "System Administrator";
                    employeePosition.lastUpdatedAt = new Date();
                    await employeePositionRepository.save(employeePosition);
                  });
                }),
            );
            // create employeeTempPosmaster
            await Promise.all(
              _orgemployeeTempPosMaster
                .filter(
                  (x: EmployeeTempPosMaster) => x.orgChild1Id == data1Id && x.orgChild2Id == null,
                )
                .map(async (item: any) => {
                  delete item.id;
                  const employeeTempPosMaster = Object.assign(new EmployeeTempPosMaster(), item);
                  employeeTempPosMaster.positions = [];
                  // if (
                  //   requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON" ||
                  //   requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE"
                  // ) {
                  //   employeeTempPosMaster.current_holderId = item.current_holderId;
                  // } else {
                  //   // employeeTempPosMaster.next_holderId = null;
                  //   employeeTempPosMaster.isSit = false;
                  // }
                  // if (
                  //   requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" ||
                  //   requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE"
                  // ) {
                  //   employeeTempPosMaster.authRoleId = item.authRoleId;
                  // } else {
                  //   employeeTempPosMaster.authRoleId = null;
                  // }
                  //   employeeTempPosMaster.current_holderId = null;
                  employeeTempPosMaster.orgRevisionId = orgRevisionDraft.id;
                  employeeTempPosMaster.orgRootId = matchedOrgRoot?.id ?? null;
                  employeeTempPosMaster.orgChild1Id = matchedOrgChild1?.id ?? null;
                  employeeTempPosMaster.createdUserId = "";
                  employeeTempPosMaster.createdFullName = "System Administrator";
                  employeeTempPosMaster.createdAt = new Date();
                  employeeTempPosMaster.lastUpdateUserId = "";
                  employeeTempPosMaster.lastUpdateFullName = "System Administrator";
                  employeeTempPosMaster.lastUpdatedAt = new Date();
                  await repoEmployeeTempPosmaster.save(employeeTempPosMaster);

                  //create employeePosition
                  item.positions.map(async (pos: any) => {
                    delete pos.id;
                    const employeePosition: EmployeePosition = Object.assign(
                      new EmployeePosition(),
                      pos,
                    );
                    employeePosition.posMasterTempId = employeeTempPosMaster.id;
                    //   if (
                    //     requestBody.typeDraft.toUpperCase() == "ORG_POSITION" ||
                    //     requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE"
                    //   ) {
                    //     employeePosition.positionIsSelected = false;
                    //   }
                    employeePosition.createdUserId = "";
                    employeePosition.createdFullName = "System Administrator";
                    employeePosition.createdAt = new Date();
                    employeePosition.lastUpdateUserId = "";
                    employeePosition.lastUpdateFullName = "System Administrator";
                    employeePosition.lastUpdatedAt = new Date();
                    await employeePositionRepository.save(employeePosition);
                  });
                }),
            );
            // }

            //create org
            orgChild2
              .filter((x: OrgChild2) => x.orgChild1Id == data1Id)
              .forEach(async (x: any) => {
                var data2Id = x.id;
                const orgChild2Current = await child2Repository.find({
                  where: { orgRevisionId: orgRevisionDraft.id },
                });

                const matchedOrgChild2 = orgChild2Current.find((i: OrgChild2) => {
                  if (
                    x.ancestorDNA === x.id || // ถ้า ancestorDNA ถูกตั้งเป็น id ตัวเอง
                    x.ancestorDNA === null ||
                    x.ancestorDNA === "00000000-0000-0000-0000-000000000000"
                  ) {
                    return (
                      i.ancestorDNA === null ||
                      i.ancestorDNA === "00000000-0000-0000-0000-000000000000"
                    );
                  }
                  return i.ancestorDNA === x.ancestorDNA;
                });
                // console.log("[in case Child2] ancestorDNA", `${x.orgChild2Id == matchedOrgChild2?.id}`);
                // if (
                //   requestBody.typeDraft.toUpperCase() == "ORG_POSITION" ||
                //   requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON" ||
                //   requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" ||
                //   requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE"
                // ) {
                //create employeePosmaster
                await Promise.all(
                  _orgemployeePosMaster
                    .filter(
                      (x: EmployeePosMaster) => x.orgChild2Id == data2Id && x.orgChild3Id == null,
                    )
                    .map(async (item: any) => {
                      delete item.id;
                      // console.log("[in case Child2] orgChild2Id == data2Id");
                      const employeePosMaster = Object.assign(new EmployeePosMaster(), item);
                      employeePosMaster.positions = [];
                      // if (
                      //   requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON" ||
                      //   requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE"
                      // ) {
                      //   employeePosMaster.current_holderId = item.current_holderId;
                      // } else {
                      //   // employeePosMaster.next_holderId = null;
                      //   employeePosMaster.isSit = false;
                      // }
                      // if (
                      //   requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" ||
                      //   requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE"
                      // ) {
                      //   employeePosMaster.authRoleId = item.authRoleId;
                      // } else {
                      //   employeePosMaster.authRoleId = null;
                      // }
                      //   employeePosMaster.current_holderId = null;
                      employeePosMaster.orgRevisionId = orgRevisionDraft.id;
                      employeePosMaster.orgRootId = matchedOrgRoot?.id ?? null;
                      employeePosMaster.orgChild1Id = matchedOrgChild1?.id ?? null;
                      employeePosMaster.orgChild2Id = matchedOrgChild2?.id ?? null;
                      employeePosMaster.createdUserId = "";
                      employeePosMaster.createdFullName = "System Administrator";
                      employeePosMaster.createdAt = new Date();
                      employeePosMaster.lastUpdateUserId = "";
                      employeePosMaster.lastUpdateFullName = "System Administrator";
                      employeePosMaster.lastUpdatedAt = new Date();
                      await repoEmployeePosmaster.save(employeePosMaster);

                      //create employeePosition
                      item.positions.map(async (pos: any) => {
                        delete pos.id;
                        const employeePosition: EmployeePosition = Object.assign(
                          new EmployeePosition(),
                          pos,
                        );
                        employeePosition.posMasterId = employeePosMaster.id;
                        //   if (
                        //     requestBody.typeDraft.toUpperCase() == "ORG_POSITION" ||
                        //     requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE"
                        //   ) {
                        //     employeePosition.positionIsSelected = false;
                        //   }
                        employeePosition.createdUserId = "";
                        employeePosition.createdFullName = "System Administrator";
                        employeePosition.createdAt = new Date();
                        employeePosition.lastUpdateUserId = "";
                        employeePosition.lastUpdateFullName = "System Administrator";
                        employeePosition.lastUpdatedAt = new Date();
                        await employeePositionRepository.save(employeePosition);
                      });
                    }),
                );
                // create employeeTempPosmaster
                await Promise.all(
                  _orgemployeeTempPosMaster
                    .filter(
                      (x: EmployeeTempPosMaster) =>
                        x.orgChild2Id == data2Id && x.orgChild3Id == null,
                    )
                    .map(async (item: any) => {
                      delete item.id;
                      const employeeTempPosMaster = Object.assign(
                        new EmployeeTempPosMaster(),
                        item,
                      );
                      employeeTempPosMaster.positions = [];
                      // if (
                      //   requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON" ||
                      //   requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE"
                      // ) {
                      //   employeeTempPosMaster.current_holderId = item.current_holderId;
                      // } else {
                      //   // employeeTempPosMaster.next_holderId = null;
                      //   employeeTempPosMaster.isSit = false;
                      // }
                      // if (
                      //   requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" ||
                      //   requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE"
                      // ) {
                      //   employeeTempPosMaster.authRoleId = item.authRoleId;
                      // } else {
                      //   employeeTempPosMaster.authRoleId = null;
                      // }
                      //   employeeTempPosMaster.current_holderId = null;
                      employeeTempPosMaster.orgRevisionId = orgRevisionDraft.id;
                      employeeTempPosMaster.orgRootId = dataId;
                      employeeTempPosMaster.orgChild1Id = data1Id;
                      employeeTempPosMaster.orgChild2Id = data2Id;
                      employeeTempPosMaster.createdUserId = "";
                      employeeTempPosMaster.createdFullName = "System Administrator";
                      employeeTempPosMaster.createdAt = new Date();
                      employeeTempPosMaster.lastUpdateUserId = "";
                      employeeTempPosMaster.lastUpdateFullName = "System Administrator";
                      employeeTempPosMaster.lastUpdatedAt = new Date();
                      await repoEmployeeTempPosmaster.save(employeeTempPosMaster);

                      //create employeePosition
                      item.positions.map(async (pos: any) => {
                        delete pos.id;
                        const employeePosition: EmployeePosition = Object.assign(
                          new EmployeePosition(),
                          pos,
                        );
                        employeePosition.posMasterTempId = employeeTempPosMaster.id;
                        //   if (
                        //     requestBody.typeDraft.toUpperCase() == "ORG_POSITION" ||
                        //     requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE"
                        //   ) {
                        //     employeePosition.positionIsSelected = false;
                        //   }
                        employeePosition.createdUserId = "";
                        employeePosition.createdFullName = "System Administrator";
                        employeePosition.createdAt = new Date();
                        employeePosition.lastUpdateUserId = "";
                        employeePosition.lastUpdateFullName = "System Administrator";
                        employeePosition.lastUpdatedAt = new Date();
                        await employeePositionRepository.save(employeePosition);
                      });
                    }),
                );
                // }

                //create org
                orgChild3
                  .filter((x: OrgChild3) => x.orgChild2Id == data2Id)
                  .forEach(async (x: any) => {
                    var data3Id = x.id;
                    const orgChild3Current = await child3Repository.find({
                      where: { orgRevisionId: orgRevisionDraft.id },
                    });

                    const matchedOrgChild3 = orgChild3Current.find((i: OrgChild3) => {
                      if (
                        x.ancestorDNA === x.id || // ถ้า ancestorDNA ถูกตั้งเป็น id ตัวเอง
                        x.ancestorDNA === null ||
                        x.ancestorDNA === "00000000-0000-0000-0000-000000000000"
                      ) {
                        return (
                          i.ancestorDNA === null ||
                          i.ancestorDNA === "00000000-0000-0000-0000-000000000000"
                        );
                      }
                      return i.ancestorDNA === x.ancestorDNA;
                    });
                    // console.log("[in case Child3] ancestorDNA", `${x.orgChild3Id == matchedOrgChild3?.id}`);
                    // if (
                    //   requestBody.typeDraft.toUpperCase() == "ORG_POSITION" ||
                    //   requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON" ||
                    //   requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" ||
                    //   requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE"
                    // ) {
                    //create employeePosmaster
                    await Promise.all(
                      _orgemployeePosMaster
                        .filter(
                          (x: EmployeePosMaster) =>
                            x.orgChild3Id == data3Id && x.orgChild4Id == null,
                        )
                        .map(async (item: any) => {
                          delete item.id;
                          // console.log("[in case Child3] orgChild3Id == data3Id");
                          const employeePosMaster = Object.assign(new EmployeePosMaster(), item);
                          employeePosMaster.positions = [];
                          // if (
                          //   requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON" ||
                          //   requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE"
                          // ) {
                          //   employeePosMaster.current_holderId = item.current_holderId;
                          // } else {
                          //   // employeePosMaster.next_holderId = null;
                          //   employeePosMaster.isSit = false;
                          // }
                          // if (
                          //   requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" ||
                          //   requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE"
                          // ) {
                          //   employeePosMaster.authRoleId = item.authRoleId;
                          // } else {
                          //   employeePosMaster.authRoleId = null;
                          // }
                          //   employeePosMaster.current_holderId = null;
                          employeePosMaster.orgRevisionId = orgRevisionDraft.id;
                          employeePosMaster.orgRootId = matchedOrgRoot?.id ?? null;
                          employeePosMaster.orgChild1Id = matchedOrgChild1?.id ?? null;
                          employeePosMaster.orgChild2Id = matchedOrgChild2?.id ?? null;
                          employeePosMaster.orgChild3Id = matchedOrgChild3?.id ?? null;
                          employeePosMaster.createdUserId = "";
                          employeePosMaster.createdFullName = "System Administrator";
                          employeePosMaster.createdAt = new Date();
                          employeePosMaster.lastUpdateUserId = "";
                          employeePosMaster.lastUpdateFullName = "System Administrator";
                          employeePosMaster.lastUpdatedAt = new Date();
                          await repoEmployeePosmaster.save(employeePosMaster);

                          //create employeePosition
                          item.positions.map(async (pos: any) => {
                            delete pos.id;
                            const employeePosition: EmployeePosition = Object.assign(
                              new EmployeePosition(),
                              pos,
                            );
                            employeePosition.posMasterId = employeePosMaster.id;
                            //   if (
                            //     requestBody.typeDraft.toUpperCase() == "ORG_POSITION" ||
                            //     requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE"
                            //   ) {
                            //     employeePosition.positionIsSelected = false;
                            //   }
                            employeePosition.createdUserId = "";
                            employeePosition.createdFullName = "System Administrator";
                            employeePosition.createdAt = new Date();
                            employeePosition.lastUpdateUserId = "";
                            employeePosition.lastUpdateFullName = "System Administrator";
                            employeePosition.lastUpdatedAt = new Date();
                            await employeePositionRepository.save(employeePosition);
                          });
                        }),
                    );
                    // create employeeTempPosmaster
                    await Promise.all(
                      _orgemployeeTempPosMaster
                        .filter(
                          (x: EmployeeTempPosMaster) =>
                            x.orgChild3Id == data3Id && x.orgChild4Id == null,
                        )
                        .map(async (item: any) => {
                          delete item.id;
                          const employeeTempPosMaster = Object.assign(
                            new EmployeeTempPosMaster(),
                            item,
                          );
                          employeeTempPosMaster.positions = [];
                          // if (
                          //   requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON" ||
                          //   requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE"
                          // ) {
                          //   employeeTempPosMaster.current_holderId = item.current_holderId;
                          // } else {
                          //   // employeeTempPosMaster.next_holderId = null;
                          //   employeeTempPosMaster.isSit = false;
                          // }
                          // if (
                          //   requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" ||
                          //   requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE"
                          // ) {
                          //   employeeTempPosMaster.authRoleId = item.authRoleId;
                          // } else {
                          //   employeeTempPosMaster.authRoleId = null;
                          // }
                          //   employeeTempPosMaster.current_holderId = null;
                          employeeTempPosMaster.orgRevisionId = orgRevisionDraft.id;
                          employeeTempPosMaster.orgRootId = matchedOrgRoot?.id ?? null;
                          employeeTempPosMaster.orgChild1Id = matchedOrgChild1?.id ?? null;
                          employeeTempPosMaster.orgChild2Id = matchedOrgChild2?.id ?? null;
                          employeeTempPosMaster.orgChild3Id = matchedOrgChild3?.id ?? null;
                          employeeTempPosMaster.createdUserId = "";
                          employeeTempPosMaster.createdFullName = "System Administrator";
                          employeeTempPosMaster.createdAt = new Date();
                          employeeTempPosMaster.lastUpdateUserId = "";
                          employeeTempPosMaster.lastUpdateFullName = "System Administrator";
                          employeeTempPosMaster.lastUpdatedAt = new Date();
                          await repoEmployeeTempPosmaster.save(employeeTempPosMaster);

                          //create employeePosition
                          item.positions.map(async (pos: any) => {
                            delete pos.id;
                            const employeePosition: EmployeePosition = Object.assign(
                              new EmployeePosition(),
                              pos,
                            );
                            employeePosition.posMasterTempId = employeeTempPosMaster.id;
                            //   if (
                            //     requestBody.typeDraft.toUpperCase() == "ORG_POSITION" ||
                            //     requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE"
                            //   ) {
                            //     employeePosition.positionIsSelected = false;
                            //   }
                            employeePosition.createdUserId = "";
                            employeePosition.createdFullName = "System Administrator";
                            employeePosition.createdAt = new Date();
                            employeePosition.lastUpdateUserId = "";
                            employeePosition.lastUpdateFullName = "System Administrator";
                            employeePosition.lastUpdatedAt = new Date();
                            await employeePositionRepository.save(employeePosition);
                          });
                        }),
                    );
                    // }

                    //create org
                    orgChild4
                      .filter((x: OrgChild4) => x.orgChild3Id == data3Id)
                      .forEach(async (x: any) => {
                        var data4Id = x.id;
                        const orgChild4Current = await child4Repository.find({
                          where: { orgRevisionId: orgRevisionDraft.id },
                        });

                        const matchedOrgChild4 = orgChild4Current.find((i: OrgChild4) => {
                          if (
                            x.ancestorDNA === x.id || // ถ้า ancestorDNA ถูกตั้งเป็น id ตัวเอง
                            x.ancestorDNA === null ||
                            x.ancestorDNA === "00000000-0000-0000-0000-000000000000"
                          ) {
                            return (
                              i.ancestorDNA === null ||
                              i.ancestorDNA === "00000000-0000-0000-0000-000000000000"
                            );
                          }
                          return i.ancestorDNA === x.ancestorDNA;
                        });
                        // console.log("[in case Child4] ancestorDNA", `${x.orgChild4Id == matchedOrgChild4?.id}`);
                        // if (
                        //   requestBody.typeDraft.toUpperCase() == "ORG_POSITION" ||
                        //   requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON" ||
                        //   requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" ||
                        //   requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE"
                        // ) {
                        //create employeePosmaster
                        await Promise.all(
                          _orgemployeePosMaster
                            .filter((x: EmployeePosMaster) => x.orgChild4Id == data4Id)
                            .map(async (item: any) => {
                              delete item.id;
                              // console.log("[in case Child4] orgChild4Id == data4Id");
                              const employeePosMaster = Object.assign(
                                new EmployeePosMaster(),
                                item,
                              );
                              employeePosMaster.positions = [];
                              // if (
                              //   requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON" ||
                              //   requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE"
                              // ) {
                              //   employeePosMaster.current_holderId = item.current_holderId;
                              // } else {
                              //   // employeePosMaster.next_holderId = null;
                              //   employeePosMaster.isSit = false;
                              // }
                              // if (
                              //   requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" ||
                              //   requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE"
                              // ) {
                              //   employeePosMaster.authRoleId = item.authRoleId;
                              // } else {
                              //   employeePosMaster.authRoleId = null;
                              // }
                              //   employeePosMaster.current_holderId = null;
                              employeePosMaster.orgRevisionId = orgRevisionDraft.id;
                              employeePosMaster.orgRootId = matchedOrgRoot?.id ?? null;
                              employeePosMaster.orgChild1Id = matchedOrgChild1?.id ?? null;
                              employeePosMaster.orgChild2Id = matchedOrgChild2?.id ?? null;
                              employeePosMaster.orgChild3Id = matchedOrgChild3?.id ?? null;
                              employeePosMaster.orgChild4Id = matchedOrgChild4?.id ?? null;
                              employeePosMaster.createdUserId = "";
                              employeePosMaster.createdFullName = "System Administrator";
                              employeePosMaster.createdAt = new Date();
                              employeePosMaster.lastUpdateUserId = "";
                              employeePosMaster.lastUpdateFullName = "System Administrator";
                              employeePosMaster.lastUpdatedAt = new Date();
                              await repoEmployeePosmaster.save(employeePosMaster);

                              //create employeePosition
                              item.positions.map(async (pos: any) => {
                                delete pos.id;
                                const employeePosition: EmployeePosition = Object.assign(
                                  new EmployeePosition(),
                                  pos,
                                );
                                employeePosition.posMasterId = employeePosMaster.id;
                                //   if (
                                //     requestBody.typeDraft.toUpperCase() == "ORG_POSITION" ||
                                //     requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE"
                                //   ) {
                                //     employeePosition.positionIsSelected = false;
                                //   }
                                employeePosition.createdUserId = "";
                                employeePosition.createdFullName = "System Administrator";
                                employeePosition.createdAt = new Date();
                                employeePosition.lastUpdateUserId = "";
                                employeePosition.lastUpdateFullName = "System Administrator";
                                employeePosition.lastUpdatedAt = new Date();
                                await employeePositionRepository.save(employeePosition);
                              });
                            }),
                        );
                        //create employeeTempPosmaster
                        await Promise.all(
                          _orgemployeeTempPosMaster
                            .filter((x: EmployeeTempPosMaster) => x.orgChild4Id == data4Id)
                            .map(async (item: any) => {
                              delete item.id;
                              const employeeTempPosMaster = Object.assign(
                                new EmployeeTempPosMaster(),
                                item,
                              );
                              employeeTempPosMaster.positions = [];
                              // if (
                              //   requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON" ||
                              //   requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE"
                              // ) {
                              //   employeeTempPosMaster.current_holderId = item.current_holderId;
                              // } else {
                              //   // employeeTempPosMaster.next_holderId = null;
                              //   employeeTempPosMaster.isSit = false;
                              // }
                              // if (
                              //   requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" ||
                              //   requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE"
                              // ) {
                              //   employeeTempPosMaster.authRoleId = item.authRoleId;
                              // } else {
                              //   employeeTempPosMaster.authRoleId = null;
                              // }
                              //   employeeTempPosMaster.current_holderId = null;
                              employeeTempPosMaster.orgRevisionId = orgRevisionDraft.id;
                              employeeTempPosMaster.orgRootId = matchedOrgRoot?.id ?? null;
                              employeeTempPosMaster.orgChild1Id = matchedOrgChild1?.id ?? null;
                              employeeTempPosMaster.orgChild2Id = matchedOrgChild2?.id ?? null;
                              employeeTempPosMaster.orgChild3Id = matchedOrgChild3?.id ?? null;
                              employeeTempPosMaster.orgChild4Id = matchedOrgChild4?.id ?? null;
                              employeeTempPosMaster.createdUserId = "";
                              employeeTempPosMaster.createdFullName = "System Administrator";
                              employeeTempPosMaster.createdAt = new Date();
                              employeeTempPosMaster.lastUpdateUserId = "";
                              employeeTempPosMaster.lastUpdateFullName = "System Administrator";
                              employeeTempPosMaster.lastUpdatedAt = new Date();
                              await repoEmployeeTempPosmaster.save(employeeTempPosMaster);

                              //create employeePosition
                              item.positions.map(async (pos: any) => {
                                delete pos.id;
                                const employeePosition: EmployeePosition = Object.assign(
                                  new EmployeePosition(),
                                  pos,
                                );
                                employeePosition.posMasterTempId = employeeTempPosMaster.id;
                                //   if (
                                //     requestBody.typeDraft.toUpperCase() == "ORG_POSITION" ||
                                //     requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE"
                                //   ) {
                                //     employeePosition.positionIsSelected = false;
                                //   }
                                employeePosition.createdUserId = "";
                                employeePosition.createdFullName = "System Administrator";
                                employeePosition.createdAt = new Date();
                                employeePosition.lastUpdateUserId = "";
                                employeePosition.lastUpdateFullName = "System Administrator";
                                employeePosition.lastUpdatedAt = new Date();
                                await employeePositionRepository.save(employeePosition);
                              });
                            }),
                        );
                        // }
                      });
                  });
              });
          });
      });
      // }

      const employeePosMaster = await repoEmployeePosmaster.find({
        where: { orgRevisionId: orgRevisionDraft.id },
        relations: ["positions", "positions.posLevel", "positions.posType"],
      });
      for (const item of employeePosMaster) {
        if (item.next_holderId != null) {
          const profile = await repoProfileEmployee.findOne({
            where: { id: item.next_holderId == null ? "" : item.next_holderId },
          });
          const position = await item.positions.find((x) => x.positionIsSelected == true);
          const _null: any = null;
          if (profile != null) {
            profile.posLevelId = position?.posLevelId ?? _null;
            profile.posTypeId = position?.posTypeId ?? _null;
            profile.position = position?.positionName ?? _null;
            await repoProfileEmployee.save(profile);
          }
        }
        // item.current_holderId = item.next_holderId;
        // item.next_holderId = null;
        item.lastUpdateUserId = lastUpdateUserId;
        item.lastUpdateFullName = lastUpdateFullName;
        item.lastUpdatedAt = lastUpdatedAt;
        await repoEmployeePosmaster.save(item).catch((e) => console.log(e));
      }
      const employeeTempPosMaster = await repoEmployeeTempPosmaster.find({
        where: { orgRevisionId: orgRevisionDraft.id },
        relations: ["positions", "positions.posLevel", "positions.posType"],
      });
      for (const item of employeeTempPosMaster) {
        if (item.next_holderId != null) {
          const profile = await repoProfileEmployee.findOne({
            where: { id: item.next_holderId == null ? "" : item.next_holderId },
          });
          const position = await item.positions.find((x) => x.positionIsSelected == true);
          const _null: any = null;
          if (profile != null) {
            profile.posLevelId = position?.posLevelId ?? _null;
            profile.posTypeId = position?.posTypeId ?? _null;
            profile.position = position?.positionName ?? _null;
            await repoProfileEmployee.save(profile);
          }
        }
        // item.current_holderId = item.next_holderId;
        // item.next_holderId = null;
        item.lastUpdateUserId = lastUpdateUserId;
        item.lastUpdateFullName = lastUpdateFullName;
        item.lastUpdatedAt = lastUpdatedAt;
        await repoEmployeeTempPosmaster.save(item).catch((e) => console.log(e));
      }
    }
    console.log("[AMQ] Excecute Organization Success");
    if (user) {
      sendWebSocket(
        "send-publish-org",
        {
          success: true,
          message: `ระบบทำการเผยแพร่โครงสร้างหน่วยงานเรียบร้อยแล้ว`,
        },
        { userId: user?.sub },
      ).catch(console.error);
    }
    return true;
  } catch (error) {
    console.error(error);
    if (user) {
      sendWebSocket(
        "send-publish-org",
        {
          success: false,
          message: `ระบบทำการเผยแพร่โครงสร้างหน่วยงานไม่สำเร็จ`,
        },
        { userId: user?.sub },
      ).catch(console.error);
    }
    return false;
  }
}

async function handler_org_draft(msg: amqp.ConsumeMessage): Promise<boolean> {
  const { data, token, user } = JSON.parse(msg.content.toString());
  const { requestBody, request, revision } = data;
  const posMasterRepository = AppDataSource.getRepository(PosMaster);
  const positionRepository = AppDataSource.getRepository(Position);
  const employeePosMasterRepository = AppDataSource.getRepository(EmployeePosMaster);
  const employeeTempPosMasterRepository = AppDataSource.getRepository(EmployeeTempPosMaster);
  const posMasterAssignRepository = AppDataSource.getRepository(PosMasterAssign);
  const posMasterActRepository = AppDataSource.getRepository(PosMasterAct);
  const permissionOrgRepository = AppDataSource.getRepository(PermissionOrg);
  const employeePositionRepository = AppDataSource.getRepository(EmployeePosition);
  const orgRevisionRepository = AppDataSource.getRepository(OrgRevision);
  const orgRootRepository = AppDataSource.getRepository(OrgRoot);
  const child1Repository = AppDataSource.getRepository(OrgChild1);
  const child2Repository = AppDataSource.getRepository(OrgChild2);
  const child3Repository = AppDataSource.getRepository(OrgChild3);
  const child4Repository = AppDataSource.getRepository(OrgChild4);
  if (user) {
    sendWebSocket(
      "send-create-draft-org",
      {
        success: true,
        message: `ระบบกำลังทำการสร้างแบบร่างโครงสร้างหน่วยงาน`,
      },
      { userId: user?.sub },
    ).catch(console.error);
  }
  try {
    //cone tree
    if (
      requestBody.typeDraft.toUpperCase() == "ORG" ||
      requestBody.typeDraft.toUpperCase() == "ORG_POSITION" ||
      requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON" ||
      requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" ||
      requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE"
    ) {
      //cone by revisionId
      if (requestBody.orgRevisionId == null)
        throw new HttpError(HttpStatusCode.NOT_FOUND, "not found.");
      const _revision = await orgRevisionRepository.findOne({
        where: { id: requestBody.orgRevisionId },
      });
      if (!_revision) throw new HttpError(HttpStatusCode.NOT_FOUND, "not found.");

      //หา dna tree ถ้าไม่มีให้เอาตัวเองเป็น dna
      const orgRoot = await orgRootRepository.find({
        where: { orgRevisionId: requestBody.orgRevisionId },
        order: { orgRootOrder: "ASC" },
      });
      let _orgRoot: any = orgRoot.map((x) => ({
        ...x,
        ancestorDNA:
          x.ancestorDNA == null || x.ancestorDNA == "00000000-0000-0000-0000-000000000000"
            ? x.id
            : x.ancestorDNA,
      }));
      await orgRootRepository.save(_orgRoot);

      const orgChild1 = await child1Repository.find({
        where: { orgRevisionId: requestBody.orgRevisionId },
        order: { orgChild1Order: "ASC" },
      });
      let _orgChild1: any = orgChild1.map((x) => ({
        ...x,
        ancestorDNA:
          x.ancestorDNA == null || x.ancestorDNA == "00000000-0000-0000-0000-000000000000"
            ? x.id
            : x.ancestorDNA,
      }));
      await child1Repository.save(_orgChild1);

      const orgChild2 = await child2Repository.find({
        where: { orgRevisionId: requestBody.orgRevisionId },
        order: { orgChild2Order: "ASC" },
      });
      let _orgChild2: any = orgChild2.map((x) => ({
        ...x,
        ancestorDNA:
          x.ancestorDNA == null || x.ancestorDNA == "00000000-0000-0000-0000-000000000000"
            ? x.id
            : x.ancestorDNA,
      }));
      await child2Repository.save(_orgChild2);

      const orgChild3 = await child3Repository.find({
        where: { orgRevisionId: requestBody.orgRevisionId },
        order: { orgChild3Order: "ASC" },
      });
      let _orgChild3: any = orgChild3.map((x) => ({
        ...x,
        ancestorDNA:
          x.ancestorDNA == null || x.ancestorDNA == "00000000-0000-0000-0000-000000000000"
            ? x.id
            : x.ancestorDNA,
      }));
      await child3Repository.save(_orgChild3);

      const orgChild4 = await child4Repository.find({
        where: { orgRevisionId: requestBody.orgRevisionId },
        order: { orgChild4Order: "ASC" },
      });
      let _orgChild4: any = orgChild4.map((x) => ({
        ...x,
        ancestorDNA:
          x.ancestorDNA == null || x.ancestorDNA == "00000000-0000-0000-0000-000000000000"
            ? x.id
            : x.ancestorDNA,
      }));
      await child4Repository.save(_orgChild4);

      //หา dna posmaster ถ้าไม่มีให้เอาตัวเองเป็น dna
      const orgPosMaster = await posMasterRepository.find({
        where: { orgRevisionId: requestBody.orgRevisionId },
        relations: ["positions"],
      });

      let _orgPosMaster: PosMaster[] = [];
      if (
        requestBody.typeDraft.toUpperCase() == "ORG_POSITION" ||
        requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON" ||
        requestBody.typeDraft.toUpperCase() == "ORG_POSITION_ROLE" ||
        requestBody.typeDraft.toUpperCase() == "ORG_POSITION_PERSON_ROLE"
      ) {
        _orgPosMaster = orgPosMaster
          .filter(
            (x) => x.ancestorDNA == null || x.ancestorDNA == "00000000-0000-0000-0000-000000000000",
          )
          .map((x) => ({
            ...x,
            ancestorDNA:
              x.ancestorDNA == null || x.ancestorDNA == "00000000-0000-0000-0000-000000000000"
                ? x.id
                : x.ancestorDNA,
          }));
        await posMasterRepository.save(_orgPosMaster);
      }
      // Create org
      for await (const x0 of _orgRoot) {
        var dataId = x0.id;
        var _null: any = null;
        // console.log(`ch0 ${x0.orgRootOrder}`);
        // console.log(dataId);
        delete x0.id;
        const data = Object.assign(new OrgRoot(), x0);
        data.orgRevisionId = revision.id;
        data.createdUserId = request.sub;
        data.createdFullName = request.name;
        data.createdAt = new Date();
        data.lastUpdateUserId = request.sub;
        data.lastUpdateFullName = request.name;
        data.lastUpdatedAt = new Date();
        await orgRootRepository.save(data);

        const orgTypes = new Set([
          "ORG_POSITION",
          "ORG_POSITION_PERSON",
          "ORG_POSITION_ROLE",
          "ORG_POSITION_PERSON_ROLE",
        ]);

        if (orgTypes.has(requestBody.typeDraft.toUpperCase())) {
          // Create posMaster
          for await (const item of orgPosMaster.filter(
            (x: PosMaster) => x.orgRootId == dataId && x.orgChild1Id == null,
          ) as any) {
            let posMasterAssign = await posMasterAssignRepository.find({
              where: { posMasterId: item.id },
            });
            delete item.id;
            const posMaster = Object.assign(new PosMaster(), item);
            posMaster.positions = [];

            if (
              ["ORG_POSITION_PERSON", "ORG_POSITION_PERSON_ROLE"].includes(
                requestBody.typeDraft.toUpperCase(),
              )
            ) {
              posMaster.next_holderId = item.current_holderId;
              // if (posMaster.next_holderId) {
              //   posMaster.conditionReason = _null;
              //   posMaster.isCondition = false;
              // }
            } else {
              posMaster.next_holderId = null;
              posMaster.isSit = false;
            }

            if (
              ["ORG_POSITION_ROLE", "ORG_POSITION_PERSON_ROLE"].includes(
                requestBody.typeDraft.toUpperCase(),
              )
            ) {
              posMaster.authRoleId = item.authRoleId;
            } else {
              posMaster.authRoleId = null;
            }

            posMaster.current_holderId = null;
            posMaster.orgRevisionId = revision.id;
            posMaster.orgRootId = data.id;
            posMaster.createdUserId = request.sub;
            posMaster.createdFullName = request.name;
            posMaster.createdAt = new Date();
            posMaster.lastUpdateUserId = request.sub;
            posMaster.lastUpdateFullName = request.name;
            posMaster.lastUpdatedAt = new Date();
            await posMasterRepository.save(posMaster);

            // Copy assignments
            await posMasterAssignRepository.save(
              posMasterAssign.map(({ id, ...rest }: PosMasterAssign) => ({
                ...rest,
                posMasterId: posMaster.id,
              })),
            );

            // Create positions
            for await (const pos of item.positions) {
              delete pos.id;
              const position = Object.assign(new Position(), pos);
              position.posMasterId = posMaster.id;

              if (
                ["ORG_POSITION", "ORG_POSITION_ROLE"].includes(requestBody.typeDraft.toUpperCase())
              ) {
                position.positionIsSelected = false;
              }

              position.createdUserId = request.sub;
              position.createdFullName = request.name;
              position.createdAt = new Date();
              position.lastUpdateUserId = request.sub;
              position.lastUpdateFullName = request.name;
              position.lastUpdatedAt = new Date();
              await positionRepository.save(position);
            }
          }
        }

        // Create orgChild1
        for await (const x1 of _orgChild1.filter((x: OrgChild1) => x.orgRootId == dataId)) {
          var data1Id = x1.id;
          // console.log(`ch1 ${x1.orgChild1Order}`);
          // console.log(data1Id);
          delete x1.id;
          const data1 = Object.assign(new OrgChild1(), x1);
          data1.orgRootId = data.id;
          data1.orgRevisionId = revision.id;
          data1.createdUserId = request.sub;
          data1.createdFullName = request.name;
          data1.createdAt = new Date();
          data1.lastUpdateUserId = request.sub;
          data1.lastUpdateFullName = request.name;
          data1.lastUpdatedAt = new Date();
          await child1Repository.save(data1);

          if (orgTypes.has(requestBody.typeDraft.toUpperCase())) {
            // Create posMaster
            for await (const item of orgPosMaster.filter(
              (x: PosMaster) => x.orgChild1Id == data1Id && x.orgChild2Id == null,
            ) as any) {
              let posMasterAssign = await posMasterAssignRepository.find({
                where: { posMasterId: item.id },
              });
              delete item.id;
              const posMaster = Object.assign(new PosMaster(), item);
              posMaster.positions = [];

              if (
                ["ORG_POSITION_PERSON", "ORG_POSITION_PERSON_ROLE"].includes(
                  requestBody.typeDraft.toUpperCase(),
                )
              ) {
                posMaster.next_holderId = item.current_holderId;
                // if (posMaster.next_holderId) {
                //   posMaster.conditionReason = _null;
                //   posMaster.isCondition = false;
                // }
              } else {
                posMaster.next_holderId = null;
                posMaster.isSit = false;
              }

              if (
                ["ORG_POSITION_ROLE", "ORG_POSITION_PERSON_ROLE"].includes(
                  requestBody.typeDraft.toUpperCase(),
                )
              ) {
                posMaster.authRoleId = item.authRoleId;
              } else {
                posMaster.authRoleId = null;
              }

              posMaster.current_holderId = null;
              posMaster.orgRevisionId = revision.id;
              posMaster.orgRootId = data.id;
              posMaster.orgChild1Id = data1.id;
              posMaster.createdUserId = request.sub;
              posMaster.createdFullName = request.name;
              posMaster.createdAt = new Date();
              posMaster.lastUpdateUserId = request.sub;
              posMaster.lastUpdateFullName = request.name;
              posMaster.lastUpdatedAt = new Date();
              await posMasterRepository.save(posMaster);

              // Copy assignments
              await posMasterAssignRepository.save(
                posMasterAssign.map(({ id, ...rest }: PosMasterAssign) => ({
                  ...rest,
                  posMasterId: posMaster.id,
                })),
              );

              // Create positions
              for await (const pos of item.positions) {
                delete pos.id;
                const position = Object.assign(new Position(), pos);
                position.posMasterId = posMaster.id;

                if (
                  ["ORG_POSITION", "ORG_POSITION_ROLE"].includes(
                    requestBody.typeDraft.toUpperCase(),
                  )
                ) {
                  position.positionIsSelected = false;
                }

                position.createdUserId = request.sub;
                position.createdFullName = request.name;
                position.createdAt = new Date();
                position.lastUpdateUserId = request.sub;
                position.lastUpdateFullName = request.name;
                position.lastUpdatedAt = new Date();
                await positionRepository.save(position);
              }
            }
          }
          for await (const x2 of _orgChild2.filter((x: OrgChild2) => x.orgChild1Id == data1Id)) {
            var data2Id = x2.id;
            // console.log(`ch2 ${x2.orgChild2Order}`);
            // console.log(data2Id);
            delete x2.id;
            const data2 = Object.assign(new OrgChild2(), x2);
            data2.orgChild1Id = data1.id;
            data2.orgRootId = data.id;
            data2.orgRevisionId = revision.id;
            data2.createdUserId = request.sub;
            data2.createdFullName = request.name;
            data2.createdAt = new Date();
            data2.lastUpdateUserId = request.sub;
            data2.lastUpdateFullName = request.name;
            data2.lastUpdatedAt = new Date();
            await child2Repository.save(data2);

            if (orgTypes.has(requestBody.typeDraft.toUpperCase())) {
              // Create posMaster
              for await (const item of orgPosMaster.filter(
                (x: PosMaster) => x.orgChild2Id == data2Id && x.orgChild3Id == null,
              ) as any) {
                let posMasterAssign = await posMasterAssignRepository.find({
                  where: { posMasterId: item.id },
                });
                delete item.id;
                const posMaster = Object.assign(new PosMaster(), item);
                posMaster.positions = [];

                if (
                  ["ORG_POSITION_PERSON", "ORG_POSITION_PERSON_ROLE"].includes(
                    requestBody.typeDraft.toUpperCase(),
                  )
                ) {
                  posMaster.next_holderId = item.current_holderId;
                  // if (posMaster.next_holderId) {
                  //   posMaster.conditionReason = _null;
                  //   posMaster.isCondition = false;
                  // }
                } else {
                  posMaster.next_holderId = null;
                  posMaster.isSit = false;
                }

                if (
                  ["ORG_POSITION_ROLE", "ORG_POSITION_PERSON_ROLE"].includes(
                    requestBody.typeDraft.toUpperCase(),
                  )
                ) {
                  posMaster.authRoleId = item.authRoleId;
                } else {
                  posMaster.authRoleId = null;
                }

                posMaster.current_holderId = null;
                posMaster.orgRevisionId = revision.id;
                posMaster.orgRootId = data.id;
                posMaster.orgChild1Id = data1.id;
                posMaster.orgChild2Id = data2.id;
                posMaster.createdUserId = request.sub;
                posMaster.createdFullName = request.name;
                posMaster.createdAt = new Date();
                posMaster.lastUpdateUserId = request.sub;
                posMaster.lastUpdateFullName = request.name;
                posMaster.lastUpdatedAt = new Date();
                await posMasterRepository.save(posMaster);

                // Copy assignments
                await posMasterAssignRepository.save(
                  posMasterAssign.map(({ id, ...rest }: PosMasterAssign) => ({
                    ...rest,
                    posMasterId: posMaster.id,
                  })),
                );

                // Create positions
                for await (const pos of item.positions) {
                  delete pos.id;
                  const position = Object.assign(new Position(), pos);
                  position.posMasterId = posMaster.id;
                  if (
                    ["ORG_POSITION", "ORG_POSITION_ROLE"].includes(
                      requestBody.typeDraft.toUpperCase(),
                    )
                  ) {
                    position.positionIsSelected = false;
                  }
                  position.createdUserId = request.sub;
                  position.createdFullName = request.name;
                  position.createdAt = new Date();
                  position.lastUpdateUserId = request.sub;
                  position.lastUpdateFullName = request.name;
                  position.lastUpdatedAt = new Date();
                  await positionRepository.save(position);
                }
              }
            }

            // Create org
            for await (const x3 of _orgChild3.filter((x: OrgChild3) => x.orgChild2Id == data2Id)) {
              var data3Id = x3.id;
              // console.log(`ch3 ${x3.orgChild3Order}`);
              // console.log(data3Id);
              delete x3.id;
              const data3 = Object.assign(new OrgChild3(), x3);
              data3.orgChild2Id = data2.id;
              data3.orgChild1Id = data1.id;
              data3.orgRootId = data.id;
              data3.orgRevisionId = revision.id;
              data3.createdUserId = request.sub;
              data3.createdFullName = request.name;
              data3.createdAt = new Date();
              data3.lastUpdateUserId = request.sub;
              data3.lastUpdateFullName = request.name;
              data3.lastUpdatedAt = new Date();
              await child3Repository.save(data3);

              if (orgTypes.has(requestBody.typeDraft.toUpperCase())) {
                // Create posMaster
                for await (const item of orgPosMaster.filter(
                  (x: PosMaster) => x.orgChild3Id == data3Id && x.orgChild4Id == null,
                ) as any) {
                  let posMasterAssign = await posMasterAssignRepository.find({
                    where: { posMasterId: item.id },
                  });
                  delete item.id;
                  const posMaster = Object.assign(new PosMaster(), item);
                  posMaster.positions = [];

                  if (
                    ["ORG_POSITION_PERSON", "ORG_POSITION_PERSON_ROLE"].includes(
                      requestBody.typeDraft.toUpperCase(),
                    )
                  ) {
                    posMaster.next_holderId = item.current_holderId;
                    // if (posMaster.next_holderId) {
                    //   posMaster.conditionReason = _null;
                    //   posMaster.isCondition = false;
                    // }
                  } else {
                    posMaster.next_holderId = null;
                    posMaster.isSit = false;
                  }

                  if (
                    ["ORG_POSITION_ROLE", "ORG_POSITION_PERSON_ROLE"].includes(
                      requestBody.typeDraft.toUpperCase(),
                    )
                  ) {
                    posMaster.authRoleId = item.authRoleId;
                  } else {
                    posMaster.authRoleId = null;
                  }

                  posMaster.current_holderId = null;
                  posMaster.orgRevisionId = revision.id;
                  posMaster.orgRootId = data.id;
                  posMaster.orgChild1Id = data1.id;
                  posMaster.orgChild2Id = data2.id;
                  posMaster.orgChild3Id = data3.id;
                  posMaster.createdUserId = request.sub;
                  posMaster.createdFullName = request.name;
                  posMaster.createdAt = new Date();
                  posMaster.lastUpdateUserId = request.sub;
                  posMaster.lastUpdateFullName = request.name;
                  posMaster.lastUpdatedAt = new Date();
                  await posMasterRepository.save(posMaster);

                  // Copy assignments
                  await posMasterAssignRepository.save(
                    posMasterAssign.map(({ id, ...rest }: PosMasterAssign) => ({
                      ...rest,
                      posMasterId: posMaster.id,
                    })),
                  );

                  // Create positions
                  for await (const pos of item.positions) {
                    delete pos.id;
                    const position = Object.assign(new Position(), pos);
                    position.posMasterId = posMaster.id;
                    if (
                      ["ORG_POSITION", "ORG_POSITION_ROLE"].includes(
                        requestBody.typeDraft.toUpperCase(),
                      )
                    ) {
                      position.positionIsSelected = false;
                    }
                    position.createdUserId = request.sub;
                    position.createdFullName = request.name;
                    position.createdAt = new Date();
                    position.lastUpdateUserId = request.sub;
                    position.lastUpdateFullName = request.name;
                    position.lastUpdatedAt = new Date();
                    await positionRepository.save(position);
                  }
                }
              }
              // Create org
              for await (const x4 of _orgChild4.filter(
                (x: OrgChild4) => x.orgChild3Id == data3Id,
              )) {
                var data4Id = x4.id;
                // console.log(`ch4 ${x4.orgChild4Order}`);
                // console.log(data4Id);
                delete x4.id;
                const data4 = Object.assign(new OrgChild4(), x4);
                data4.orgChild3Id = data3.id;
                data4.orgChild2Id = data2.id;
                data4.orgChild1Id = data1.id;
                data4.orgRootId = data.id;
                data4.orgRevisionId = revision.id;
                data4.createdUserId = request.sub;
                data4.createdFullName = request.name;
                data4.createdAt = new Date();
                data4.lastUpdateUserId = request.sub;
                data4.lastUpdateFullName = request.name;
                data4.lastUpdatedAt = new Date();
                await child4Repository.save(data4);

                if (orgTypes.has(requestBody.typeDraft.toUpperCase())) {
                  // Create posMaster
                  for await (const item of orgPosMaster.filter(
                    (x: PosMaster) => x.orgChild4Id == data4Id,
                  ) as any) {
                    let posMasterAssign = await posMasterAssignRepository.find({
                      where: { posMasterId: item.id },
                    });
                    delete item.id;
                    const posMaster = Object.assign(new PosMaster(), item);
                    posMaster.positions = [];

                    if (
                      ["ORG_POSITION_PERSON", "ORG_POSITION_PERSON_ROLE"].includes(
                        requestBody.typeDraft.toUpperCase(),
                      )
                    ) {
                      posMaster.next_holderId = item.current_holderId;
                      // if (posMaster.next_holderId) {
                      //   posMaster.conditionReason = _null;
                      //   posMaster.isCondition = false;
                      // }
                    } else {
                      posMaster.next_holderId = null;
                      posMaster.isSit = false;
                    }

                    if (
                      ["ORG_POSITION_ROLE", "ORG_POSITION_PERSON_ROLE"].includes(
                        requestBody.typeDraft.toUpperCase(),
                      )
                    ) {
                      posMaster.authRoleId = item.authRoleId;
                    } else {
                      posMaster.authRoleId = null;
                    }

                    posMaster.current_holderId = null;
                    posMaster.orgRevisionId = revision.id;
                    posMaster.orgRootId = data.id;
                    posMaster.orgChild1Id = data1.id;
                    posMaster.orgChild2Id = data2.id;
                    posMaster.orgChild3Id = data3.id;
                    posMaster.orgChild4Id = data4.id;
                    posMaster.createdUserId = request.sub;
                    posMaster.createdFullName = request.name;
                    posMaster.createdAt = new Date();
                    posMaster.lastUpdateUserId = request.sub;
                    posMaster.lastUpdateFullName = request.name;
                    posMaster.lastUpdatedAt = new Date();
                    await posMasterRepository.save(posMaster);

                    // Copy assignments
                    await posMasterAssignRepository.save(
                      posMasterAssign.map(({ id, ...rest }: PosMasterAssign) => ({
                        ...rest,
                        posMasterId: posMaster.id,
                      })),
                    );

                    // Create positions
                    for await (const pos of item.positions) {
                      delete pos.id;
                      const position = Object.assign(new Position(), pos);
                      position.posMasterId = posMaster.id;
                      if (
                        ["ORG_POSITION", "ORG_POSITION_ROLE"].includes(
                          requestBody.typeDraft.toUpperCase(),
                        )
                      ) {
                        position.positionIsSelected = false;
                      }
                      position.createdUserId = request.sub;
                      position.createdFullName = request.name;
                      position.createdAt = new Date();
                      position.lastUpdateUserId = request.sub;
                      position.lastUpdateFullName = request.name;
                      position.lastUpdatedAt = new Date();
                      await positionRepository.save(position);
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
    //ลบ daft เก่าที่ค้างแล้วยังไม่ได้เผยแพร่
    const _orgRevisions = await orgRevisionRepository.find({
      where: [{ orgRevisionIsDraft: true, id: Not(revision.id) }],
    });
    const _roots = await orgRootRepository.find({
      where: [{ orgRevisionId: In(_orgRevisions.map((x) => x.id)) }],
    });
    const _posMasters = await posMasterRepository.find({
      where: [{ orgRevisionId: In(_orgRevisions.map((x) => x.id)) }],
    });
    const _employeePosMasters = await employeePosMasterRepository.find({
      where: [{ orgRevisionId: In(_orgRevisions.map((x) => x.id)) }],
    });
    const _employeeTempPosMasters = await employeeTempPosMasterRepository.find({
      where: [{ orgRevisionId: In(_orgRevisions.map((x) => x.id)) }],
    });
    await positionRepository.delete({ posMasterId: In(_posMasters.map((x) => x.id)) });
    await employeePositionRepository.delete({
      posMasterId: In(_employeePosMasters.map((x) => x.id)),
    });
    await employeePositionRepository.delete({
      posMasterTempId: In(_employeeTempPosMasters.map((x) => x.id)),
    });
    await posMasterAssignRepository.delete({ posMasterId: In(_posMasters.map((x) => x.id)) });
    await posMasterActRepository.delete({ posMasterId: In(_posMasters.map((x) => x.id)) });
    await posMasterActRepository.delete({
      posMasterChildId: In(_posMasters.map((x) => x.id)),
    });
    // await posMasterRepository.remove(_posMasters);
    const batchSize = 1000;
    const removeInBatches = async (repository: any, data: any, label: any) => {
      for (let i = 0; i < data.length; i += batchSize) {
        const batch = data.slice(i, i + batchSize);
        try {
          await repository.remove(batch);
          console.log(`Removed ${label} batch ${i / batchSize + 1}`);
        } catch (error) {
          console.log(`Failed to remove ${label} batch ${i / batchSize + 1}`);
        }
      }
    };
    await removeInBatches(posMasterRepository, _posMasters, "PosMaster");
    await removeInBatches(employeePosMasterRepository, _employeePosMasters, "EmployeePosMaster");
    await removeInBatches(
      employeeTempPosMasterRepository,
      _employeeTempPosMasters,
      "EmployeeTempPosMaster",
    );
    await child4Repository.delete({ orgRevisionId: In(_orgRevisions.map((x) => x.id)) });
    await child3Repository.delete({ orgRevisionId: In(_orgRevisions.map((x) => x.id)) });
    await child2Repository.delete({ orgRevisionId: In(_orgRevisions.map((x) => x.id)) });
    await child1Repository.delete({ orgRevisionId: In(_orgRevisions.map((x) => x.id)) });
    await permissionOrgRepository.delete({
      orgRootId: In(_roots.map((x) => x.id)),
    });
    await orgRootRepository.delete({ orgRevisionId: In(_orgRevisions.map((x) => x.id)) });
    await orgRevisionRepository.remove(_orgRevisions);

    console.log("[AMQ] Create Draft Success");
    if (user) {
      await sendWebSocket(
        "send-create-draft-org",
        {
          success: true,
          message: `ระบบทำการสร้างแบบร่างโครงสร้างหน่วยงานเรียบร้อยแล้ว`,
        },
        { userId: user?.sub },
      ).catch(console.error);
    }
    return true;
  } catch (error) {
    console.error(error);
    if (user) {
      await sendWebSocket(
        "send-create-draft-org",
        {
          success: false,
          message: `ระบบทำการสร้างแบบร่างโครงสร้างหน่วยงานไม่สำเร็จ`,
        },
        { userId: user?.sub },
      ).catch(console.error);
    }
    return false;
  }
}
