import { AppDataSource } from "../database/data-source";
import { AuthRoleAttr } from "../entities/AuthRoleAttr";
import { PosMasterAct } from "../entities/PosMasterAct";

export interface ActingPositionData {
  isAct: boolean;
  posMasterActs: Array<{
    privilege: string | null;
    posNo: string | null;
    rootDnaId: string | null;
    child1DnaId: string | null;
    child2DnaId: string | null;
    child3DnaId: string | null;
    child4DnaId: string | null;
  }>;
}

export interface ActingPositionWithPrivilegeData extends ActingPositionData {
  privilege?: string | null;
}

/**
 * Service สำหรับจัดการข้อมูลตำแหน่งที่รักษาการและ privilege
 */
export class ActingPositionService {
  private posMasterActRepo = AppDataSource.getRepository(PosMasterAct);
  private authRoleAttrRepo = AppDataSource.getRepository(AuthRoleAttr);

  /**
   * ดึงข้อมูลตำแหน่งที่รักษาการและ privilege
   *
   * @param profileId - ID ของ profile ที่ต้องการตรวจสอบ
   * @param orgRevisionId - ID ของ orgRevision ปัจจุบัน
   * @param action - Action ที่ต้องการตรวจสอบสิทธิ์ (CREATE, DELETE, GET, LIST, UPDATE)
   * @param system - System ID ที่ต้องการตรวจสอบสิทธิ์ (authSysId)
   * @returns ข้อมูลตำแหน่งที่รักษาการและ privilege
   */
  async getActingPositionsWithPrivilege(
    profileId: string,
    orgRevisionId: string | undefined,
    action?: string,
    system?: string
  ): Promise<ActingPositionWithPrivilegeData> {
    // ดึงข้อมูล posMasterAct โดย join กับ posMaster (ตำแหน่งที่ถูกรักษาการ)
    const posMasterActs = await this.posMasterActRepo
      .createQueryBuilder("posMasterAct")
      .leftJoinAndSelect("posMasterAct.posMaster", "posMaster")
      .addSelect([
        "posMaster.authRoleId",  // เพิ่มการดึง authRoleId จากตำแหน่งที่ถูกรักษาการ
        "posMaster.posMasterNo",   // เพิ่มการดึงเลขที่ตำแหน่ง
        "posMaster.posMasterNoPrefix",  // เพิ่มการดึง prefix ของเลขที่ตำแหน่ง
        "posMaster.posMasterNoSuffix"   // เพิ่มการดึง suffix ของเลขที่ตำแหน่ง
      ])
      .leftJoinAndSelect("posMaster.orgRoot", "orgRoot")
      .leftJoinAndSelect("posMaster.orgChild1", "orgChild1")
      .leftJoinAndSelect("posMaster.orgChild2", "orgChild2")
      .leftJoinAndSelect("posMaster.orgChild3", "orgChild3")
      .leftJoinAndSelect("posMaster.orgChild4", "orgChild4")
      .leftJoinAndSelect("posMaster.orgRevision", "orgRevision")
      .leftJoinAndSelect("posMasterAct.posMasterChild", "posMasterChild")
      .leftJoinAndSelect("posMasterChild.current_holder", "profileChild")
      .where("profileChild.id = :profileId", { profileId })
      .andWhere("posMaster.orgRevisionId = :orgRevisionId", { orgRevisionId })
      .andWhere("orgRevision.orgRevisionIsCurrent = true")
      .andWhere("orgRevision.orgRevisionIsDraft = false")
      .getMany();

    if (posMasterActs.length === 0) {
      return {
        isAct: false,
        posMasterActs: [],
      };
    }

    // วนลูปแต่ละ posMasterAct เพื่อดึง privilege ของตำแหน่งที่รักษาการ
    const posMasterActsResponse = await Promise.all(
      posMasterActs.map(async (act) => {
        let privilege: string | null = null;
        let privileges: Record<string, string> = {};

        if (act.posMaster?.authRoleId) {
          // ถ้าระบุ action และ system มา ให้ดึงเฉพาะ privilege ของระบบนั้นๆ
          if (action && system) {
            const roleAttr = await this.authRoleAttrRepo
              .createQueryBuilder("authRoleAttr")
              .select(["authRoleAttr.attrPrivilege", "authRoleAttr.attrIsCreate", "authRoleAttr.attrIsDelete", "authRoleAttr.attrIsGet", "authRoleAttr.attrIsList", "authRoleAttr.attrIsUpdate"])
              .where("authRoleAttr.authRoleId = :authRoleId", {
                authRoleId: act.posMaster.authRoleId,
              })
              .andWhere("authRoleAttr.authSysId = :system", { system })
              .getOne();

            if (roleAttr) {
              // ตรวจสอบสิทธิ์ตาม action
              let hasPermission = false;
              const actionUpper = action.trim().toUpperCase();

              switch (actionUpper) {
                case "CREATE":
                  hasPermission = roleAttr.attrIsCreate;
                  break;
                case "DELETE":
                  hasPermission = roleAttr.attrIsDelete;
                  break;
                case "GET":
                  hasPermission = roleAttr.attrIsGet;
                  break;
                case "LIST":
                  hasPermission = roleAttr.attrIsList;
                  break;
                case "UPDATE":
                  hasPermission = roleAttr.attrIsUpdate;
                  break;
              }

              if (hasPermission) {
                privilege = roleAttr.attrPrivilege;
              }
            }
          } else {
            // ดึงข้อมูล AuthRoleAttr สำหรับทุกระบบ
            const roleAttrs = await this.authRoleAttrRepo
              .createQueryBuilder("authRoleAttr")
              .select(["authRoleAttr.authSysId", "authRoleAttr.attrPrivilege"])
              .where("authRoleAttr.authRoleId = :authRoleId", {
                authRoleId: act.posMaster.authRoleId,
              })
              .getMany();

            privileges = roleAttrs.reduce((acc, attr) => {
              acc[attr.authSysId] = attr.attrPrivilege;
              return acc;
            }, {} as Record<string, string>);
          }
        }

        // จัดรูปแบบเลขที่ตำแหน่งตามรูปแบบ shortName ที่ใช้ในระบบ
        const holder = act.posMaster;
        const posNo = !holder
          ? null
          : holder.orgChild4 != null
            ? `${holder.orgChild4.orgChild4ShortName} ${holder.posMasterNo}`
            : holder.orgChild3 != null
              ? `${holder.orgChild3.orgChild3ShortName} ${holder.posMasterNo}`
              : holder.orgChild2 != null
                ? `${holder.orgChild2.orgChild2ShortName} ${holder.posMasterNo}`
                : holder.orgChild1 != null
                  ? `${holder.orgChild1.orgChild1ShortName} ${holder.posMasterNo}`
                  : holder.orgRoot != null
                    ? `${holder.orgRoot.orgRootShortName} ${holder.posMasterNo}`
                    : null;

        return {
          posNo: posNo,
          privilege: action && system ? privilege : JSON.stringify(privileges),
          rootDnaId: act.posMaster?.orgRoot?.ancestorDNA ?? null,
          child1DnaId: act.posMaster?.orgChild1?.ancestorDNA ?? null,
          child2DnaId: act.posMaster?.orgChild2?.ancestorDNA ?? null,
          child3DnaId: act.posMaster?.orgChild3?.ancestorDNA ?? null,
          child4DnaId: act.posMaster?.orgChild4?.ancestorDNA ?? null,
        };
      })
    );

    // ถ้าระบุ action และ system มา ให้ดึง privilege ของตำแหน่งแรก
    let specificPrivilege: string | null = null;
    if (action && system && posMasterActsResponse.length > 0) {
      specificPrivilege = posMasterActsResponse[0].privilege;
    }

    const response: ActingPositionWithPrivilegeData = {
      isAct: true,
      posMasterActs: posMasterActsResponse,
    };

    // ถ้าระบุ action และ system มา ให้เพิ่ม privilege เข้าไปใน response ด้วย
    if (action && system) {
      response.privilege = specificPrivilege ?? null;
    }

    return response;
  }
}

// Export singleton instance
export const actingPositionService = new ActingPositionService();
