import { query, withDbSession } from "../config/db.js";

const FALLBACK_PAGES_BY_ROLE = {
  admin: ["/", "/cases", "/deadlines", "/meetings", "/agenda-items", "/decisions", "/reports", "/finance", "/tasks", "/calendar", "/documents", "/comments", "/notifications", "/users", "/committees", "/templates", "/permissions", "/security", "/audit"],
  chair: ["/", "/cases", "/deadlines", "/meetings", "/agenda-items", "/decisions", "/reports", "/finance", "/tasks", "/calendar", "/documents", "/comments", "/notifications", "/committees", "/templates"],
  secretary: ["/", "/meetings", "/agenda-items", "/decisions", "/reports", "/finance", "/tasks", "/calendar", "/documents", "/comments", "/notifications"],
  member: ["/", "/cases", "/deadlines", "/tasks", "/calendar", "/documents", "/comments", "/notifications"],
  advisor: ["/", "/calendar", "/documents", "/comments", "/notifications"],
};

export function fallbackAllowedPagePaths(role) {
  return FALLBACK_PAGES_BY_ROLE[role] || ["/"];
}

export async function getUserAccess(userId, role) {
  try {
    return await withDbSession({ sub: userId, role }, async (db) => {
      const pages = await db.query(
        `SELECT DISTINCT p.page_key, p.path, p.label, p.nav_group, p.sort_order
             FROM app_page p
             JOIN app_role_page rp ON rp.page_key = p.page_key AND rp.can_view = TRUE
             JOIN app_role_profile r ON r.id = rp.role_profile_id AND r.is_active = TRUE
            WHERE r.system_role::TEXT = $2
               OR EXISTS (
                 SELECT 1 FROM app_user_role_profile urp
                  WHERE urp.role_profile_id = r.id
                    AND urp.user_id = $1
               )
            ORDER BY p.sort_order, p.label`,
          [userId, role]
        );

      const permissions = await db.query(
        `SELECT DISTINCT perm.permission_key
             FROM app_permission perm
             JOIN app_role_permission rp ON rp.permission_key = perm.permission_key AND rp.granted = TRUE
             JOIN app_role_profile r ON r.id = rp.role_profile_id AND r.is_active = TRUE
            WHERE r.system_role::TEXT = $2
               OR EXISTS (
                 SELECT 1 FROM app_user_role_profile urp
                  WHERE urp.role_profile_id = r.id
                    AND urp.user_id = $1
               )
            ORDER BY perm.permission_key`,
          [userId, role]
        );

      const roleProfiles = await db.query(
        `SELECT DISTINCT r.id, r.code, r.name, r.description, r.system_role, r.is_system
             FROM app_role_profile r
            WHERE r.is_active = TRUE
              AND (
                r.system_role::TEXT = $2
                OR EXISTS (
                  SELECT 1 FROM app_user_role_profile urp
                   WHERE urp.role_profile_id = r.id
                     AND urp.user_id = $1
                )
              )
            ORDER BY r.is_system DESC, r.name`,
          [userId, role]
        );

      const teamRoles = await db.query(
        `SELECT tr.id, tr.code, tr.name, tr.description,
                  tr.can_view_cases, tr.can_write_cases,
                  tr.can_view_documents, tr.can_write_documents,
                  utr.committee_id
             FROM app_user_team_role utr
             JOIN app_team_role tr ON tr.id = utr.team_role_id
            WHERE utr.user_id = $1
              AND tr.is_active = TRUE
            ORDER BY tr.name`,
          [userId]
        );

      const pageRows = pages.rows || [];
      const permissionKeys = permissions.rows.map((row) => row.permission_key);
      const pagePaths = pageRows.map((row) => row.path);

      if (role === "admin") {
        return {
          allowed_pages: pageRows,
          allowed_page_paths: pagePaths.length ? pagePaths : fallbackAllowedPagePaths(role),
          permissions: permissionKeys.includes("system.admin") ? permissionKeys : ["system.admin", ...permissionKeys],
          role_profiles: roleProfiles.rows,
          team_roles: teamRoles.rows,
        };
      }

      return {
        allowed_pages: pageRows,
        allowed_page_paths: pagePaths.length ? pagePaths : fallbackAllowedPagePaths(role),
        permissions: permissionKeys,
        role_profiles: roleProfiles.rows,
        team_roles: teamRoles.rows,
      };
    });
  } catch (err) {
    return {
      allowed_pages: [],
      allowed_page_paths: fallbackAllowedPagePaths(role),
      permissions: role === "admin" ? ["system.admin"] : [],
      role_profiles: [],
      team_roles: [],
    };
  }
}

export async function userHasPermission(userId, role, permissionKey) {
  if (role === "admin") return true;
  const result = await query(`SELECT app_has_permission($1, $2::bigint, $3::text) AS allowed`, [permissionKey, userId, role || "anonymous"]);
  return Boolean(result.rows[0]?.allowed);
}

export async function userCanViewPage(userId, role, pageKey) {
  if (role === "admin") return true;
  const result = await query(`SELECT app_can_view_page($1, $2::bigint, $3::text) AS allowed`, [pageKey, userId, role || "anonymous"]);
  return Boolean(result.rows[0]?.allowed);
}
