import { Controller, Get, Post, Route, Tags, Body, Path, Response } from "tsoa";
import { OrgRevision } from "../entities/OrgRevision";
import { AppDataSource } from "../database/data-source";
import HttpSuccess from "../interfaces/http-success";
import HttpError from "../interfaces/http-error";
import HttpStatusCode from "../interfaces/http-status";
import { Brackets, IsNull, Not } from "typeorm";
import { OrgRoot } from "../entities/OrgRoot";
import { PosMaster } from "../entities/PosMaster";
import { calculateRetireDate } from "../interfaces/utils";
import { EmployeePosMaster } from "../entities/EmployeePosMaster";
import { Profile } from "../entities/Profile";
import { ProfileEmployee } from "../entities/ProfileEmployee";

@Route("api/v1/org/unauthorize")
@Tags("OrganizationUnauthorize")
@Response(
  HttpStatusCode.INTERNAL_SERVER_ERROR,
  "เกิดข้อผิดพลาด ไม่สามารถแสดงรายการได้ กรุณาลองใหม่ในภายหลัง",
)
export class OrganizationUnauthorizeController extends Controller {
  private orgRevisionRepository = AppDataSource.getRepository(OrgRevision);
  private orgRootRepository = AppDataSource.getRepository(OrgRoot);
  private profileRepo = AppDataSource.getRepository(Profile);
  private profileEmpRepo = AppDataSource.getRepository(ProfileEmployee);

  /**
   * API รายชื่อราชการที่เลื่อนเงินเดือน (unauthorize)
   *
   * @summary ORG_072 - รายชื่อราชการที่เลื่อนเงินเดือน #76 (unauthorize)
   *
   */
  @Post("salary/gen")
  async salaryGen(
    @Body()
    body: {
      page: number;
      pageSize: number;
      keyword?: string;
      year: number;
      period: string;
    },
  ) {
    const findRevision = await this.orgRevisionRepository.findOne({
      where: { orgRevisionIsCurrent: true },
    });
    if (!findRevision) {
      throw new HttpError(HttpStatusCode.NOT_FOUND, "not found. OrgRevision");
    }

    const [findPosMaster, total] = await AppDataSource.getRepository(PosMaster)
      .createQueryBuilder("posMaster")
      .leftJoinAndSelect("posMaster.current_holder", "current_holder")
      .leftJoinAndSelect("posMaster.orgRoot", "orgRoot")
      .leftJoinAndSelect("posMaster.orgChild1", "orgChild1")
      .leftJoinAndSelect("posMaster.orgChild2", "orgChild2")
      .leftJoinAndSelect("posMaster.orgChild3", "orgChild3")
      .leftJoinAndSelect("posMaster.orgChild4", "orgChild4")
      .leftJoinAndSelect("posMaster.positions", "positions")
      .leftJoinAndSelect("positions.posExecutive", "posExecutive")
      .leftJoinAndSelect("current_holder.profileSalary", "profileSalary")
      .leftJoinAndSelect("current_holder.profileDisciplines", "profileDisciplines")
      .leftJoinAndSelect("current_holder.profileLeaves", "profileLeaves")
      .leftJoinAndSelect("current_holder.profileAssessments", "profileAssessments")
      .leftJoinAndSelect("current_holder.posLevel", "posLevel")
      .leftJoinAndSelect("current_holder.posType", "posType")
      .where({
        orgRevisionId: findRevision?.id,
        current_holderId: Not(IsNull()),
      })
      .andWhere(
        new Brackets((qb) => {
          qb.where(
            body.keyword != null && body.keyword != ""
              ? "current_holder.prefix LIKE :keyword"
              : "1=1",
            {
              keyword: `%${body.keyword}%`,
            },
          )
            .orWhere(
              body.keyword != null && body.keyword != ""
                ? "current_holder.firstName LIKE :keyword"
                : "1=1",
              {
                keyword: `%${body.keyword}%`,
              },
            )
            .orWhere(
              body.keyword != null && body.keyword != ""
                ? "current_holder.lastName LIKE :keyword"
                : "1=1",
              {
                keyword: `%${body.keyword}%`,
              },
            )
            .orWhere(
              body.keyword != null && body.keyword != ""
                ? "current_holder.position LIKE :keyword"
                : "1=1",
              {
                keyword: `%${body.keyword}%`,
              },
            )

            .orWhere(
              body.keyword != null && body.keyword != ""
                ? "current_holder.citizenId LIKE :keyword"
                : "1=1",
              {
                keyword: `%${body.keyword}%`,
              },
            )
            .orWhere(
              body.keyword != null && body.keyword != ""
                ? "posType.posTypeName LIKE :keyword"
                : "1=1",
              {
                keyword: `%${body.keyword}%`,
              },
            )
            .orWhere(
              body.keyword != null && body.keyword != ""
                ? "posLevel.posLevelName LIKE :keyword"
                : "1=1",
              {
                keyword: `%${body.keyword}%`,
              },
            );
        }),
      )
      .orderBy("current_holder.citizenId", "ASC")
      .skip((body.page - 1) * body.pageSize)
      .take(body.pageSize)
      .getManyAndCount();
    if (!findPosMaster) {
      throw new HttpError(HttpStatusCode.NOT_FOUND, "not found. PosMaster");
    }

    const formattedData = findPosMaster.map((item) => {
      let orgShortName = "";

      if (item.orgChild1Id === null) {
        orgShortName = item.orgRoot?.orgRootShortName;
      } else if (item.orgChild2Id === null) {
        orgShortName = item.orgChild1?.orgChild1ShortName;
      } else if (item.orgChild3Id === null) {
        orgShortName = item.orgChild2?.orgChild2ShortName;
      } else if (item.orgChild4Id === null) {
        orgShortName = item.orgChild3?.orgChild3ShortName;
      } else {
        orgShortName = item.orgChild4?.orgChild4ShortName;
      }
      const posExecutive =
        item.positions == null ||
        item.positions?.find((position) => position.positionIsSelected == true) == null ||
        item.positions?.find((position) => position.positionIsSelected == true)?.posExecutive ==
          null ||
        item.positions?.find((position) => position.positionIsSelected == true)?.posExecutive
          ?.posExecutiveName == null
          ? null
          : item.positions?.find((position) => position.positionIsSelected == true)?.posExecutive
              .posExecutiveName;

      const amount =
        item.current_holder == null || item.current_holder.profileSalary.length == 0
          ? null
          : item.current_holder.profileSalary.sort((a: any, b: any) => b.date - a.date)[0].amount;
      let datePeriodStart = new Date(
        `${new Date().getFullYear()}-${String(new Date().getMonth() + 1).padStart(2, "0")}-${String(new Date().getDate() + 1).padStart(2, "0")}T00:00:00.000Z`,
      );
      let datePeriodEnd = new Date(
        `${new Date().getFullYear()}-${String(new Date().getMonth() + 1).padStart(2, "0")}-${String(new Date().getDate() + 1).padStart(2, "0")}T00:00:00.000Z`,
      );
      if (body.period.toLocaleUpperCase() == "APR") {
        datePeriodStart = new Date(`${body.year}-03-31T00:00:00.000Z`);
        datePeriodEnd = new Date(`${body.year}-03-31T00:00:00.000Z`);
      }
      if (body.period.toLocaleUpperCase() == "OCT") {
        datePeriodStart = new Date(`${body.year}-09-30T00:00:00.000Z`);
        datePeriodEnd = new Date(`${body.year}-09-30T00:00:00.000Z`);
      }
      datePeriodStart = new Date(
        new Date(datePeriodStart.setDate(datePeriodStart.getDate() + 1)).setMonth(
          datePeriodStart.getMonth() - 6,
        ),
      );
      const specialPosition = item.positions.find(
        (position) => position.positionIsSelected === true,
      );
      const isSpecial = specialPosition ? specialPosition.isSpecial : null;

      const latestProfileAssessment = item.current_holder.profileAssessments
        ? item.current_holder.profileAssessments.sort((a: any, b: any) => b.date - a.date)[0]
        : null;
      const pointSum = latestProfileAssessment
        ? `(${this.textPointSummaryKpi(latestProfileAssessment.pointSum)})${latestProfileAssessment.pointSum}`
        : null;
      return {
        id: item.id,
        profileId: item.current_holder.id,
        prefix: item.current_holder.prefix,
        firstName: item.current_holder.firstName,
        lastName: item.current_holder.lastName,
        citizenId: item.current_holder.citizenId,
        posMasterNoPrefix: item.posMasterNoPrefix,
        posMasterNo: item.posMasterNo,
        posMasterNoSuffix: item.posMasterNoSuffix,
        orgShortName: orgShortName,
        position: item.current_holder.position,
        posType:
          item.current_holder.posType == null ? null : item.current_holder.posType.posTypeName,
        posLevel:
          item.current_holder.posLevel == null ? null : item.current_holder.posLevel.posLevelName,
        posExecutive: posExecutive,
        amount: amount ? amount : null,
        rootId: item.orgRootId,
        root: item.orgRoot?.orgRootName ? item.orgRoot.orgRootName : null,
        child1Id: item.orgChild1Id,
        child1: item.orgChild1?.orgChild1Name ? item.orgChild1.orgChild1Name : null,
        child2Id: item.orgChild2Id,
        child2: item.orgChild2?.orgChild2Name ? item.orgChild2.orgChild2Name : null,
        child3Id: item.orgChild3Id,
        child3: item.orgChild3?.orgChild3Name ? item.orgChild3.orgChild3Name : null,
        child4Id: item.orgChild4Id,
        child4: item.orgChild4?.orgChild4Name ? item.orgChild4.orgChild4Name : null,
        result: pointSum,
        duration: null,
        isPunish:
          item.current_holder.profileDisciplines.filter(
            (x: any) =>
              new Date(
                `${new Date(x.date).getFullYear()}-${String(new Date(x.date).getMonth() + 1).padStart(2, "0")}-${String(new Date(x.date).getDate() + 1).padStart(2, "0")}T00:00:00.000Z`,
              ) >= datePeriodStart &&
              new Date(
                `${new Date(x.date).getFullYear()}-${String(new Date(x.date).getMonth() + 1).padStart(2, "0")}-${String(new Date(x.date).getDate() + 1).padStart(2, "0")}T00:00:00.000Z`,
              ) <= datePeriodEnd,
          ).length > 0
            ? true
            : false,
        isSuspension: item.current_holder.dateRetire == null ? false : true,
        isAbsent: item.current_holder.profileDisciplines.length > 0 ? true : false,
        isLeave: item.current_holder.profileLeaves.length > 0 ? true : false,
        isRetired:
          item.current_holder.birthDate == null ||
          calculateRetireDate(item.current_holder.birthDate).getFullYear() != body.year
            ? false
            : true,
        isSpecial: isSpecial,
      };
    });
    return new HttpSuccess({ data: formattedData, total: total });
  }

  /**
   * API รายชื่อราชการที่เลื่อนเงินเดือน (unauthorize)
   *
   * @summary ORG_072 - รายชื่อราชการที่เลื่อนเงินเดือน #76 (unauthorize)
   *
   */
  @Post("salary/employee/gen")
  async salaryEmployeeGen(
    @Body()
    body: {
      page: number;
      pageSize: number;
      keyword?: string;
      year: number;
      period: string;
    },
  ) {
    const findRevision = await this.orgRevisionRepository.findOne({
      where: { orgRevisionIsCurrent: true },
    });
    if (!findRevision) {
      throw new HttpError(HttpStatusCode.NOT_FOUND, "not found. OrgRevision");
    }

    const [findPosMaster, total] = await AppDataSource.getRepository(EmployeePosMaster)
      .createQueryBuilder("employeePosMaster")
      .leftJoinAndSelect("employeePosMaster.current_holder", "current_holder")
      .leftJoinAndSelect("employeePosMaster.orgRoot", "orgRoot")
      .leftJoinAndSelect("employeePosMaster.orgChild1", "orgChild1")
      .leftJoinAndSelect("employeePosMaster.orgChild2", "orgChild2")
      .leftJoinAndSelect("employeePosMaster.orgChild3", "orgChild3")
      .leftJoinAndSelect("employeePosMaster.orgChild4", "orgChild4")
      .leftJoinAndSelect("employeePosMaster.positions", "positions")
      .leftJoinAndSelect("current_holder.profileSalary", "profileSalary")
      .leftJoinAndSelect("current_holder.profileDisciplines", "profileDisciplines")
      .leftJoinAndSelect("current_holder.profileLeaves", "profileLeaves")
      .leftJoinAndSelect("current_holder.profileAssessments", "profileAssessments")
      .leftJoinAndSelect("current_holder.posLevel", "posLevel")
      .leftJoinAndSelect("current_holder.posType", "posType")
      .where({
        orgRevisionId: findRevision?.id,
        current_holderId: Not(IsNull()),
      })
      .andWhere(
        new Brackets((qb) => {
          qb.where(
            body.keyword != null && body.keyword != ""
              ? "current_holder.prefix LIKE :keyword"
              : "1=1",
            {
              keyword: `%${body.keyword}%`,
            },
          )
            .orWhere(
              body.keyword != null && body.keyword != ""
                ? "current_holder.firstName LIKE :keyword"
                : "1=1",
              {
                keyword: `%${body.keyword}%`,
              },
            )
            .orWhere(
              body.keyword != null && body.keyword != ""
                ? "current_holder.lastName LIKE :keyword"
                : "1=1",
              {
                keyword: `%${body.keyword}%`,
              },
            )
            .orWhere(
              body.keyword != null && body.keyword != ""
                ? "current_holder.position LIKE :keyword"
                : "1=1",
              {
                keyword: `%${body.keyword}%`,
              },
            )

            .orWhere(
              body.keyword != null && body.keyword != ""
                ? "current_holder.citizenId LIKE :keyword"
                : "1=1",
              {
                keyword: `%${body.keyword}%`,
              },
            )
            .orWhere(
              body.keyword != null && body.keyword != ""
                ? "posType.posTypeName LIKE :keyword"
                : "1=1",
              {
                keyword: `%${body.keyword}%`,
              },
            )
            .orWhere(
              body.keyword != null && body.keyword != ""
                ? "posLevel.posLevelName LIKE :keyword"
                : "1=1",
              {
                keyword: `%${body.keyword}%`,
              },
            );
        }),
      )
      .orderBy("current_holder.citizenId", "ASC")
      .skip((body.page - 1) * body.pageSize)
      .take(body.pageSize)
      .getManyAndCount();
    if (!findPosMaster) {
      throw new HttpError(HttpStatusCode.NOT_FOUND, "not found. PosMaster");
    }

    const formattedData = findPosMaster.map((item) => {
      let orgShortName = "";

      if (item.orgChild1Id === null) {
        orgShortName = item.orgRoot?.orgRootShortName;
      } else if (item.orgChild2Id === null) {
        orgShortName = item.orgChild1?.orgChild1ShortName;
      } else if (item.orgChild3Id === null) {
        orgShortName = item.orgChild2?.orgChild2ShortName;
      } else if (item.orgChild4Id === null) {
        orgShortName = item.orgChild3?.orgChild3ShortName;
      } else {
        orgShortName = item.orgChild4?.orgChild4ShortName;
      }

      const amount =
        item.current_holder == null || item.current_holder.profileSalary.length == 0
          ? null
          : item.current_holder.profileSalary.sort((a: any, b: any) => b.date - a.date)[0].amount;
      let datePeriodStart = new Date(
        `${new Date().getFullYear()}-${String(new Date().getMonth() + 1).padStart(2, "0")}-${String(new Date().getDate() + 1).padStart(2, "0")}T00:00:00.000Z`,
      );
      let datePeriodEnd = new Date(
        `${new Date().getFullYear()}-${String(new Date().getMonth() + 1).padStart(2, "0")}-${String(new Date().getDate() + 1).padStart(2, "0")}T00:00:00.000Z`,
      );
      if (body.period.toLocaleUpperCase() == "APR") {
        datePeriodStart = new Date(`${body.year}-03-31T00:00:00.000Z`);
        datePeriodEnd = new Date(`${body.year}-03-31T00:00:00.000Z`);
      }
      if (body.period.toLocaleUpperCase() == "OCT") {
        datePeriodStart = new Date(`${body.year}-09-30T00:00:00.000Z`);
        datePeriodEnd = new Date(`${body.year}-09-30T00:00:00.000Z`);
      }
      datePeriodStart = new Date(
        new Date(datePeriodStart.setDate(datePeriodStart.getDate() + 1)).setMonth(
          datePeriodStart.getMonth() - 6,
        ),
      );
      const latestProfileAssessment = item.current_holder.profileAssessments
        ? item.current_holder.profileAssessments.sort((a: any, b: any) => b.date - a.date)[0]
        : null;
      const pointSum = latestProfileAssessment
        ? `(${this.textPointSummaryKpi(latestProfileAssessment.pointSum)})${latestProfileAssessment.pointSum}`
        : null;
      return {
        profileId: item.current_holder.id,
        salaryLevel: item.current_holder.salaryLevel,
        group: item.current_holder.group,
        prefix: item.current_holder.prefix,
        firstName: item.current_holder.firstName,
        lastName: item.current_holder.lastName,
        citizenId: item.current_holder.citizenId,
        posMasterNoPrefix: item.posMasterNoPrefix,
        posMasterNo: item.posMasterNo,
        posMasterNoSuffix: item.posMasterNoSuffix,
        orgShortName: orgShortName,
        position: item.current_holder.position,
        posType:
          item.current_holder.posType == null ? null : item.current_holder.posType.posTypeName,
        posTypeShort:
          item.current_holder.posType == null ? null : item.current_holder.posType.posTypeShortName,
        posLevel:
          item.current_holder.posLevel == null ? null : item.current_holder.posLevel.posLevelName,
        amount: amount ? amount : null,
        rootId: item.orgRootId,
        root: item.orgRoot?.orgRootName ? item.orgRoot.orgRootName : null,
        child1Id: item.orgChild1Id,
        child1: item.orgChild1?.orgChild1Name ? item.orgChild1.orgChild1Name : null,
        child2Id: item.orgChild2Id,
        child2: item.orgChild2?.orgChild2Name ? item.orgChild2.orgChild2Name : null,
        child3Id: item.orgChild3Id,
        child3: item.orgChild3?.orgChild3Name ? item.orgChild3.orgChild3Name : null,
        child4Id: item.orgChild4Id,
        child4: item.orgChild4?.orgChild4Name ? item.orgChild4.orgChild4Name : null,
        result: pointSum,
        duration: null,
        isPunish:
          item.current_holder.profileDisciplines.filter(
            (x: any) =>
              new Date(
                `${new Date(x.date).getFullYear()}-${String(new Date(x.date).getMonth() + 1).padStart(2, "0")}-${String(new Date(x.date).getDate() + 1).padStart(2, "0")}T00:00:00.000Z`,
              ) >= datePeriodStart &&
              new Date(
                `${new Date(x.date).getFullYear()}-${String(new Date(x.date).getMonth() + 1).padStart(2, "0")}-${String(new Date(x.date).getDate() + 1).padStart(2, "0")}T00:00:00.000Z`,
              ) <= datePeriodEnd,
          ).length > 0
            ? true
            : false,
        isSuspension: item.current_holder.dateRetire == null ? false : true,
        isAbsent: item.current_holder.profileDisciplines.length > 0 ? true : false,
        isLeave: item.current_holder.profileLeaves.length > 0 ? true : false,
        isRetired:
          item.current_holder.birthDate == null ||
          calculateRetireDate(item.current_holder.birthDate).getFullYear() != body.year
            ? false
            : true,
      };
    });
    return new HttpSuccess({ data: formattedData, total: total });
  }

  /**
   * API หาสำนักทั้งหมด (unauthorize)
   *
   * @summary หาสำนักทั้งหมด (unauthorize)
   *
   */
  @Get("active/root/id")
  async _GetActiveRootId() {
    try {
      const orgRevisionActive = await this.orgRevisionRepository.findOne({
        where: { orgRevisionIsCurrent: true, orgRevisionIsDraft: false },
      });
      if (!orgRevisionActive) {
        throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบโครงสร้างที่เผยแพร่อยู่ตอนนี้");
      }

      const data = await this.orgRootRepository.find({
        where: { orgRevisionId: orgRevisionActive.id },
      });
      return new HttpSuccess(
        data.map((x) => ({
          rootId: x.id,
          root: x.orgRootName,
        })),
      );
    } catch (error) {
      return error;
    }
  }

  /**
   * API หา revision ล่าสุด (unauthorize)
   *
   * @summary หา revision ล่าสุด (unauthorize)
   *
   */
  @Get("revision/latest")
  async _salaryGen() {
    const findRevision = await this.orgRevisionRepository.findOne({
      where: { orgRevisionIsCurrent: true },
    });
    if (!findRevision) {
      throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบโครงสร้างล่าสุด");
    }
    return new HttpSuccess(findRevision.id);
  }

  /**
   * API หา user profile officer
   *
   * @summary หา user profile officer
   *
   */
  @Get("officer/{id}")
  async GetProfileById(@Path() id: string) {
    const findRevision = await this.orgRevisionRepository.findOne({
      where: { orgRevisionIsCurrent: true },
    });
    if (!findRevision) {
      throw new HttpError(HttpStatusCode.NOT_FOUND, "not found. OrgRevision");
    }

    const findProfile = await AppDataSource.getRepository(Profile)
      .createQueryBuilder("profile")
      .leftJoinAndSelect("profile.current_holders", "current_holders")
      .leftJoinAndSelect("current_holders.positions", "positions")
      .leftJoinAndSelect("positions.posExecutive", "posExecutive")
      .where({ id: id })
      .getOne();
    if (!findProfile) {
      throw new HttpError(HttpStatusCode.NOT_FOUND, "not found Profile");
    }

    const posExecutive =
      findProfile.current_holders == null ||
      findProfile.current_holders.length == 0 ||
      findProfile.current_holders.find((x) => x.orgRevisionId == findRevision.id) == null ||
      findProfile.current_holders.find((x) => x.orgRevisionId == findRevision.id)?.positions ==
        null ||
      findProfile.current_holders?.find((x) => x.orgRevisionId == findRevision.id)?.positions
        .length == 0 ||
      findProfile.current_holders
        .find((x) => x.orgRevisionId == findRevision.id)
        ?.positions?.find((position) => position.positionIsSelected == true) == null ||
      findProfile.current_holders
        .find((x) => x.orgRevisionId == findRevision.id)
        ?.positions?.find((position) => position.positionIsSelected == true)?.posExecutive ==
        null ||
      findProfile.current_holders
        .find((x) => x.orgRevisionId == findRevision.id)
        ?.positions?.find((position) => position.positionIsSelected == true)?.posExecutive
        ?.posExecutiveName == null
        ? null
        : findProfile.current_holders
            .find((x) => x.orgRevisionId == findRevision.id)
            ?.positions?.find((position) => position.positionIsSelected == true)?.posExecutive
            .posExecutiveName;
    const root =
      findProfile.current_holders == null ||
      findProfile.current_holders.length == 0 ||
      findProfile.current_holders.find((x) => x.orgRevisionId == findRevision.id) == null
        ? null
        : findProfile.current_holders.find((x) => x.orgRevisionId == findRevision.id)?.orgRoot;
    return new HttpSuccess({
      rootId: root == null ? null : root.id,
      root: root == null ? null : root.orgRootName,
      orgRootShortName: root == null ? null : root.orgRootShortName,
      orgRevisionId: findRevision.id,
      profileId: findProfile.id,
      type: "OFFICER",
      rank: findProfile.rank,
      prefix: findProfile.prefix,
      firstName: findProfile.firstName,
      lastName: findProfile.lastName,
      citizenId: findProfile.citizenId,
      position: findProfile.position,
      posExecutive: posExecutive,
      posLevelId: findProfile.posLevelId,
      posTypeId: findProfile.posTypeId,
    });
  }

  /**
   * API หา user profile employee
   *
   * @summary หา user profile employee
   *
   */
  @Get("employee/{id}")
  async GetProfileEmployeeById(@Path() id: string) {
    const findRevision = await this.orgRevisionRepository.findOne({
      where: { orgRevisionIsCurrent: true },
    });
    if (!findRevision) {
      throw new HttpError(HttpStatusCode.NOT_FOUND, "not found. OrgRevision");
    }

    const findProfile = await AppDataSource.getRepository(ProfileEmployee)
      .createQueryBuilder("profile")
      .leftJoinAndSelect("profile.current_holders", "current_holders")
      .leftJoinAndSelect("current_holders.positions", "positions")
      .leftJoinAndSelect("positions.posExecutive", "posExecutive")
      .where({ id: id })
      .getOne();
    if (!findProfile) {
      throw new HttpError(HttpStatusCode.NOT_FOUND, "not found Profile");
    }

    const root =
      findProfile.current_holders == null ||
      findProfile.current_holders.length == 0 ||
      findProfile.current_holders.find((x) => x.orgRevisionId == findRevision.id) == null
        ? null
        : findProfile.current_holders.find((x) => x.orgRevisionId == findRevision.id)?.orgRoot;

    return new HttpSuccess({
      rootId: root == null ? null : root.id,
      root: root == null ? null : root.orgRootName,
      orgRootShortName: root == null ? null : root.orgRootShortName,
      orgRevisionId: findRevision.id,
      profileId: findProfile.id,
      type: "OFFICER",
      rank: findProfile.rank,
      prefix: findProfile.prefix,
      firstName: findProfile.firstName,
      lastName: findProfile.lastName,
      citizenId: findProfile.citizenId,
      position: findProfile.position,
      posLevelId: findProfile.posLevelId,
      posTypeId: findProfile.posTypeId,
    });
  }

  /**
   * API หา user profile officer
   *
   * @summary หา user profile officer
   *
   */
  @Get("officer/citizen/{id}")
  async GetProfileByCitizenId(@Path() id: string) {
    const findRevision = await this.orgRevisionRepository.findOne({
      where: { orgRevisionIsCurrent: true },
    });
    if (!findRevision) {
      throw new HttpError(HttpStatusCode.NOT_FOUND, "not found. OrgRevision");
    }

    const findProfile = await AppDataSource.getRepository(Profile)
      .createQueryBuilder("profile")
      .leftJoinAndSelect("profile.current_holders", "current_holders")
      .leftJoinAndSelect("current_holders.orgRoot", "orgRoot")
      .leftJoinAndSelect("current_holders.orgChild1", "orgChild1")
      .leftJoinAndSelect("current_holders.orgChild2", "orgChild2")
      .leftJoinAndSelect("current_holders.orgChild3", "orgChild3")
      .leftJoinAndSelect("current_holders.orgChild4", "orgChild4")
      .leftJoinAndSelect("current_holders.positions", "positions")
      .leftJoinAndSelect("positions.posExecutive", "posExecutive")
      .where({ citizenId: id })
      .getOne();
    if (!findProfile) {
      throw new HttpError(HttpStatusCode.NOT_FOUND, "not found Profile");
    }

    const posExecutive =
      findProfile.current_holders == null ||
      findProfile.current_holders.length == 0 ||
      findProfile.current_holders.find((x) => x.orgRevisionId == findRevision.id) == null ||
      findProfile.current_holders.find((x) => x.orgRevisionId == findRevision.id)?.positions ==
        null ||
      findProfile.current_holders?.find((x) => x.orgRevisionId == findRevision.id)?.positions
        .length == 0 ||
      findProfile.current_holders
        .find((x) => x.orgRevisionId == findRevision.id)
        ?.positions?.find((position) => position.positionIsSelected == true) == null ||
      findProfile.current_holders
        .find((x) => x.orgRevisionId == findRevision.id)
        ?.positions?.find((position) => position.positionIsSelected == true)?.posExecutive ==
        null ||
      findProfile.current_holders
        .find((x) => x.orgRevisionId == findRevision.id)
        ?.positions?.find((position) => position.positionIsSelected == true)?.posExecutive
        ?.posExecutiveName == null
        ? null
        : findProfile.current_holders
            .find((x) => x.orgRevisionId == findRevision.id)
            ?.positions?.find((position) => position.positionIsSelected == true)?.posExecutive
            .posExecutiveName;
    const root =
      findProfile.current_holders == null ||
      findProfile.current_holders.length == 0 ||
      findProfile.current_holders.find((x) => x.orgRevisionId == findRevision.id) == null
        ? null
        : findProfile.current_holders.find((x) => x.orgRevisionId == findRevision.id)?.orgRoot;

    const child1 =
      findProfile.current_holders == null ||
      findProfile.current_holders.length == 0 ||
      findProfile.current_holders.find((x) => x.orgRevisionId == findRevision.id) == null
        ? null
        : findProfile.current_holders.find((x) => x.orgRevisionId == findRevision.id)?.orgChild1;

    const child2 =
      findProfile.current_holders == null ||
      findProfile.current_holders.length == 0 ||
      findProfile.current_holders.find((x) => x.orgRevisionId == findRevision.id) == null
        ? null
        : findProfile.current_holders.find((x) => x.orgRevisionId == findRevision.id)?.orgChild2;

    const child3 =
      findProfile.current_holders == null ||
      findProfile.current_holders.length == 0 ||
      findProfile.current_holders.find((x) => x.orgRevisionId == findRevision.id) == null
        ? null
        : findProfile.current_holders.find((x) => x.orgRevisionId == findRevision.id)?.orgChild3;

    const child4 =
      findProfile.current_holders == null ||
      findProfile.current_holders.length == 0 ||
      findProfile.current_holders.find((x) => x.orgRevisionId == findRevision.id) == null
        ? null
        : findProfile.current_holders.find((x) => x.orgRevisionId == findRevision.id)?.orgChild4;

    let _child1 = child1 == null ? "" : `${child1.orgChild1Name}/`;
    let _child2 = child2 == null ? "" : `${child2.orgChild2Name}/`;
    let _child3 = child3 == null ? "" : `${child3.orgChild3Name}/`;
    let _child4 = child4 == null ? "" : `${child4.orgChild4Name}/`;
    let _root = root == null ? "" : `${root.orgRootName}`;

    return new HttpSuccess({
      rootId: root == null ? null : root.id,
      root: root == null ? null : root.orgRootName,
      orgRootShortName: root == null ? null : root.orgRootShortName,
      orgRevisionId: findRevision.id,
      profileId: findProfile.id,
      org: `${_child4}${_child3}${_child2}${_child1}${_root}`,
      type: "OFFICER",
      rank: findProfile.rank,
      prefix: findProfile.prefix,
      firstName: findProfile.firstName,
      lastName: findProfile.lastName,
      citizenId: findProfile.citizenId,
      position: findProfile.position,
      posExecutive: posExecutive,
      posLevelId: findProfile.posLevelId,
      posTypeId: findProfile.posTypeId,
    });
  }

  /**
   * API หา user profile employee
   *
   * @summary หา user profile employee
   *
   */
  @Get("employee/citizen/{id}")
  async GetProfileEmployeeByCitizenId(@Path() id: string) {
    const findRevision = await this.orgRevisionRepository.findOne({
      where: { orgRevisionIsCurrent: true },
    });
    if (!findRevision) {
      throw new HttpError(HttpStatusCode.NOT_FOUND, "not found. OrgRevision");
    }

    const findProfile = await AppDataSource.getRepository(ProfileEmployee)
      .createQueryBuilder("profile")
      .leftJoinAndSelect("profile.current_holders", "current_holders")
      .leftJoinAndSelect("current_holders.orgRoot", "orgRoot")
      .leftJoinAndSelect("current_holders.orgChild1", "orgChild1")
      .leftJoinAndSelect("current_holders.orgChild2", "orgChild2")
      .leftJoinAndSelect("current_holders.orgChild3", "orgChild3")
      .leftJoinAndSelect("current_holders.orgChild4", "orgChild4")
      .leftJoinAndSelect("current_holders.positions", "positions")
      // .leftJoinAndSelect("positions.posExecutive", "posExecutive")
      .where({ citizenId: id })
      .getOne();
    if (!findProfile) {
      throw new HttpError(HttpStatusCode.NOT_FOUND, "not found Profile");
    }

    const root =
      findProfile.current_holders == null ||
      findProfile.current_holders.length == 0 ||
      findProfile.current_holders.find((x) => x.orgRevisionId == findRevision.id) == null
        ? null
        : findProfile.current_holders.find((x) => x.orgRevisionId == findRevision.id)?.orgRoot;

    const child1 =
      findProfile.current_holders == null ||
      findProfile.current_holders.length == 0 ||
      findProfile.current_holders.find((x) => x.orgRevisionId == findRevision.id) == null
        ? null
        : findProfile.current_holders.find((x) => x.orgRevisionId == findRevision.id)?.orgChild1;

    const child2 =
      findProfile.current_holders == null ||
      findProfile.current_holders.length == 0 ||
      findProfile.current_holders.find((x) => x.orgRevisionId == findRevision.id) == null
        ? null
        : findProfile.current_holders.find((x) => x.orgRevisionId == findRevision.id)?.orgChild2;

    const child3 =
      findProfile.current_holders == null ||
      findProfile.current_holders.length == 0 ||
      findProfile.current_holders.find((x) => x.orgRevisionId == findRevision.id) == null
        ? null
        : findProfile.current_holders.find((x) => x.orgRevisionId == findRevision.id)?.orgChild3;

    const child4 =
      findProfile.current_holders == null ||
      findProfile.current_holders.length == 0 ||
      findProfile.current_holders.find((x) => x.orgRevisionId == findRevision.id) == null
        ? null
        : findProfile.current_holders.find((x) => x.orgRevisionId == findRevision.id)?.orgChild4;

    let _child1 = child1 == null ? "" : `${child1.orgChild1Name}/`;
    let _child2 = child2 == null ? "" : `${child2.orgChild2Name}/`;
    let _child3 = child3 == null ? "" : `${child3.orgChild3Name}/`;
    let _child4 = child4 == null ? "" : `${child4.orgChild4Name}/`;
    let _root = root == null ? "" : `${root.orgRootName}`;

    return new HttpSuccess({
      rootId: root == null ? null : root.id,
      root: root == null ? null : root.orgRootName,
      orgRootShortName: root == null ? null : root.orgRootShortName,
      orgRevisionId: findRevision.id,
      profileId: findProfile.id,
      org: `${_child4}${_child3}${_child2}${_child1}${_root}`,
      type: "EMPLOYEE",
      rank: findProfile.rank,
      prefix: findProfile.prefix,
      firstName: findProfile.firstName,
      lastName: findProfile.lastName,
      citizenId: findProfile.citizenId,
      position: findProfile.position,
      posLevelId: findProfile.posLevelId,
      posTypeId: findProfile.posTypeId,
    });
  }

  /**
   * API หา user profile employee
   *
   * @summary หา user profile employee
   *
   */
  @Get("employee-prem/citizen/{id}")
  async GetProfileEmployeePremByCitizenId(@Path() id: string) {
    const findRevision = await this.orgRevisionRepository.findOne({
      where: { orgRevisionIsCurrent: true },
    });
    if (!findRevision) {
      throw new HttpError(HttpStatusCode.NOT_FOUND, "not found. OrgRevision");
    }

    const findProfile = await AppDataSource.getRepository(ProfileEmployee)
      .createQueryBuilder("profile")
      .leftJoinAndSelect("profile.current_holders", "current_holders")
      .leftJoinAndSelect("current_holders.orgRoot", "orgRoot")
      .leftJoinAndSelect("current_holders.orgChild1", "orgChild1")
      .leftJoinAndSelect("current_holders.orgChild2", "orgChild2")
      .leftJoinAndSelect("current_holders.orgChild3", "orgChild3")
      .leftJoinAndSelect("current_holders.orgChild4", "orgChild4")
      .leftJoinAndSelect("current_holders.positions", "positions")
      // .leftJoinAndSelect("positions.posExecutive", "posExecutive")
      .where({ citizenId: id, employeeclass: "PREM" })
      .getOne();
    if (!findProfile) {
      throw new HttpError(HttpStatusCode.NOT_FOUND, "not found Profile");
    }

    const root =
      findProfile.current_holders == null ||
      findProfile.current_holders.length == 0 ||
      findProfile.current_holders.find((x) => x.orgRevisionId == findRevision.id) == null
        ? null
        : findProfile.current_holders.find((x) => x.orgRevisionId == findRevision.id)?.orgRoot;

    const child1 =
      findProfile.current_holders == null ||
      findProfile.current_holders.length == 0 ||
      findProfile.current_holders.find((x) => x.orgRevisionId == findRevision.id) == null
        ? null
        : findProfile.current_holders.find((x) => x.orgRevisionId == findRevision.id)?.orgChild1;

    const child2 =
      findProfile.current_holders == null ||
      findProfile.current_holders.length == 0 ||
      findProfile.current_holders.find((x) => x.orgRevisionId == findRevision.id) == null
        ? null
        : findProfile.current_holders.find((x) => x.orgRevisionId == findRevision.id)?.orgChild2;

    const child3 =
      findProfile.current_holders == null ||
      findProfile.current_holders.length == 0 ||
      findProfile.current_holders.find((x) => x.orgRevisionId == findRevision.id) == null
        ? null
        : findProfile.current_holders.find((x) => x.orgRevisionId == findRevision.id)?.orgChild3;

    const child4 =
      findProfile.current_holders == null ||
      findProfile.current_holders.length == 0 ||
      findProfile.current_holders.find((x) => x.orgRevisionId == findRevision.id) == null
        ? null
        : findProfile.current_holders.find((x) => x.orgRevisionId == findRevision.id)?.orgChild4;

    let _child1 = child1 == null ? "" : `${child1.orgChild1Name}/`;
    let _child2 = child2 == null ? "" : `${child2.orgChild2Name}/`;
    let _child3 = child3 == null ? "" : `${child3.orgChild3Name}/`;
    let _child4 = child4 == null ? "" : `${child4.orgChild4Name}/`;
    let _root = root == null ? "" : `${root.orgRootName}`;

    return new HttpSuccess({
      rootId: root == null ? null : root.id,
      root: root == null ? null : root.orgRootName,
      orgRootShortName: root == null ? null : root.orgRootShortName,
      orgRevisionId: findRevision.id,
      profileId: findProfile.id,
      org: `${_child4}${_child3}${_child2}${_child1}${_root}`,
      type: "EMPLOYEE",
      rank: findProfile.rank,
      prefix: findProfile.prefix,
      firstName: findProfile.firstName,
      lastName: findProfile.lastName,
      citizenId: findProfile.citizenId,
      position: findProfile.position,
      posLevelId: findProfile.posLevelId,
      posTypeId: findProfile.posTypeId,
    });
  }
  textPointSummaryKpi(val: number | undefined) {
    if (val == undefined || val == null) val = -1;
    if (val >= 0 && val <= 60) return "ต้องปรับปรุง";
    if (val >= 60 && val <= 69) return "พอใช้";
    if (val >= 70 && val <= 79) return "ดี";
    if (val >= 80 && val <= 89) return "ดีมาก";
    if (val >= 90 && val <= 100) return "ดีเด่น";
    else return "-";
  }

  /**
   * API หาสำนักทั้งหมด
   *
   * @summary หาสำนักทั้งหมด
   *
   */
  @Get("active/root/all")
  async GetActiveRootAll() {
    const orgRevisionActive = await this.orgRevisionRepository.findOne({
      where: { orgRevisionIsCurrent: true, orgRevisionIsDraft: false },
    });
    if (!orgRevisionActive) {
      throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบโครงสร้างที่เผยแพร่อยู่ตอนนี้");
    }

    const data = await this.orgRootRepository.find({
      where: { orgRevisionId: orgRevisionActive.id },
    });
    return new HttpSuccess(data);
  }

  /**
   * 3.	API Get Profile จาก keycloak id
   *
   * @summary 3. API Get Profile จาก keycloak id
   *
   * @param {string} keycloakId  Id keycloak
   */
  @Get("root/officer/{rootId}")
  async GetProfileByRootIdAsync(@Path() rootId: string) {
    const profiles = await this.profileRepo.find({
      relations: {
        posLevel: true,
        posType: true,
        profileSalary: true,
        profileInsignias: true,
      },
      where: { current_holders: { orgRootId: rootId } },
      order: {
        profileSalary: {
          date: "DESC",
        },
        profileInsignias: {
          receiveDate: "DESC",
        },
      },
    });
    // if (!profile) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูล");

    const mapProfile = profiles.map((profile) => ({
      id: profile.id,
      avatar: profile.avatar,
      avatarName: profile.avatarName,
      rank: profile.rank,
      prefix: profile.prefix,
      firstName: profile.firstName,
      lastName: profile.lastName,
      citizenId: profile.citizenId,
      position: profile.position,
      posLevelId: profile.posLevelId,
      email: profile.email,
      phone: profile.phone,
      keycloak: profile.keycloak,
      isProbation: profile.isProbation,
      isLeave: profile.isLeave,
      leaveReason: profile.leaveReason,
      dateRetire: profile.dateRetire,
      dateAppoint: profile.dateAppoint,
      dateRetireLaw: profile.dateRetireLaw,
      dateStart: profile.dateStart,
      govAgeAbsent: profile.govAgeAbsent,
      govAgePlus: profile.govAgePlus,
      birthDate: profile.birthDate,
      reasonSameDate: profile.reasonSameDate,
      telephoneNumber: profile.telephoneNumber,
      nationality: profile.nationality,
      gender: profile.gender,
      relationship: profile.relationship,
      religion: profile.religion,
      bloodGroup: profile.bloodGroup,
      registrationAddress: profile.registrationAddress,
      registrationProvinceId: profile.registrationProvinceId,
      registrationDistrictId: profile.registrationDistrictId,
      registrationSubDistrictId: profile.registrationSubDistrictId,
      registrationZipCode: profile.registrationZipCode,
      currentAddress: profile.currentAddress,
      currentProvinceId: profile.currentProvinceId,
      currentSubDistrictId: profile.currentSubDistrictId,
      currentZipCode: profile.currentZipCode,
      dutyTimeId: profile.dutyTimeId,
      dutyTimeEffectiveDate: profile.dutyTimeEffectiveDate,
      posLevel: profile.posLevel ? profile.posLevel : null,
      posType: profile.posType ? profile.posType : null,
      profileSalary: profile.profileSalary,
      profileInsignia: profile.profileInsignias,
    }));

    return new HttpSuccess(mapProfile);
  }

  /**
   * 3.	API Get Profile จาก keycloak id
   *
   * @summary 3. API Get Profile จาก keycloak id
   *
   * @param {string} keycloakId  Id keycloak
   */
  @Get("root/employee/{rootId}")
  async GetProfileByRootIdEmpAsync(@Path() rootId: string) {
    const profiles = await this.profileEmpRepo.find({
      relations: {
        posLevel: true,
        posType: true,
        profileSalary: true,
        profileInsignias: true,
      },
      where: { current_holders: { orgRootId: rootId } },
      order: {
        profileSalary: {
          date: "DESC",
        },
        profileInsignias: {
          receiveDate: "DESC",
        },
      },
    });
    // if (!profile) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูล");

    const mapProfile = profiles.map((profile) => ({
      id: profile.id,
      avatar: profile.avatar,
      avatarName: profile.avatarName,
      rank: profile.rank,
      prefix: profile.prefix,
      firstName: profile.firstName,
      lastName: profile.lastName,
      citizenId: profile.citizenId,
      position: profile.position,
      posLevelId: profile.posLevelId,
      email: profile.email,
      phone: profile.phone,
      keycloak: profile.keycloak,
      isProbation: profile.isProbation,
      isLeave: profile.isLeave,
      leaveReason: profile.leaveReason,
      dateRetire: profile.dateRetire,
      dateAppoint: profile.dateAppoint,
      dateRetireLaw: profile.dateRetireLaw,
      dateStart: profile.dateStart,
      govAgeAbsent: profile.govAgeAbsent,
      govAgePlus: profile.govAgePlus,
      birthDate: profile.birthDate,
      reasonSameDate: profile.reasonSameDate,
      telephoneNumber: profile.telephoneNumber,
      nationality: profile.nationality,
      gender: profile.gender,
      relationship: profile.relationship,
      religion: profile.religion,
      bloodGroup: profile.bloodGroup,
      registrationAddress: profile.registrationAddress,
      registrationProvinceId: profile.registrationProvinceId,
      registrationDistrictId: profile.registrationDistrictId,
      registrationSubDistrictId: profile.registrationSubDistrictId,
      registrationZipCode: profile.registrationZipCode,
      currentAddress: profile.currentAddress,
      currentProvinceId: profile.currentProvinceId,
      currentSubDistrictId: profile.currentSubDistrictId,
      currentZipCode: profile.currentZipCode,
      //   dutyTimeId: profile.dutyTimeId,
      //   dutyTimeEffectiveDate: profile.dutyTimeEffectiveDate,
      posLevel: profile.posLevel ? profile.posLevel : null,
      posType: profile.posType ? profile.posType : null,
      profileSalary: profile.profileSalary,
      profileInsignia: profile.profileInsignias,
    }));

    return new HttpSuccess(mapProfile);
  }
}
