// FILE: backend/src/utils/scope.js
// 03.2 5) เพิ่ม utils/scope.js (ใหม่)
// - ใช้ร่วมกับ requirePerm() และ loadPrincipal()
// - สำหรับสร้าง SQL WHERE clause ในการ list entities ตาม scope ของผู้ใช้
// Scope and permission utilities
// - Functions to build SQL WHERE clauses based on user principal and permissions
// - Used for filtering list queries according to user's
//   roles, permissions, and associated orgs/projects
// - Works with rbac.js loadPrincipal() output
// - Supports SUPER_ADMIN, ADMIN, and scoped permissions

/**
 * สร้าง WHERE fragment + params สำหรับ list ตาม principal
 * - SUPER_ADMIN: ไม่จำกัด
 * - ADMIN: จำกัดใน org/project ที่ตนสังกัด
 * - อื่น ๆ: จำกัดตาม permission scope ที่มี
 *
 * @param {object} principal - จาก loadPrincipal()
 * @param {object} opts
 *   tableAlias: ชื่อ alias ของตารางหลัก (เช่น 'c' สำหรับ correspondences)
 *   orgColumn:  ระบุคอลัมน์ org_id (เช่น 'c.org_id')
 *   projectColumn: ระบุคอลัมน์ project_id (เช่น 'c.project_id')
 *   permCode: permission_code ที่ใช้สำหรับ read list (เช่น 'correspondence.read')
 *   preferProject: true -> บังคับต้อง match project scope ก่อน (ถ้ามี)
 */
export function buildScopeWhere(
  principal,
  { tableAlias, orgColumn, projectColumn, permCode, preferProject = false }
) {
  if (principal.isSuperAdmin) return { where: "1=1", params: {} };

  const perm = principal.perms.get(permCode);
  const orgIds = new Set(principal.orgIds);
  const projectIds = new Set(principal.projectIds);

  // กรณี ADMIN: ให้ดูภายใน org/project ตัวเองได้ทั้งหมด (แต่ต้องถือ permCode)
  if (principal.roleCodes.has("ADMIN") && perm) {
    const orgList = [...orgIds];
    const prjList = [...projectIds];
    if (preferProject && prjList.length > 0) {
      return {
        where: `${projectColumn} IN (:prjList)`,
        params: { prjList },
      };
    }
    if (orgList.length > 0) {
      return {
        where: `${orgColumn} IN (:orgList)`,
        params: { orgList },
      };
    }
    // ถ้าไม่มี mapping เลย ให้ไม่เห็นอะไร
    return { where: "1=0", params: {} };
  }

  // บทบาทอื่น: อิงตาม perm scope
  if (!perm) return { where: "1=0", params: {} };

  const permOrg = [...perm.orgIds];
  const permPrj = [...perm.projectIds];

  if (preferProject && permPrj.length > 0) {
    return { where: `${projectColumn} IN (:permPrj)`, params: { permPrj } };
  }
  if (permOrg.length > 0) {
    return { where: `${orgColumn} IN (:permOrg)`, params: { permOrg } };
  }

  // ถ้า perm ไม่มี scope ผูก (global grant) ให้ผ่านทั้งหมด
  return { where: "1=1", params: {} };
}

/**
 * owner resolvers: อ่าน org_id/project_id จาก DB ด้วย id
 * ใช้กับ requirePerm(getOrgId/getProjectId) เสมอ
 */
export function ownerResolvers(sql, mainTable, idColumn = "id") {
  return {
    async getOrgIdById(req) {
      const id = Number(req.params.id ?? req.body?.id);
      if (!id) return null;
      const [[row]] = await sql.query(
        `SELECT org_id FROM ${mainTable} WHERE ${idColumn}=?`,
        [id]
      );
      return row?.org_id ?? null;
    },
    async getProjectIdById(req) {
      const id = Number(req.params.id ?? req.body?.id);
      if (!id) return null;
      const [[row]] = await sql.query(
        `SELECT project_id FROM ${mainTable} WHERE ${idColumn}=?`,
        [id]
      );
      return row?.project_id ?? null;
    },
  };
}
