/**
 * Système de permissions et habilitations pour l'Espace Paie Odentas
 * 
 * Hiérarchie des rôles clients :
 * - SUPER_ADMIN : Compte principal protégé (1 seul par org)
 * - ADMIN : Accès total aux données
 * - AGENT : Opérationnel (contrats, paies, salariés)
 * - COMPTA : Lecture seule financière (cotisations, virements, facturation)
 * 
 * STAFF : Accès total toutes organisations (réservé Odentas)
 */

import { createRouteHandlerClient } from "@supabase/auth-helpers-nextjs";
import { cookies } from "next/headers";
import type { SupabaseClient } from "@supabase/supabase-js";

// ============================================================================
// Types
// ============================================================================

export type UserRole = "SUPER_ADMIN" | "ADMIN" | "AGENT" | "COMPTA";

export interface UserPermissions {
  userId: string;
  role: UserRole;
  orgId: string;
  isStaff: boolean;
}

export interface PermissionCheck {
  allowed: boolean;
  reason?: string;
}

// ============================================================================
// Type de documents pour COMPTA
// ============================================================================

const COMPTA_ALLOWED_DOCUMENT_TYPES = [
  "facture",
  "devis",
  "releve_cotisations",
  "virement_salaires",
  "justificatif_bancaire",
  "bilan",
  "comptable"
];

// ============================================================================
// Récupération des permissions utilisateur
// ============================================================================

/**
 * Récupère les permissions d'un utilisateur authentifié
 * @returns UserPermissions ou null si non authentifié
 */
export async function getUserPermissions(
  supabase?: SupabaseClient
): Promise<UserPermissions | null> {
  const sb = supabase || createRouteHandlerClient({ cookies });

  // 1. Vérifier l'authentification
  const {
    data: { user },
    error: authError,
  } = await sb.auth.getUser();

  if (authError || !user) {
    return null;
  }

  // 2. Vérifier si c'est un staff
  const { data: staffData } = await (sb as any)
    .from("staff_users")
    .select("is_staff")
    .eq("user_id", user.id)
    .maybeSingle();

  const isStaff = !!staffData?.is_staff;

  // Si staff, retourner avec rôle SUPER_ADMIN et pas d'orgId
  if (isStaff) {
    return {
      userId: user.id,
      role: "SUPER_ADMIN",
      orgId: "", // Staff n'a pas d'org spécifique
      isStaff: true,
    };
  }

  // 3. Récupérer le rôle dans une organisation
  const { data: memberData } = await (sb as any)
    .from("organization_members")
    .select("role, org_id, revoked")
    .eq("user_id", user.id)
    .eq("revoked", false)
    .maybeSingle();

  if (!memberData) {
    return null;
  }

  return {
    userId: user.id,
    role: memberData.role as UserRole,
    orgId: memberData.org_id,
    isStaff: false,
  };
}

// ============================================================================
// Vérifications de permissions par domaine
// ============================================================================

/**
 * Vérifie si l'utilisateur peut accéder à la facturation
 * Autorisé : SUPER_ADMIN, ADMIN, COMPTA
 * Bloqué : AGENT
 */
export function canAccessFacturation(permissions: UserPermissions | null): PermissionCheck {
  if (!permissions) {
    return { allowed: false, reason: "Non authentifié" };
  }

  if (permissions.isStaff) {
    return { allowed: true };
  }

  if (permissions.role === "AGENT") {
    return { allowed: false, reason: "Les agents n'ont pas accès à la facturation" };
  }

  return { allowed: true };
}

/**
 * Vérifie si l'utilisateur peut MODIFIER la facturation
 * Autorisé : SUPER_ADMIN, ADMIN
 * Bloqué : AGENT, COMPTA
 */
export function canModifyFacturation(permissions: UserPermissions | null): PermissionCheck {
  if (!permissions) {
    return { allowed: false, reason: "Non authentifié" };
  }

  if (permissions.isStaff) {
    return { allowed: true };
  }

  if (permissions.role === "COMPTA") {
    return { allowed: false, reason: "Le rôle COMPTA est en lecture seule" };
  }

  if (permissions.role === "AGENT") {
    return { allowed: false, reason: "Les agents n'ont pas accès à la facturation" };
  }

  return { allowed: true }; // SUPER_ADMIN ou ADMIN
}

/**
 * Vérifie si l'utilisateur peut accéder aux cotisations
 * Autorisé : SUPER_ADMIN, ADMIN, COMPTA
 * Bloqué : AGENT
 */
export function canAccessCotisations(permissions: UserPermissions | null): PermissionCheck {
  if (!permissions) {
    return { allowed: false, reason: "Non authentifié" };
  }

  if (permissions.isStaff) {
    return { allowed: true };
  }

  if (permissions.role === "AGENT") {
    return { allowed: false, reason: "Les agents n'ont pas accès aux cotisations" };
  }

  return { allowed: true };
}

/**
 * Vérifie si l'utilisateur peut accéder aux virements salaires
 * Autorisé : SUPER_ADMIN, ADMIN, COMPTA
 * Bloqué : AGENT
 */
export function canAccessVirements(permissions: UserPermissions | null): PermissionCheck {
  if (!permissions) {
    return { allowed: false, reason: "Non authentifié" };
  }

  if (permissions.isStaff) {
    return { allowed: true };
  }

  if (permissions.role === "AGENT") {
    return { allowed: false, reason: "Les agents n'ont pas accès aux virements salaires" };
  }

  return { allowed: true };
}

/**
 * Vérifie si l'utilisateur peut accéder aux contrats
 * Autorisé : SUPER_ADMIN, ADMIN, AGENT
 * Bloqué : COMPTA
 */
export function canAccessContrats(permissions: UserPermissions | null): PermissionCheck {
  if (!permissions) {
    return { allowed: false, reason: "Non authentifié" };
  }

  if (permissions.isStaff) {
    return { allowed: true };
  }

  if (permissions.role === "COMPTA") {
    return { allowed: false, reason: "Le rôle COMPTA n'a pas accès aux contrats" };
  }

  return { allowed: true };
}

/**
 * Vérifie si l'utilisateur peut MODIFIER les contrats
 * Autorisé : SUPER_ADMIN, ADMIN, AGENT
 * Bloqué : COMPTA
 */
export function canModifyContrats(permissions: UserPermissions | null): PermissionCheck {
  // Même logique que canAccessContrats
  return canAccessContrats(permissions);
}

/**
 * Vérifie si l'utilisateur peut accéder aux paies
 * Autorisé : SUPER_ADMIN, ADMIN, AGENT
 * Bloqué : COMPTA
 */
export function canAccessPaies(permissions: UserPermissions | null): PermissionCheck {
  if (!permissions) {
    return { allowed: false, reason: "Non authentifié" };
  }

  if (permissions.isStaff) {
    return { allowed: true };
  }

  if (permissions.role === "COMPTA") {
    return { allowed: false, reason: "Le rôle COMPTA n'a pas accès aux paies" };
  }

  return { allowed: true };
}

/**
 * Vérifie si l'utilisateur peut accéder aux salariés
 * Autorisé : SUPER_ADMIN, ADMIN, AGENT
 * Bloqué : COMPTA
 */
export function canAccessSalaries(permissions: UserPermissions | null): PermissionCheck {
  if (!permissions) {
    return { allowed: false, reason: "Non authentifié" };
  }

  if (permissions.isStaff) {
    return { allowed: true };
  }

  if (permissions.role === "COMPTA") {
    return { allowed: false, reason: "Le rôle COMPTA n'a pas accès aux salariés" };
  }

  return { allowed: true };
}

/**
 * Vérifie si l'utilisateur peut gérer les utilisateurs (accès)
 * Autorisé : SUPER_ADMIN, ADMIN
 * Bloqué : AGENT, COMPTA
 */
export function canManageUsers(permissions: UserPermissions | null): PermissionCheck {
  if (!permissions) {
    return { allowed: false, reason: "Non authentifié" };
  }

  if (permissions.isStaff) {
    return { allowed: true };
  }

  if (!["SUPER_ADMIN", "ADMIN"].includes(permissions.role)) {
    return { allowed: false, reason: "Seuls les administrateurs peuvent gérer les utilisateurs" };
  }

  return { allowed: true };
}

/**
 * Vérifie si l'utilisateur peut modifier un autre utilisateur
 * @param permissions Permissions de l'utilisateur actuel
 * @param targetRole Rôle de l'utilisateur cible
 */
export function canModifyUser(
  permissions: UserPermissions | null,
  targetRole: UserRole
): PermissionCheck {
  if (!permissions) {
    return { allowed: false, reason: "Non authentifié" };
  }

  if (permissions.isStaff) {
    return { allowed: true };
  }

  // ADMIN ne peut pas modifier SUPER_ADMIN
  if (permissions.role === "ADMIN" && targetRole === "SUPER_ADMIN") {
    return { allowed: false, reason: "Seul le staff peut modifier un SUPER_ADMIN" };
  }

  // AGENT et COMPTA ne peuvent pas gérer d'utilisateurs
  if (!["SUPER_ADMIN", "ADMIN"].includes(permissions.role)) {
    return { allowed: false, reason: "Seuls les administrateurs peuvent modifier les utilisateurs" };
  }

  return { allowed: true };
}

/**
 * Vérifie si l'utilisateur peut créer un utilisateur avec un rôle donné
 * @param permissions Permissions de l'utilisateur actuel
 * @param newRole Rôle à assigner au nouvel utilisateur
 */
export function canCreateUserWithRole(
  permissions: UserPermissions | null,
  newRole: UserRole
): PermissionCheck {
  if (!permissions) {
    return { allowed: false, reason: "Non authentifié" };
  }

  if (permissions.isStaff) {
    return { allowed: true };
  }

  // Seul le staff peut créer un SUPER_ADMIN
  if (newRole === "SUPER_ADMIN") {
    return { allowed: false, reason: "Seul le staff Odentas peut créer un SUPER_ADMIN" };
  }

  // ADMIN peut créer ADMIN, AGENT, COMPTA
  if (permissions.role === "ADMIN") {
    return { allowed: true };
  }

  // SUPER_ADMIN peut tout créer (sauf SUPER_ADMIN, déjà vérifié)
  if (permissions.role === "SUPER_ADMIN") {
    return { allowed: true };
  }

  return { allowed: false, reason: "Seuls les administrateurs peuvent créer des utilisateurs" };
}

/**
 * Vérifie si l'utilisateur peut modifier les informations de structure (SIRET, coordonnées, SEPA)
 * Autorisé : SUPER_ADMIN uniquement (+ STAFF)
 * Bloqué : ADMIN, AGENT, COMPTA
 */
export function canModifyStructureInfo(permissions: UserPermissions | null): PermissionCheck {
  if (!permissions) {
    return { allowed: false, reason: "Non authentifié" };
  }

  if (permissions.isStaff) {
    return { allowed: true };
  }

  if (permissions.role !== "SUPER_ADMIN") {
    return {
      allowed: false,
      reason: "Seul le SUPER_ADMIN peut modifier les informations de structure",
    };
  }

  return { allowed: true };
}

/**
 * Vérifie si l'utilisateur peut uploader des documents
 * Autorisé : SUPER_ADMIN, ADMIN, AGENT
 * Bloqué : COMPTA
 */
export function canUploadDocuments(permissions: UserPermissions | null): PermissionCheck {
  if (!permissions) {
    return { allowed: false, reason: "Non authentifié" };
  }

  if (permissions.isStaff) {
    return { allowed: true };
  }

  if (permissions.role === "COMPTA") {
    return { allowed: false, reason: "Le rôle COMPTA ne peut pas uploader de documents" };
  }

  return { allowed: true };
}

/**
 * Vérifie si l'utilisateur peut accéder à un type de document
 * @param permissions Permissions de l'utilisateur
 * @param documentType Type du document (ex: "facture", "contrat", etc.)
 */
export function canAccessDocumentType(
  permissions: UserPermissions | null,
  documentType: string
): PermissionCheck {
  if (!permissions) {
    return { allowed: false, reason: "Non authentifié" };
  }

  if (permissions.isStaff) {
    return { allowed: true };
  }

  // COMPTA ne peut accéder qu'aux documents comptables
  if (permissions.role === "COMPTA") {
    if (!COMPTA_ALLOWED_DOCUMENT_TYPES.includes(documentType.toLowerCase())) {
      return {
        allowed: false,
        reason: "Le rôle COMPTA n'a accès qu'aux documents comptables et financiers",
      };
    }
  }

  return { allowed: true };
}

// ============================================================================
// Helpers pour les réponses HTTP
// ============================================================================

/**
 * Retourne une réponse 401 Unauthorized
 */
export function unauthorizedResponse() {
  return new Response(
    JSON.stringify({ error: "Non authentifié", message: "Authentification requise" }),
    { status: 401, headers: { "Content-Type": "application/json" } }
  );
}

/**
 * Retourne une réponse 403 Forbidden avec un message personnalisé
 */
export function forbiddenResponse(reason?: string) {
  return new Response(
    JSON.stringify({
      error: "Accès refusé",
      message: reason || "Vous n'avez pas les permissions nécessaires pour cette action",
    }),
    { status: 403, headers: { "Content-Type": "application/json" } }
  );
}

/**
 * Vérifie les permissions et retourne une réponse d'erreur si nécessaire
 * @returns null si autorisé, Response d'erreur sinon
 */
export function checkPermissionOrRespond(check: PermissionCheck): Response | null {
  if (!check.allowed) {
    return forbiddenResponse(check.reason);
  }
  return null;
}
