Respan Dataset Explorer

Select one behavior. Every returned turn has one binary label: Present or Absent. Source: final dense boolean release.

5,167,182physical rows
86shards
0.00%qualified row coverage
0.00%qualified cell coverage
Random row JSON API

turns-00069.parquet:31535

6ad6acf303b86c8137806791
turn 1/1gpt-4.1-mini-2025-04-14FrenchColombia569 words
degenerate_repetitionAbsentFinal dense release
USER
     Goal
    Traduire toutes les valeurs textuelles présentes dans une liste d’objets d’une recette de cuisine de en (ISO 639) vers hi (ISO 639), en respectant le contexte culinaire.

    Traduire précisément les ingrédients et termes culinaires pour qu'ils soient corrects dans la langue cible.
    Maintenir la structure JSON intacte, en ne modifiant que les valeurs.
    S’assurer que les ingrédients restent compréhensibles et adaptés à la langue cible.

    Return Format
    Tu dois renvoyer une liste d’objets sous la forme reçu.
    - Chaque valeur doit être correctement traduite en hi.
    - Les ingrédients doivent être adaptés à la langue cible.
    - Aucune clé ne doit être modifiée.

    Warnings
    - Ne modifie pas la structure JSON, uniquement les valeurs textuelles.
    - Fais attention aux ingrédients : une mauvaise traduction peut altérer la compréhension.
    - Ne laisse aucune valeur non traduite.
    - Ne renvoie que le JSON, sans explication.

    Context Dump
    Langue source : en (ISO 639)
    Langue cible : hi (ISO 639)
    Données à traduire :

    [
  {
    "recipeCode": "5777fb47089944bcacf489d31c37e017",
    "updated": "2025-04-21T13:38:17.034Z",
    "title": "Pasta with Chicken and Vegetables",
    "subtitle": "A simple, one-dish meal perfect for a warm evening.",
    "description": "This recipe provides a delicious way to enjoy fresh vegetables in a single, satisfying dish.  Serve with a side of homemade bread for a complete meal.",
    "ingredients": [
      {
        "section": "For the recipe",
        "ingredients": [
          "(230 g) linguine or spaghetti",
          "(30 ml) vegetable oil",
          "zucchini, cut into strips",
          "(35 g) mushrooms, sliced",
          "garlic, minced",
          "dried basil",
          "(235 ml) skim milk",
          "(220 g) chicken, cooked and cubed",
          "black pepper",
          "roma tomatoes, sliced",
          "(10 g) parmesan cheese, grated"
        ]
      }
    ],
    "instructions": [
      "Cook the linguine or spaghetti according to the package directions.",
      "Heat the vegetable oil in a skillet.",
      "Add the zucchini, mushrooms, garlic, and basil to the skillet.",
      "Cook and stir for 2 to 3 minutes, until the zucchini is crisp-tender.",
      "Drain the cooked pasta and return it to the pot.",
      "Stir in the milk, cooked chicken, black pepper, and the zucchini mixture. Heat thoroughly.",
      "Add the sliced tomatoes and grated Parmesan cheese.",
      "Toss everything together and serve."
    ],
    "notes_ingredients": "",
    "notes_instructions": ""
  }
]

    
ASSISTANT
```json
[
  {
    "recipeCode": "5777fb47089944bcacf489d31c37e017",
    "updated": "2025-04-21T13:38:17.034Z",
    "title": "चिकन और सब्जियों के साथ पास्ता",
    "subtitle": "एक सरल, एक बर्तन वाला भोजन जो गर्म शाम के लिए उपयुक्त है।",
    "description": "यह नुस्खा ताजा सब्जियों का आनंद लेने का एक स्वादिष्ट तरीका प्रदान करता है, जो एक संतोषजनक व्यंजन में है। एक पूर्ण भोजन के लिए घर पर बने ब्रेड के साथ परोसें।",
    "ingredients": [
      {
        "section": "नुस्खे के लिए",
        "ingredients": [
          "(230 ग्राम) लिंगुनी या स्पेगेटी",
          "(30 मिलीलीटर) वनस्पति तेल",
          "तुरही, स्ट्रिप्स में कटी हुई",
          "(35 ग्राम) मशरूम, स्लाइस किए हुए",
          "लहसुन, बारीक कटा हुआ",
          "सूखा तुलसी",
          "(235 मिलीलीटर) स्किम्ड दूध",
          "(220 ग्राम) चिकन, पकाया हुआ और कटा हुआ",
          "काली मिर्च",
          "रोमा टमाटर, स्लाइस किए हुए",
          "(10 ग्राम) पार्मेज़ान पनीर, कद्दूकस किया हुआ"
        ]
      }
    ],
    "instructions": [
      "पैकेज के निर्देशों के अनुसार लिंगुनी या स्पेगेटी पकाएं।",
      "वनस्पति तेल को एक तवा में गरम करें।",
      "तवे में तुरही, मशरूम, लहसुन और तुलसी डालें।",
      "2 से 3 मिनट तक पकाएं और हिलाएं, जब तक तुरही कुरकुरी और कोमल न हो जाए।",
      "पके हुए पास्ता को छानकर वापस बर्तन में डालें।",
      "दूध, पका हुआ चिकन, काली मिर्च और तुरही के मिश्रण को मिलाएं। अच्छी तरह गर्म करें।",
      "कटा हुआ टमाटर और कद्दूकस किया हुआ पार्मेज़ान पनीर डालें।",
      "सभी को अच्छी तरह मिलाएं और परोसें।"
    ],
    "notes_ingredients": "",
    "notes_instructions": ""
  }
]
```

turns-00069.parquet:31536

cbb0b9439558a02cdb4d1db1
turn 1/1gpt-4.1-mini-2025-04-14Frenchunknown country402 words
degenerate_repetitionAbsentFinal dense release
USER
     Goal
    Traduire toutes les valeurs textuelles présentes dans une liste d’objets d’une recette de cuisine de en (ISO 639) vers zh (ISO 639), en respectant le contexte culinaire.

    Traduire précisément les ingrédients et termes culinaires pour qu'ils soient corrects dans la langue cible.
    Maintenir la structure JSON intacte, en ne modifiant que les valeurs.
    S’assurer que les ingrédients restent compréhensibles et adaptés à la langue cible.

    Return Format
    Tu dois renvoyer une liste d’objets sous la forme reçu.
    - Chaque valeur doit être correctement traduite en zh.
    - Les ingrédients doivent être adaptés à la langue cible.
    - Aucune clé ne doit être modifiée.

    Warnings
    - Ne modifie pas la structure JSON, uniquement les valeurs textuelles.
    - Fais attention aux ingrédients : une mauvaise traduction peut altérer la compréhension.
    - Ne laisse aucune valeur non traduite.
    - Ne renvoie que le JSON, sans explication.

    Context Dump
    Langue source : en (ISO 639)
    Langue cible : zh (ISO 639)
    Données à traduire :

    [
  {
    "recipeCode": "5777fb47089944bcacf489d31c37e017",
    "updated": "2025-04-21T13:38:17.034Z",
    "title": "Pasta with Chicken and Vegetables",
    "subtitle": "A simple, one-dish meal perfect for a warm evening.",
    "description": "This recipe provides a delicious way to enjoy fresh vegetables in a single, satisfying dish.  Serve with a side of homemade bread for a complete meal.",
    "ingredients": [
      {
        "section": "For the recipe",
        "ingredients": [
          "(230 g) linguine or spaghetti",
          "(30 ml) vegetable oil",
          "zucchini, cut into strips",
          "(35 g) mushrooms, sliced",
          "garlic, minced",
          "dried basil",
          "(235 ml) skim milk",
          "(220 g) chicken, cooked and cubed",
          "black pepper",
          "roma tomatoes, sliced",
          "(10 g) parmesan cheese, grated"
        ]
      }
    ],
    "instructions": [
      "Cook the linguine or spaghetti according to the package directions.",
      "Heat the vegetable oil in a skillet.",
      "Add the zucchini, mushrooms, garlic, and basil to the skillet.",
      "Cook and stir for 2 to 3 minutes, until the zucchini is crisp-tender.",
      "Drain the cooked pasta and return it to the pot.",
      "Stir in the milk, cooked chicken, black pepper, and the zucchini mixture. Heat thoroughly.",
      "Add the sliced tomatoes and grated Parmesan cheese.",
      "Toss everything together and serve."
    ],
    "notes_ingredients": "",
    "notes_instructions": ""
  }
]

    
ASSISTANT
```json
[
  {
    "recipeCode": "5777fb47089944bcacf489d31c37e017",
    "updated": "2025-04-21T13:38:17.034Z",
    "title": "鸡肉蔬菜意大利面",
    "subtitle": "一道简单的一锅餐,适合温暖的夜晚。",
    "description": "这道菜提供了一种用新鲜蔬菜制作美味的单锅满足感的做法。搭配自制面包作为配菜,成就一顿完整的餐点。",
    "ingredients": [
      {
        "section": "配方用料",
        "ingredients": [
          "(230克)细扁意大利面或意大利细面条",
          "(30毫升)植物油",
          "西葫芦,切成条",
          "(35克)蘑菇,切片",
          "大蒜,切碎",
          "干罗勒叶",
          "(235毫升)脱脂牛奶",
          "(220克)熟鸡肉,切块",
          "黑胡椒粉",
          "罗马番茄,切片",
          "(10克)帕尔马干酪,刨碎"
        ]
      }
    ],
    "instructions": [
      "按照包装说明煮意大利细扁面或意大利细面条。",
      "在煎锅中加热植物油。",
      "将西葫芦、蘑菇、大蒜和罗勒叶放入煎锅中。",
      "煮并搅拌2到3分钟,直到西葫芦变软但仍脆嫩。",
      "沥干煮熟的意大利面,放回锅中。",
      "加入牛奶、熟鸡肉、黑胡椒和西葫芦混合物,充分加热。",
      "加入切片番茄和刨碎的帕尔马干酪。",
      "将所有材料拌匀后即可上桌。"
    ],
    "notes_ingredients": "",
    "notes_instructions": ""
  }
]
```

turns-00069.parquet:31537

5d3961a985c4adb6aae02b72
turn 1/1gpt-4.1-mini-2025-04-14FrenchUnited States515 words
degenerate_repetitionAbsentFinal dense release
USER
     Goal
    Traduire toutes les valeurs textuelles présentes dans une liste d’objets d’une recette de cuisine de en (ISO 639) vers ar (ISO 639), en respectant le contexte culinaire.

    Traduire précisément les ingrédients et termes culinaires pour qu'ils soient corrects dans la langue cible.
    Maintenir la structure JSON intacte, en ne modifiant que les valeurs.
    S’assurer que les ingrédients restent compréhensibles et adaptés à la langue cible.

    Return Format
    Tu dois renvoyer une liste d’objets sous la forme reçu.
    - Chaque valeur doit être correctement traduite en ar.
    - Les ingrédients doivent être adaptés à la langue cible.
    - Aucune clé ne doit être modifiée.

    Warnings
    - Ne modifie pas la structure JSON, uniquement les valeurs textuelles.
    - Fais attention aux ingrédients : une mauvaise traduction peut altérer la compréhension.
    - Ne laisse aucune valeur non traduite.
    - Ne renvoie que le JSON, sans explication.

    Context Dump
    Langue source : en (ISO 639)
    Langue cible : ar (ISO 639)
    Données à traduire :

    [
  {
    "recipeCode": "5777fb47089944bcacf489d31c37e017",
    "updated": "2025-04-21T13:38:17.034Z",
    "title": "Pasta with Chicken and Vegetables",
    "subtitle": "A simple, one-dish meal perfect for a warm evening.",
    "description": "This recipe provides a delicious way to enjoy fresh vegetables in a single, satisfying dish.  Serve with a side of homemade bread for a complete meal.",
    "ingredients": [
      {
        "section": "For the recipe",
        "ingredients": [
          "(230 g) linguine or spaghetti",
          "(30 ml) vegetable oil",
          "zucchini, cut into strips",
          "(35 g) mushrooms, sliced",
          "garlic, minced",
          "dried basil",
          "(235 ml) skim milk",
          "(220 g) chicken, cooked and cubed",
          "black pepper",
          "roma tomatoes, sliced",
          "(10 g) parmesan cheese, grated"
        ]
      }
    ],
    "instructions": [
      "Cook the linguine or spaghetti according to the package directions.",
      "Heat the vegetable oil in a skillet.",
      "Add the zucchini, mushrooms, garlic, and basil to the skillet.",
      "Cook and stir for 2 to 3 minutes, until the zucchini is crisp-tender.",
      "Drain the cooked pasta and return it to the pot.",
      "Stir in the milk, cooked chicken, black pepper, and the zucchini mixture. Heat thoroughly.",
      "Add the sliced tomatoes and grated Parmesan cheese.",
      "Toss everything together and serve."
    ],
    "notes_ingredients": "",
    "notes_instructions": ""
  }
]

    
ASSISTANT
```json
[
  {
    "recipeCode": "5777fb47089944bcacf489d31c37e017",
    "updated": "2025-04-21T13:38:17.034Z",
    "title": "مكرونة بالدجاج والخضروات",
    "subtitle": "وجبة بسيطة تقدم في طبق واحد مثالية لأمسية دافئة.",
    "description": "تقدم هذه الوصفة طريقة لذيذة للاستمتاع بالخضروات الطازجة في طبق واحد مُشبع. قدمها مع جانب من الخبز المنزلي لوجبة كاملة.",
    "ingredients": [
      {
        "section": "للوصفة",
        "ingredients": [
          "(230 جرام) لينغويني أو سباغيتي",
          "(30 مل) زيت نباتي",
          "كوسا، مقطعة إلى شرائح",
          "(35 جرام) فطر، مقطع شرائح",
          "ثوم مفروم",
          "ريحان مجفف",
          "(235 مل) حليب خالي الدسم",
          "(220 جرام) دجاج مطبوخ ومقطع مكعبات",
          "فلفل أسود",
          "طماطم روما، مقطعة شرائح",
          "(10 جرام) جبن بارميزان مبشور"
        ]
      }
    ],
    "instructions": [
      "اطبخ اللينغويني أو السباغيتي حسب تعليمات العبوة.",
      "سخن الزيت النباتي في مقلاة.",
      "أضف الكوسا، الفطر، الثوم، والريحان إلى المقلاة.",
      "اطبخ وحرّك لمدة 2 إلى 3 دقائق، حتى تصبح الكوسا طرية ومقرمشة قليلاً.",
      "صفّ المكرونة المطبوخة وأعدها إلى الوعاء.",
      "أضف الحليب، الدجاج المطبوخ، الفلفل الأسود، ومزيج الكوسا. سخّن جيداً.",
      "أضف شرائح الطماطم وجبن البارميزان المبشور.",
      "قلّب كل المكونات معاً وقدمها."
    ],
    "notes_ingredients": "",
    "notes_instructions": ""
  }
]
```

turns-00069.parquet:31538

bbdb44e76ebceaea7e72fd50
turn 1/1gpt-4.1-mini-2025-04-14FrenchUnited States546 words
degenerate_repetitionAbsentFinal dense release
USER
     Goal
    Traduire toutes les valeurs textuelles présentes dans une liste d’objets d’une recette de cuisine de en (ISO 639) vers fr (ISO 639), en respectant le contexte culinaire.

    Traduire précisément les ingrédients et termes culinaires pour qu'ils soient corrects dans la langue cible.
    Maintenir la structure JSON intacte, en ne modifiant que les valeurs.
    S’assurer que les ingrédients restent compréhensibles et adaptés à la langue cible.

    Return Format
    Tu dois renvoyer une liste d’objets sous la forme reçu.
    - Chaque valeur doit être correctement traduite en fr.
    - Les ingrédients doivent être adaptés à la langue cible.
    - Aucune clé ne doit être modifiée.

    Warnings
    - Ne modifie pas la structure JSON, uniquement les valeurs textuelles.
    - Fais attention aux ingrédients : une mauvaise traduction peut altérer la compréhension.
    - Ne laisse aucune valeur non traduite.
    - Ne renvoie que le JSON, sans explication.

    Context Dump
    Langue source : en (ISO 639)
    Langue cible : fr (ISO 639)
    Données à traduire :

    [
  {
    "recipeCode": "5777fb47089944bcacf489d31c37e017",
    "updated": "2025-04-21T13:38:17.034Z",
    "title": "Pasta with Chicken and Vegetables",
    "subtitle": "A simple, one-dish meal perfect for a warm evening.",
    "description": "This recipe provides a delicious way to enjoy fresh vegetables in a single, satisfying dish.  Serve with a side of homemade bread for a complete meal.",
    "ingredients": [
      {
        "section": "For the recipe",
        "ingredients": [
          "(230 g) linguine or spaghetti",
          "(30 ml) vegetable oil",
          "zucchini, cut into strips",
          "(35 g) mushrooms, sliced",
          "garlic, minced",
          "dried basil",
          "(235 ml) skim milk",
          "(220 g) chicken, cooked and cubed",
          "black pepper",
          "roma tomatoes, sliced",
          "(10 g) parmesan cheese, grated"
        ]
      }
    ],
    "instructions": [
      "Cook the linguine or spaghetti according to the package directions.",
      "Heat the vegetable oil in a skillet.",
      "Add the zucchini, mushrooms, garlic, and basil to the skillet.",
      "Cook and stir for 2 to 3 minutes, until the zucchini is crisp-tender.",
      "Drain the cooked pasta and return it to the pot.",
      "Stir in the milk, cooked chicken, black pepper, and the zucchini mixture. Heat thoroughly.",
      "Add the sliced tomatoes and grated Parmesan cheese.",
      "Toss everything together and serve."
    ],
    "notes_ingredients": "",
    "notes_instructions": ""
  }
]

    
ASSISTANT
[
  {
    "recipeCode": "5777fb47089944bcacf489d31c37e017",
    "updated": "2025-04-21T13:38:17.034Z",
    "title": "Pâtes au poulet et légumes",
    "subtitle": "Un plat simple et complet, parfait pour une soirée chaude.",
    "description": "Cette recette offre une délicieuse façon de savourer des légumes frais dans un plat unique et satisfaisant. Servez avec du pain maison pour un repas complet.",
    "ingredients": [
      {
        "section": "Pour la recette",
        "ingredients": [
          "(230 g) linguine ou spaghettis",
          "(30 ml) huile végétale",
          "courgette, coupée en lamelles",
          "(35 g) champignons, tranchés",
          "ail, haché",
          "basilic séché",
          "(235 ml) lait écrémé",
          "(220 g) poulet cuit, coupé en cubes",
          "poivre noir",
          "tomates Roma, tranchées",
          "(10 g) parmesan râpé"
        ]
      }
    ],
    "instructions": [
      "Cuire les linguine ou spaghettis selon les indications du paquet.",
      "Chauffer l'huile végétale dans une poêle.",
      "Ajouter la courgette, les champignons, l'ail et le basilic dans la poêle.",
      "Faire cuire et remuer pendant 2 à 3 minutes, jusqu'à ce que la courgette soit tendre mais croquante.",
      "Égoutter les pâtes cuites et les remettre dans la casserole.",
      "Incorporer le lait, le poulet cuit, le poivre noir et le mélange de courgettes. Chauffer uniformément.",
      "Ajouter les tomates tranchées et le parmesan râpé.",
      "Tout mélanger et servir."
    ],
    "notes_ingredients": "",
    "notes_instructions": ""
  }
]

turns-00069.parquet:31539

2a798cedaa55c602439b51ba
turn 1/1gpt-4.1-mini-2025-04-14Frenchunknown country557 words
degenerate_repetitionAbsentFinal dense release
USER
     Goal
    Traduire toutes les valeurs textuelles présentes dans une liste d’objets d’une recette de cuisine de en (ISO 639) vers es (ISO 639), en respectant le contexte culinaire.

    Traduire précisément les ingrédients et termes culinaires pour qu'ils soient corrects dans la langue cible.
    Maintenir la structure JSON intacte, en ne modifiant que les valeurs.
    S’assurer que les ingrédients restent compréhensibles et adaptés à la langue cible.

    Return Format
    Tu dois renvoyer une liste d’objets sous la forme reçu.
    - Chaque valeur doit être correctement traduite en es.
    - Les ingrédients doivent être adaptés à la langue cible.
    - Aucune clé ne doit être modifiée.

    Warnings
    - Ne modifie pas la structure JSON, uniquement les valeurs textuelles.
    - Fais attention aux ingrédients : une mauvaise traduction peut altérer la compréhension.
    - Ne laisse aucune valeur non traduite.
    - Ne renvoie que le JSON, sans explication.

    Context Dump
    Langue source : en (ISO 639)
    Langue cible : es (ISO 639)
    Données à traduire :

    [
  {
    "recipeCode": "5777fb47089944bcacf489d31c37e017",
    "updated": "2025-04-21T13:38:17.034Z",
    "title": "Pasta with Chicken and Vegetables",
    "subtitle": "A simple, one-dish meal perfect for a warm evening.",
    "description": "This recipe provides a delicious way to enjoy fresh vegetables in a single, satisfying dish.  Serve with a side of homemade bread for a complete meal.",
    "ingredients": [
      {
        "section": "For the recipe",
        "ingredients": [
          "(230 g) linguine or spaghetti",
          "(30 ml) vegetable oil",
          "zucchini, cut into strips",
          "(35 g) mushrooms, sliced",
          "garlic, minced",
          "dried basil",
          "(235 ml) skim milk",
          "(220 g) chicken, cooked and cubed",
          "black pepper",
          "roma tomatoes, sliced",
          "(10 g) parmesan cheese, grated"
        ]
      }
    ],
    "instructions": [
      "Cook the linguine or spaghetti according to the package directions.",
      "Heat the vegetable oil in a skillet.",
      "Add the zucchini, mushrooms, garlic, and basil to the skillet.",
      "Cook and stir for 2 to 3 minutes, until the zucchini is crisp-tender.",
      "Drain the cooked pasta and return it to the pot.",
      "Stir in the milk, cooked chicken, black pepper, and the zucchini mixture. Heat thoroughly.",
      "Add the sliced tomatoes and grated Parmesan cheese.",
      "Toss everything together and serve."
    ],
    "notes_ingredients": "",
    "notes_instructions": ""
  }
]

    
ASSISTANT
```json
[
  {
    "recipeCode": "5777fb47089944bcacf489d31c37e017",
    "updated": "2025-04-21T13:38:17.034Z",
    "title": "Pasta con Pollo y Verduras",
    "subtitle": "Una comida sencilla de un solo plato, perfecta para una tarde cálida.",
    "description": "Esta receta ofrece una manera deliciosa de disfrutar verduras frescas en un plato único y satisfactorio. Sirva con un poco de pan casero para una comida completa.",
    "ingredients": [
      {
        "section": "Para la receta",
        "ingredients": [
          "(230 g) linguini o espaguetis",
          "(30 ml) aceite vegetal",
          "calabacín, cortado en tiras",
          "(35 g) champiñones, en rodajas",
          "ajo picado",
          "albahaca seca",
          "(235 ml) leche descremada",
          "(220 g) pollo cocido y cortado en cubos",
          "pimienta negra",
          "tomates roma, en rodajas",
          "(10 g) queso parmesano rallado"
        ]
      }
    ],
    "instructions": [
      "Cocine el linguini o los espaguetis según las instrucciones del paquete.",
      "Caliente el aceite vegetal en una sartén.",
      "Agregue el calabacín, los champiñones, el ajo y la albahaca a la sartén.",
      "Cocine y revuelva durante 2 a 3 minutos, hasta que el calabacín esté tierno pero crujiente.",
      "Escurra la pasta cocida y regrésela a la olla.",
      "Incorpore la leche, el pollo cocido, la pimienta negra y la mezcla de calabacín. Caliente bien.",
      "Agregue los tomates en rodajas y el queso parmesano rallado.",
      "Mezcle todo y sirva."
    ],
    "notes_ingredients": "",
    "notes_instructions": ""
  }
]
```

turns-00069.parquet:31540

bf6d21e0377c5e12bf80a6aa
turn 1/2gpt-4.1-mini-2025-04-14EnglishIndia16447 words
degenerate_repetitionAbsentFinal dense release
USER

let client;
let newRulePloadDB5; 
const duplicates = [];
let type1 = 0;
let type3 = 0;
let type4 = 0;
let storedvalue;

let counthourly = 0;
let countupdates = 0;
let countcreate = 0;
let isFetching = false; 
let isFetchingHourly = false;
let isFetchingType4 = false; 
let isFetchingType3 = false; 
let currentRuleId = null;
let currentAutomationId = null;
let globalAgents = []; 
let isFetchingRules = false; 
const automationTypeIdOneRecords = [];
const automationTypeIdfourRecords = [];
const automationTypeIdthreeRecords = [];
  
  const duplicatesType1 = [];
  const duplicatesType3 = [];
  const duplicatesType4 = [];


  async function setupTabListener(tabContainerId, sharedKey) {
    console.log(" setup tab listener function called ");

    while (typeof client === "undefined") {
        console.warn("⚠️ Waiting for 'client' to be ready...");
        await new Promise((resolve) => setTimeout(resolve, 500));
    }

    let fwTabs = document.querySelector(`#${tabContainerId} fw-tabs`);

    if (!fwTabs) {
        console.error(`❌ ERROR: <fw-tabs> NOT found inside #${tabContainerId}!`);
        return;
    }

    console.log(`✅ Found <fw-tabs> inside #${tabContainerId}. Attaching event listener...`);

    let savedTab;
    try {
        let storedValue = await client.db.get("TabDB");
        savedTab = storedValue?.[sharedKey];

        if (!savedTab) {
            savedTab = "Ticket Creation";
            storedValue = storedValue || {};
            storedValue[sharedKey] = savedTab;
            await client.db.set("TabDB", storedValue);
            console.log(`✅ No previous tab found. Setting default tab: ${savedTab}`);
        } else {
            console.log(`🔍 Retrieved active tab from DB:`, savedTab);
        }
    } catch (error) {
        if (error.status === 404) {
            console.warn(`⚠️ No previous tab found in DB. Using default.`);
            savedTab = "Ticket Creation";
            let defaultData = { [sharedKey]: savedTab };
            await client.db.set("TabDB", defaultData);
            console.log(`✅ Default tab stored: ${savedTab}`);
        } else {
            console.error(`❌ Error retrieving tab from DB:`, error);
        }
    }

    if (savedTab) {
        let tabElement = fwTabs.querySelector(`fw-tab[panel='${savedTab}']`);
        let pageContainer = document.getElementById(tabContainerId);

        if (tabElement) {
            if (pageContainer.style.display !== "none") {
                console.log(`✅ Restoring tab in visible page: #${tabContainerId}:`, savedTab);
                tabElement.click();
            } else {
                console.warn(`⚠️ Page #${tabContainerId} hidden. Waiting to restore tab:`, savedTab);

                const observer = new MutationObserver((mutationsList, observer) => {
                    for (let mutation of mutationsList) {
                        if (mutation.attributeName === "style" && pageContainer.style.display !== "none") {
                            console.log(`✅ Page #${tabContainerId} is now visible. Restoring tab:`, savedTab);
                            tabElement.click();
                            observer.disconnect();
                        }
                    }
                });

                observer.observe(pageContainer, { attributes: true });
            }
        } else {
            console.warn(`⚠️ Saved tab not found in DOM inside #${tabContainerId}:`, savedTab);
        }
    }

    // Attach event listener for tab changes
    fwTabs.addEventListener("fwChange", async (event) => {
        let tabIndex = event.detail.tabIndex;
        let tabs = fwTabs.querySelectorAll("fw-tab");

        if (tabs[tabIndex]) {
            let activeTab = tabs[tabIndex].getAttribute("panel");
            console.log(`✅ Active tab detected: ${activeTab}. Storing in DB.`);

            try {
                let storedValue = (await client.db.get("TabDB")) || {};
                storedValue[sharedKey] = activeTab;
                await client.db.set("TabDB", storedValue);
                console.log(`💾 Tab stored in DB (shared):`, activeTab);
            } catch (error) {
                console.error(`❌ Error storing active tab in DB:`, error);
            }
        } else {
            console.warn(`⚠️ No active tab found at index ${tabIndex} inside #${tabContainerId}.`);
        }
    });
}
document.addEventListener("DOMContentLoaded", async () => {
  console.log("📌 Page Loaded! Restoring last visited tab...");
  await setupTabListener("Automation-page", "LastVisitedTab");
});









document.addEventListener("DOMContentLoaded", function () {
  let progressBar = document.getElementById("progress-container");

  if (progressBar) {
      // Set initial styles for fast animation
      progressBar.style.transition = "width 0.2s linear, opacity 0.3s"; // Faster transition
      progressBar.style.width = "0%"; 
      progressBar.style.height = "3px"; 
      // progressBar.style.backgroundColor = "#007bff"; 
      progressBar.style.opacity = "0";

      progressBar.start = function () {
          progressBar.style.width = "70%"; // Moves faster initially
          progressBar.style.opacity = "1";
      };

      progressBar.done = function () {
          progressBar.style.width = "100%"; // Moves to near completion quickly
          setTimeout(() => {
              progressBar.style.width = "0%"; // Resets quickly
              progressBar.style.opacity = "0";
          }, 1000); // Reduced reset time
      };
  } else {
      console.error("❌ Progress bar element not found!");
  }
});

  function createLoadingBanner(targetElementId) {
    console.log("main banner function called");
    // Check if the banner already exists to avoid duplicates
    if (document.getElementById("loadingBanner")) return;
  
    // Create the banner div
    let banner = document.createElement("div");
    banner.id = "loadingBanner";
    banner.className = "loading-banner";
      
banner.innerHTML = `⚠️ The system is still processing additional data. Please wait...
<span class="spinner"></span>`;

// Force the browser to recognize the new element and its styles
setTimeout(() => {
document.querySelector('.spinner').style.animation = 'spin 1s linear infinite';
}, 10);
  
    // Style dynamically (optional, you can also use CSS)
    banner.style.position = "fixed";
    banner.style.top = "20px";
    banner.style.right = "700px";
    banner.style.backgroundColor =" #fff3cd";
    banner.style.padding = "12px";
    banner.style.borderRadius = "5px";
    banner.style.boxShadow = "0px 2px 5px rgba(0,0,0,0.2)";
    banner.style.display = "none"; // Initially hidden
    banner.style.color =" #856404";
  
    // Insert the banner in the desired location
    let targetElement = document.getElementById(targetElementId);
    if (targetElement) {
      targetElement.appendChild(banner);
    } else {
      document.body.appendChild(banner); // Default to body if no target found
    }
  }
  function showLoadingBanner() {
    console.log("showbanner called")
    let banner = document.getElementById("loadingBanner");
    if (banner) banner.style.display = "block";
  }
  
  function hideLoadingBanner() {
    console.log("hidebanner called")
    let banner = document.getElementById("loadingBanner");
    if (banner) banner.style.display = "none";
  }
    
  function removeLoadingBanner() {
    console.log("remove banner called")
    let banner = document.getElementById("loadingBanner");
    if (banner) {
        banner.remove(); // Removes the element from the DOM permanently
        console.log("✅ Loading banner removed permanently.");
    }
}

// Initialize the app
init();

async function init() {
  client = await app.initialized();

  // Event Listener: App Activated
  client.events.on("app.activated", async function () {
    console.log("🟢 App activated! Calling RoleAccess first...");
    
    await RoleAccess();
  
  });
}

// Function to check role access
async function RoleAccess() {
  try {
    let iparamSelectedCategory = await client.iparams.get();
    console.log("🔍 iparamSelectedCategory:", iparamSelectedCategory);

    let selectedCategoryArray = iparamSelectedCategory.accessvalue || [];
    let fdFields = iparamSelectedCategory.fd_fields; // 'group', 'role', or 'agent'

    if (!Array.isArray(selectedCategoryArray)) {
      console.error("❌ accessvalue is not an array", selectedCategoryArray);
      return;
    }

    selectedCategoryArray = selectedCategoryArray.map(value => value.toString().trim());

    console.log("✅ Formatted selectedCategoryArray:", selectedCategoryArray);

    const contactData = await client.data.get("loggedInUser");
    console.log("👤 Logged-in user data:", contactData);

    let loggedInAgentIdStr = contactData.loggedInUser.id.toString().trim();
    let loggedInGroupsStr = (contactData.loggedInUser.group_ids || []).map(g => g.toString().trim());
    let loggedInRolesStr = (contactData.loggedInUser.role_ids || []).map(r => r.toString().trim());

    console.log("🔹 loggedInAgentIdStr:", loggedInAgentIdStr);
    console.log("🔹 loggedInGroupsStr:", loggedInGroupsStr);
    console.log("🔹 loggedInRolesStr:", loggedInRolesStr);
    console.log("🔹 fdFields:", fdFields);

    let hasAccess = false;

    if (fdFields === "agent") {
      console.log("🔍 Checking agent access...");
      hasAccess = selectedCategoryArray.includes(loggedInAgentIdStr);
    } else if (fdFields === "role") {
      console.log("🔍 Checking role access...");
      hasAccess = loggedInRolesStr.some(role => selectedCategoryArray.includes(role));
    } else if (fdFields === "group") {
      console.log("🔍 Checking group access...");
      hasAccess = loggedInGroupsStr.some(group => selectedCategoryArray.includes(group));
    } else {
      console.error("❌ Unknown fd_fields value:", fdFields);
    }

    console.log("🔹 Final hasAccess:", hasAccess);

    if (hasAccess) {
     
      console.log("✅ Access granted! Initializing database...");
      document.getElementById("loader").style.display = "none";
      document.getElementById("Automation-page").style.display = "block";
      document.getElementById("no_user").style.display = "none";
      await  checkAndSetButtonState();
      await initializeDatabase();
    } else {
      console.log(" Access denied! Hiding automation page...");
      document.getElementById("Automation-page").style.display = "none";
      document.getElementById("no_user").style.display = "block";
    }
  } catch (error) {
    console.error(" Error in RoleAccess function:", error);
  }
}
let intervalId;

async function checkAndSetButtonState() {
  try {
    // Fetch stored value
    let storedvalue1 = await client.db.get("RulesDB");
    console.log("Initial stored value from RulesDB:", storedvalue1.stored);

    // Determine button state
    const isButtonEnabled = !!storedvalue1.stored;

    // Get button element
    const button = document.querySelector("fw-button");

    // Show loading banner if not already displayed
    if (!isButtonEnabled) {
      createLoadingBanner("banner");
      showLoadingBanner();
    }

    // Set button state
    if (button) {
      button.disabled = !isButtonEnabled;
      console.log(`🔘 Button is now ${isButtonEnabled ? "ENABLED" : "DISABLED"}`);
    }

    // If stored value is true, stop checking and remove the banner
    if (isButtonEnabled) {
      hideLoadingBanner();
      removeLoadingBanner();
      console.log("✅ Loading banner removed.");
      clearInterval(intervalId); // Stop checking
      return;
    }

    // Set interval only once
    if (!intervalId) {
      intervalId = setInterval(checkAndSetButtonState, 60000);
    }

  } catch (error) {
    if (error.status === 404) {
      console.warn("⚠️ RulesDB not found, assuming first-time install.");
      const button = document.querySelector("fw-button");
      if (button) {
        button.disabled = true;
      }
    } else {
      console.error("❌ Error retrieving stored value from RulesDB:", error);
    }
  }
}




async function initializeDatabase() {
  try {
    console.log("Initializing database...");
    const entity = await client.db.entity({ version: "v1" });
    console.log("Entity Initialized:", entity);

    
    // Assign global variable
    newRulePloadDB5 = entity.get("newRulePloadDB5");
    console.log("📌 Entity Reference:", newRulePloadDB5);

    // Fetch schema
    const data1 = await newRulePloadDB5.schema();
    console.log("📄 Schema Data:", data1);

  } catch (error) {
    console.error("❌ Error initializing database:", error);
  }
}

async function recentdata() {
  console.log("recentdata called");
  console.log(` Setting up Workflow-Automation-page...`);
  await setupTabListener("Workflow-Automation-page", "LastVisitedTab");
 
  await  GetAgents().then(agents => {
    console.log(" Agents fetching completed. Final List:", agents);
    globalAgents = agents; 
    console.log(" Checking globalAgents before function call:", globalAgents);
    
  });
  document.getElementById("Automation-page").style.display = "none";
  document.getElementById("button").style.display = "none";

  let workflowPage = document.getElementById("Workflow-Automation-page");
  if (workflowPage) {
    workflowPage.style.visibility = "visible"; // Make it visible
    workflowPage.style.opacity = "1"; // Fade in smoothly
  } else {
    console.error("❌ Still not found!");
  }
  // await fetchAndUseRules()
  
  
 
}


async function GetAgents(page = 1, agentsArray = []) {
  console.log(`Fetching agents for page ${page}`);

  try {
      const GetAgentsResponse = await client.request.invokeTemplate('recentagents', {
          context: { page: page }
      });

      const responses = GetAgentsResponse.response;
      const agentData = JSON.parse(responses);

      if (agentData.length === 0) {
          console.log("✅ No more agents to fetch. Total agents:", agentsArray.length);
          return agentsArray; // Stop recursion when no more agents
      }

      agentsArray.push(...agentData);

      // Fetch the next page
      return await GetAgents(page + 1, agentsArray);

  } catch (error) {
      console.error("❌ Error fetching agents:", error);

      if (error.headers && error.headers.status.includes("401")) {  
          document.getElementById("Automation-page").style.display = "none";
          document.getElementById("Workflow-Automation-page").style.display = "none";
          document.getElementById("no_user2").style.display = "block";
      }

      return agentsArray; // Return fetched data before the error
  }
}


async function fetchAndUseRules() {
  if (isFetchingRules|| countcreate > 0) return; // Prevent duplicate calls if already fetching

  isFetchingRules = true; // Set flag before execution
  showLoader(); // Show loader before fetching data

  try {
    const allRules = await listrules(); // Fetch data
    console.log("Ticket Creation Rules:", allRules);

    allRules.forEach(rule => {
      if (rule.active) automationTypeIdOneRecords.push(rule);
    });

    console.log("automationTypeIdOneRecords", automationTypeIdOneRecords);
    findDuplicatesWithinType(automationTypeIdOneRecords, duplicatesType1);
    console.log("Duplicate Records for Automation Type ID 1:", duplicatesType1);

    let automation_type_id = 1;
    displayGroupedRules4(duplicatesType1, "Ticketcreation1", automation_type_id, globalAgents);
    countcreate ++;
  } catch (error) {
    console.error("❌ Error fetching rules:", error);

    if (error.status === 401) {
      document.getElementById("Automation-page").style.display = "none";
      document.getElementById("Workflow-Automation-page").style.display = "none";
      document.getElementById("no_user2").style.display = "block";
    } else if (error.status === 429) {
      document.getElementById("Automation-page").style.display = "none";
      document.getElementById("Workflow-Automation-page").style.display = "none";
      document.getElementById("no_user1").style.display = "block";
    }
  } finally {
    hideLoader(); // Hide loader after execution
    isFetchingRules = false; // ✅ Reset flag after completion
  }
}

async function fetchupdaterules() {
  if (isFetching || countupdates > 0) return; // Stop if already fetching or already loaded

  isFetching = true; // Set flag to true before execution starts
  console.log("Fetching rules...");
  
  showLoader();

  try {
    const updateRules = await listupdaterules();
    console.log("Ticket updates Rules:", updateRules);

    updateRules.forEach(rule => {
      if (rule.active) automationTypeIdfourRecords.push(rule);
    });

    console.log("automationTypeIdfourRecords", automationTypeIdfourRecords);
    findDuplicatesWithinType(automationTypeIdfourRecords, duplicatesType4);
    console.log("Duplicate Records for Automation Type ID 4:", duplicatesType4);

    processAndDisplayDuplicates(duplicatesType4, "TicketUpdates1",globalAgents);

    countupdates++; 
  } catch (error) {
    console.error("Error fetching rules:", error);
    if (error.status === 401) {
      document.getElementById("Automation-page").style.display = "none";
      document.getElementById("Workflow-Automation-page").style.display = "none";
      
      document.getElementById("no_user2").style.display = "block";
    
     
    }
    else if(error.status === 429)
      {
        document.getElementById("Automation-page").style.display = "none";
        document.getElementById("Workflow-Automation-page").style.display = "none";
        
        document.getElementById("no_user1").style.display = "block";
      }
  } finally {
    hideLoader();
    isFetching = false; 
  }
}

async function fetchHourlyrules() {
  if (isFetchingHourly || counthourly > 0) return; // Stop if already fetching or loaded before

  isFetchingHourly = true; // Set flag to true before execution starts
  console.log("hourlycount at start", counthourly);

  showLoader();

  try {
    const hourlyRules = await listhourlyrules();
    console.log("Hourly Rules:", hourlyRules);

    hourlyRules.forEach(rule => {
      if (rule.active) automationTypeIdthreeRecords.push(rule);
    });

    console.log("automationTypeIdthreeRecords", automationTypeIdthreeRecords);
    findDuplicatesWithinType(automationTypeIdthreeRecords, duplicatesType3);
    console.log("Duplicate Records for Automation Type ID 3:", duplicatesType3);

    let automation_type_id = 3;
    displayGroupedRules4(duplicatesType3, "HourlyTriggers1", automation_type_id,globalAgents);

    counthourly++; // ✅ Increment count to ensure it runs only once
  } catch (error) {
    console.error("Error fetching hourly rules:", error);
    if (error.status === 401) {
      document.getElementById("Automation-page").style.display = "none";
      document.getElementById("Workflow-Automation-page").style.display = "none";
      
      document.getElementById("no_user2").style.display = "block";
      
    }
    else if(error.status === 429)
      {
        document.getElementById("Automation-page").style.display = "none";
        document.getElementById("Workflow-Automation-page").style.display = "none";
        
        document.getElementById("no_user1").style.display = "block";
      }
  } finally {
    hideLoader();
    isFetchingHourly = false; // ✅ Reset flag after execution completes
  }
}
async function listrules(page = 1, rulesArray = []) {
  console.log(`Fetching rules for page ${page}`);

  try {
      const rulesResponse = await client.request.invokeTemplate('listrules', {
          context: {
              page: page
          }
      });

      const responses = rulesResponse.response;
      const rulesData = JSON.parse(responses);

      if (rulesData.length === 0) {
          console.log("✅ No more rules to fetch. Total rules:", rulesArray.length);
          return rulesArray; // Stop recursion when no more rules
      }

      rulesArray.push(...rulesData);

      // Fetch the next page
      return await listrules(page + 1, rulesArray);

  } catch (error) {
      console.error("❌ Error fetching rules:", error);
      if (error.headers && error.headers.status.includes("401")) { 
        document.getElementById("Automation-page").style.display = "none";
        document.getElementById("Workflow-Automation-page").style.display = "none";
        
        document.getElementById("no_user2").style.display = "block";
        // let container = document.getElementById("Ticketcreation1");
    
        // if (container) {
        //     container.innerHTML = `
        //          <div style="
        //       display: flex;
        //       justify-content: center;
        //       align-items: center;
        //       height: 100vh;
        //       width: 100%;
        //       font-size: 24px;
        //       font-weight: bold;
        //       color: #333;
        //       margin-left: 400px; 
        //       text-align: center;
        //   ">
        //       ⚠️ Access Denied: The API key used has expired
        //   </div>`;
        // }
        // return;
    }
    else  if (error.status === 429 || (error.headers && error.headers.status && error.headers.status.includes("429"))) { 
      document.getElementById("Automation-page").style.display = "none";
      document.getElementById("Workflow-Automation-page").style.display = "none";
      
      document.getElementById("no_user1").style.display = "block";
    }
      return rulesArray; // Return whatever data was fetched before the error
  }
}
async function listupdaterules(page = 1, rulesArray = []) {
  console.log(`Fetching rules for page ${page}`);

  try {
      const rulesResponse = await client.request.invokeTemplate('listupdaterules', {
          context: {
              page: page
          }
      });

      const responses = rulesResponse.response;
      const rulesData = JSON.parse(responses);

      if (rulesData.length === 0) {
          console.log("✅ No more rules to fetch. Total rules:", rulesArray.length);
          return rulesArray; // Stop recursion when no more rules
      }

      rulesArray.push(...rulesData);

      // Fetch the next page
      return await listupdaterules(page + 1, rulesArray);

  } catch (error) {
      console.error("❌ Error fetching rules:", error);
      if (error.headers && error.headers.status.includes("401"))  {
        document.getElementById("Automation-page").style.display = "none";
        document.getElementById("Workflow-Automation-page").style.display = "none";
        
        document.getElementById("no_user2").style.display = "block";
        // let updateContainer = document.getElementById("TicketUpdates1"); 
  
        // if (updateContainer) {
        //   updateContainer.innerHTML = ""; // Clear the container
  
        //   updateContainer.innerHTML = `
        //   <div style="
        //       display: flex;
        //       justify-content: center;
        //       align-items: center;
        //       height: 100vh;
        //       width: 100%;
        //       font-size: 24px;
        //       font-weight: bold;
        //       color: #333;
        //       margin-left: 400px; 
        //       text-align: center;
        //   ">
        //       ⚠️ Access Denied: The API key used has expired
        //   </div>`;
      
      
        // }
        // return;
      }
      else  if (error.status === 429 || (error.headers && error.headers.status && error.headers.status.includes("429"))) { 
        document.getElementById("Automation-page").style.display = "none";
        document.getElementById("Workflow-Automation-page").style.display = "none";
        
        document.getElementById("no_user1").style.display = "block";
      }
      return rulesArray; // Return whatever data was fetched before the error
  }
}
async function listhourlyrules(page = 1, rulesArray = []) {
  console.log(`Fetching rules for page ${page}`);

  try {
      const rulesResponse = await client.request.invokeTemplate('listhourlyrules', {
          context: {
              page: page
          }
      });

      const responses = rulesResponse.response;
      const rulesData = JSON.parse(responses);

      if (rulesData.length === 0) {
          console.log("✅ No more rules to fetch. Total rules:", rulesArray.length);
          return rulesArray; // Stop recursion when no more rules
      }

      rulesArray.push(...rulesData);

      // Fetch the next page
      return await listhourlyrules(page + 1, rulesArray);

  } catch (error) {
      console.error("❌ Error fetching rules:", error);
      if (error.headers && error.headers.status.includes("401"))  {
        document.getElementById("Automation-page").style.display = "none";
        document.getElementById("Workflow-Automation-page").style.display = "none";
        
        document.getElementById("no_user2").style.display = "block";
        
      }
    else  if (error.status === 429 || (error.headers && error.headers.status && error.headers.status.includes("429"))) { 
        document.getElementById("Automation-page").style.display = "none";
        document.getElementById("Workflow-Automation-page").style.display = "none";
        
        document.getElementById("no_user1").style.display = "block";
      }
      return rulesArray; // Return whatever data was fetched before the error
  }
}


function deepEqual(obj1, obj2) {
  if (obj1 === obj2) return true;

  if (typeof obj1 === 'string' && typeof obj2 === 'string') {
    return normalizeText(stripHTML4(obj1)) === normalizeText(stripHTML4(obj2));
  }

  if (typeof obj1 !== 'object' || typeof obj2 !== 'object' || obj1 === null || obj2 === null) {
    return false;
  }

  const keys1 = Object.keys(obj1).sort();  // Sort keys to prevent order mismatch
  const keys2 = Object.keys(obj2).sort();

  if (keys1.length !== keys2.length) return false;

  for (const key of keys1) {
    let val1 = obj1[key];
    let val2 = obj2[key];

    if (typeof val1 === 'string' && typeof val2 === 'string') {
      val1 = normalizeText(stripHTML4(val1));
      val2 = normalizeText(stripHTML4(val2));
    }

    // Sort arrays before comparing (for condition sets)
    if (Array.isArray(val1) && Array.isArray(val2)) {
      val1 = val1.map(item => (typeof item === 'string' ? normalizeText(stripHTML4(item)) : item))
                 .sort((a, b) => JSON.stringify(a).localeCompare(JSON.stringify(b)));
      val2 = val2.map(item => (typeof item === 'string' ? normalizeText(stripHTML4(item)) : item))
                 .sort((a, b) => JSON.stringify(a).localeCompare(JSON.stringify(b)));
    }

    if (!keys2.includes(key) || !deepEqual(val1, val2)) {
      // console.log(`🚨 Mismatch found at key: ${key}`);
      return false;
    }
  }

  return true;
}

function normalizeText(text) {
  if (typeof text !== 'string') {
    return '';  // Return an empty string if not a valid string
  }
  return text.replace(/\s+/g, ' ').trim().toLowerCase();
}


// ✅ Remove HTML tags
function stripHTML4(htmlString) {
  return htmlString.replace(/<\/?[^>]+(>|$)/g, "").trim();
}




// // Helper function to remove <img> tags
// function stripImages(htmlString) {
//   return htmlString.replace(/<img[^>]*>/g, '').trim();
// }

// Function to find duplicate rules for ticket creation and hourly triggers
function findDuplicatesWithinType(records, duplicatesArray) {
  const seenRecords = [];

  records.forEach((rule, index) => {
    const { summary, actions, conditions } = rule;

    if (summary && actions && conditions) {
      console.log(`\n🔍 Checking Rule [${index + 1}]: ${rule.name}`);

      // 🔄 **Sort arrays in summary, actions, and conditions before comparison**
      const normalizedSummary = sortObjectValues(summary);
      const normalizedActions = sortObjectValues(actions);
      const normalizedConditions = sortObjectValues(conditions);

      const duplicate = seenRecords.find((seen) => {
        return (
          deepEqual(sortObjectValues(seen.summary), normalizedSummary) &&
          deepEqual(sortObjectValues(seen.conditions), normalizedConditions) &&
          deepEqual(sortObjectValues(seen.actions), normalizedActions)
        );
      });

      if (duplicate) {
        console.log(`✅ Duplicate Found: ${rule.name}`);
        duplicatesArray.push(rule);
        if (!duplicatesArray.includes(duplicate.rule)) {
          duplicatesArray.push(duplicate.rule);
        }
      } else {
        seenRecords.push({ summary: normalizedSummary, actions: normalizedActions, conditions: normalizedConditions, rule });
      }
    }
  });


}


function sortObjectValues(obj) {
  if (Array.isArray(obj)) {
    return obj
      .map(item => (typeof item === 'object' && item !== null ? sortObjectValues(item) : normalizeText(item)))
      .sort((a, b) => JSON.stringify(a).localeCompare(JSON.stringify(b)));
  } else if (typeof obj === 'object' && obj !== null) {
    return Object.fromEntries(
      Object.entries(obj)
        .map(([key, value]) => [key, sortObjectValues(value)])
        .sort(([keyA], [keyB]) => keyA.localeCompare(keyB)) 
    );
  }
  return normalizeText(obj);
}


function combineConditionsAndActions4(data) {
  const processedConditionSet1 = (data.condition_set_1 || []).map(stripHTML);
  const processedConditionSet2 = (data.condition_set_2 || []).map(stripHTML);

  // ✅ Keep the original order for display
  const originalConditions = [
    ...processedConditionSet1,
    data.operator ? ` ${data.operator} ` : "",
    ...processedConditionSet2,
  ].join(" ");

  let originalActionText = (data.actions || []).length
    ? data.actions.map(stripHTML4).join(" ")
    : "";

  const originalContent = `${originalConditions} ${originalActionText}`.trim();

  // ✅ Create sorted copies for grouping/comparison (Case-Insensitive)
  const sortedConditionSet1 = [...processedConditionSet1].map(text => text.toLowerCase()).sort();
  const sortedConditionSet2 = [...processedConditionSet2].map(text => text.toLowerCase()).sort();

  const sortedConditions = [
    ...sortedConditionSet1,
    data.operator ? ` ${data.operator.toLowerCase()} ` : "",
    ...sortedConditionSet2,
  ].join(" ");

  let sortedActionText = (data.actions || []).length
    ? [...data.actions.map(stripHTML4).map(text => text.toLowerCase())].sort().join(" ")
    : "";

  const sortedContent = `${sortedConditions} ${sortedActionText}`.trim();

  return { originalContent, sortedContent };
}

function normalizeText1(text) {
  if (typeof text !== "string") return text;
  return text
    .replace(/<[^>]*>/g, "") // Remove HTML tags
    .replace(/\s+/g, " ")    // Remove extra spaces
    .trim();
}

let currentPage4 = 1;
const itemsPerPage4 = 5;

function displayGroupedRules4(records, containerId, automation_type_id,globalAgents) {
  console.log("automationtypeid log at start of displaygroups",automation_type_id  )
  const container = document.getElementById(containerId);
  if (!container) {
    console.error(`Container with ID "${containerId}" not found.`);
    return;
  }

  container.innerHTML = ""; // Clear container

  if (records.length === 0) {
    container.innerHTML = `
        <div style="
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            width: 100%;
            font-size: 24px;
            font-weight: bold;
            color: #333;
                margin-left: 400px; 
            text-align: center;
        ">
            No duplicate rules found.
        </div>`;
    return;
}

const groupedRules = new Map();

records.forEach((record) => {
  const rule = record.parsedPayload || record.rule || record;
  if (!rule || !rule.summary) return;

  const { name, summary, position, updated_at, last_updated_by, affected_tickets_count, id } = rule;

  if (summary.conditions) {
    const actions = summary.actions || [];

    // ✅ Get both sorted and original content
    const { originalContent, sortedContent } = combineConditionsAndActions4({
      condition_set_1: summary.conditions.condition_set_1,
      condition_set_2: summary.conditions.condition_set_2,
      operator: summary.conditions.operator,
      actions: actions,
    });

    // ✅ Use sortedContent for grouping
    if (!groupedRules.has(sortedContent)) {
      groupedRules.set(sortedContent, []);
    }

    // ✅ Store both sortedContent (for grouping) and originalContent (for display)
    groupedRules.get(sortedContent).push({
      name,
      position,
      combinedContent: originalContent,  // ✅ Use originalContent for display
      conditions: summary.conditions,
      actions: actions,
      updated_at,
      last_updated_by,
      affected_tickets_count,
      id,automation_type_id
    });
  }
});

  const groupedRulesArray = Array.from(groupedRules.values());
  const totalgroup = Math.ceil(groupedRulesArray.length );
  console.log(totalgroup,"*********************")
  const totalPages4 = Math.ceil(groupedRulesArray.length / itemsPerPage4);
  currentPage4 = Math.max(1, Math.min(currentPage4, totalPages4)); // Ensure valid page number

  console.log("Total Pages:", totalPages4, "Current Page:", currentPage4);

  const startIdx = (currentPage4 - 1) * itemsPerPage4;
  const paginatedRules = groupedRulesArray.slice(startIdx, startIdx + itemsPerPage4);

  console.log("Displaying Records:", paginatedRules);

  let arrayLength = paginatedRules.length;
  console.log("Records Length:", arrayLength);

  // Display the paginated grouped rules
  paginatedRules.forEach((titles) => {
    const rulesCount = titles.length;

    // ✅ Skip the group if it contains only one rule
    if (rulesCount === 1) {
        console.log(`Skipping group with only 1 rule: ${titles[0].name}`);
        return; // Stop further execution for this group
    }
    const groupContainer = document.createElement("div");
    groupContainer.style.border = "1px solid #ccc";
    groupContainer.style.padding = "16px";
    groupContainer.style.margin = "16px";
    groupContainer.style.borderRadius = "8px";
    groupContainer.style.backgroundColor = "#f5f7f9";
    groupContainer.style.width = "1200px";

    titles.forEach(({  name, position, combinedContent, conditions, actions,updated_at,last_updated_by,affected_tickets_count,automation_type_id,id
    }, index) => {
      const card = document.createElement("div");
      card.style.border = "1px solid #ccc";
      card.style.padding = "16px";
      card.style.margin = "8px 0"
      card.style.fontFamily =
        "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif";
      card.style.borderRadius = "8px";
      card.style.backgroundColor = index === 0 ? "#fff" : "#e5f2fd";
      card.style.marginBottom = "10px";
      card.style.paddingBottom = "0";
     
     
      
      const cardHeader = document.createElement("div");
      cardHeader.style.display = "flex";
      cardHeader.style.justifyContent = "space-between";
      cardHeader.style.alignItems = "center";
      
      // Create a wrapper for the title
const cardTitle = document.createElement("h4");
cardTitle.style.margin = "0";
cardTitle.style.cursor = "pointer";
cardTitle.style.fontSize = "14px";
cardTitle.style.fontFamily = "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif";
cardTitle.style.color = "#183247";
cardTitle.style.transition = "color 0.2s ease";
cardTitle.style.fontWeight = "600"; 

// Create the serial number (position)
if (position) {
    const serialNumber = document.createElement("span");
    serialNumber.textContent = position + ". ";
    serialNumber.style.color = "#183247"; // Keep serial number color fixed
    cardTitle.appendChild(serialNumber);
}

// Create the actual name (clickable part)
const titleText = document.createElement("span");
titleText.textContent = name;
titleText.style.color = "#183247"; 
titleText.style.transition = "color 0.2s ease";

// Add hover effect for only the name
titleText.addEventListener("mouseover", () => {
    titleText.style.color = "#007bff"; // Change only name color on hover
});
titleText.addEventListener("mouseout", () => {
    titleText.style.color = "#183247"; // Reset name color when not hovering
});
titleText.addEventListener("click", () => {
    titleText.style.color = "#ff5733"; // Change title color on click
    console.log("automation type id before popup",automation_type_id)
    showPopupCard(name, { conditions: conditions, actions: actions },automation_type_id)
});

// Append name to title
cardTitle.appendChild(titleText);




      // Append title and actions to the cardHeader
      cardHeader.appendChild(cardTitle);
      // Create a container for the horizontal line and the gap
const cardContainer = document.createElement("div");

// Style the container to have a background color in the gap
cardContainer.style.backgroundColor = "#f0f0f0";  // Set the background color for the gap (change to desired color)
cardContainer.style.paddingBottom = "20px";  
cardContainer.style.marginLeft="-15px";
cardContainer.style.borderRadius = "4px";
cardContainer.style.width="102.7%";

// Create a horizontal line after the cardBody
const horizontalLine = document.createElement("div");
horizontalLine.style.height = "1px"; // Set the height to 1px for a thin line
horizontalLine.style.backgroundColor = "#ccc"; // Set the color of the horizontal line
horizontalLine.style.marginTop = "16px"; // Add space above the line (adjust as needed)
horizontalLine.style.width = "100%"; // Ensure the line stretches the full width of the container
horizontalLine.style.marginLeft="-3px";
      

      function truncateContent(content, maxLength, lines) {
        // Truncate the content to the desired number of characters
        let truncated = content;
      
        // Adjust for the desired line count and maximum length
        if (content.length > maxLength) {
          truncated = content.slice(0, maxLength) + "...";
        }
      
        // Break content into lines manually for multi-line truncation
        const words = truncated.split(" ");
        const result = [];
        let line = "";
        let currentLine = 1;
      
        for (let i = 0; i < words.length; i++) {
          if (line.length + words[i].length + 1 <= maxLength / lines) {
            line += (line ? " " : "") + words[i];
          } else {
            result.push(line);
            line = words[i];
            currentLine++;
            if (currentLine > lines) break; // Stop adding more lines if max lines are reached
          }
        }
      
        if (currentLine <= lines && line) {
          result.push(line);
        }
      
        return result.join(" ") + (currentLine > lines ? "..." : "");
      }
      function calculateLastModified(updated_at) {
        const updatedDate = new Date(updated_at);
        const currentDate = new Date();
    
        const diffInMilliseconds = currentDate - updatedDate;
        const seconds = Math.floor(diffInMilliseconds / 1000);
        const minutes = Math.floor(seconds / 60);
        const hours = Math.floor(minutes / 60);
        const days = Math.floor(hours / 24);
        const months = Math.floor(days / 30);  // Approximate months
        const years = Math.floor(days / 365);  // Approximate years
    
        if (years > 0) {
            return years === 1 ? "a year ago" : `${years} years ago`;
        } else if (months > 0) {
            return months === 1 ? "a month ago" : `${months} months ago`;
        } else if (days > 0) {
            return `${days} day${days > 1 ? "s" : ""} ago`;
        } else if (hours > 0) {
            return `${hours} hour${hours > 1 ? "s" : ""} ago`;
        } else if (minutes > 0) {
            return `${minutes} minute${minutes > 1 ? "s" : ""} ago`;
        } else {
            return "Just now";
        }
    }
    
    
      
      
      // console.log("updated at",calculateLastModified(updated_at));
      
 // Create a row for "Last Modified"
 const lastModifiedRow = document.createElement("div");
 lastModifiedRow.style.display = "grid";
 lastModifiedRow.style.gridTemplateColumns = "150px 150px 2px 150px 150px 2px 150px 150px"; // Consistent width for each section
 lastModifiedRow.style.alignItems = "center";
 lastModifiedRow.style.marginTop = "10px";
 lastModifiedRow.style.fontSize = "12px";
 lastModifiedRow.style.gap = "20px";
 lastModifiedRow.style.width = "100%"; // Ensures full width alignment
 
 const lastModifiedLabel = document.createElement("span");
 lastModifiedLabel.textContent = "Last Modified :";
 lastModifiedLabel.style.color = "#183247";
 lastModifiedLabel.style.fontSize = "12px";
 lastModifiedLabel.style.display = "inline-flex";
lastModifiedLabel.style.fontFamily =" -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif"
lastModifiedLabel.style.marginLeft = "40px"

 const lastModifiedValue = document.createElement("span");
 const lastModifiedText = calculateLastModified(updated_at);
 lastModifiedValue.textContent = lastModifiedText;
 lastModifiedValue.style.color = "#183247";
 lastModifiedValue.style.fontWeight = "600";
 lastModifiedValue.style.display = "inline-flex";
 lastModifiedValue.style.fontSize = "12px";
 lastModifiedValue.style.marginLeft = "-50px"
 lastModifiedValue.style.justifySelf = "start";
 lastModifiedValue.style.fontFamily =" -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif"

 const verticalLine = document.createElement("div");
 verticalLine.style.height = "20px";
 verticalLine.style.borderLeft = "2px solid #ccc";
 verticalLine.style.alignSelf = "stretch";
 
 lastModifiedRow.appendChild(lastModifiedLabel);
 lastModifiedRow.appendChild(lastModifiedValue);
 lastModifiedRow.appendChild(verticalLine);
 
 const agentsid = last_updated_by;

 const matchingAgent = globalAgents.find(agent => String(agent.id) === String(agentsid));

 if (matchingAgent) {
   console.log(`✅ Matching agent found:`, matchingAgent);
 } else {
   console.log(`❌ No agent found with id: ${agentsid}`);
 }
 
         const agentNameLabel = document.createElement("span");
         agentNameLabel.textContent = "By :";
         agentNameLabel.style.fontSize = "12px";
         agentNameLabel.style.color = "#183247";
         agentNameLabel.style.whiteSpace = "nowrap";
         agentNameLabel.style.marginLeft="149px"
         agentNameLabel.style.fontFamily =" -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif"

         const agentNameValue = document.createElement("span");
         if (matchingAgent) {
          agentNameValue.textContent = matchingAgent.contact.name|| "Unknown Agent"; 
      } else {
          agentNameValue.textContent = "Unknown Agent"; 
      }
         agentNameValue.style.color = "#183247";
         agentNameValue.style.fontWeight = "600";
         agentNameValue.style.whiteSpace = "nowrap";
         agentNameValue.style.fontFamily =" -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif"
         const verticalLine2 = document.createElement("div");
         verticalLine2.style.height = "20px";
         verticalLine2.style.borderLeft = "2px solid #ccc";
         verticalLine2.style.alignSelf = "stretch";
         verticalLine2.style.marginLeft = "100px";  // Increase for more right shift

 
         lastModifiedRow.appendChild(agentNameLabel);
         lastModifiedRow.appendChild(agentNameValue);
         lastModifiedRow.appendChild(verticalLine2);
 
         const affectedTicketsLabel = document.createElement("span");
         affectedTicketsLabel.textContent = "Impacted tickets (Last 7 days) : ";
         affectedTicketsLabel.style.fontSize = "12px";
         affectedTicketsLabel.style.color = "#183247";
         affectedTicketsLabel.style.marginLeft="140px";
         affectedTicketsLabel.style.whiteSpace = "nowrap";
         affectedTicketsLabel.style.fontFamily =" -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif"

         const affectedTicketsValue = document.createElement("span");
         affectedTicketsValue.textContent = affected_tickets_count === 0 ? "--" : affected_tickets_count;
         affectedTicketsValue.style.color = "#183247";
         affectedTicketsValue.style.fontWeight = "600";
         affectedTicketsValue.style.marginLeft ="134px"
         affectedTicketsValue.style.whiteSpace = "nowrap";
         affectedTicketsValue.style.fontFamily =" -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif"

         lastModifiedRow.appendChild(affectedTicketsLabel);
         lastModifiedRow.appendChild(affectedTicketsValue);
  
 

 
      const cardBody = document.createElement("div"); // Create a container for card content and actions
      cardBody.style.display = "flex"; // Flexbox to align items horizontally
      cardBody.style.justifyContent = "space-between"; // Ensure there's space between content and actions
      cardBody.style.alignItems = "flex-start"; // Align items to the top (optional, depending on your needs)
               

const truncatedContent = truncateContent(combinedContent, 200, 2);

const cardContent = document.createElement("pre");
cardContent.textContent = truncatedContent;

// Style the card content
cardContent.style.marginTop = "8px";
cardContent.style.padding = "8px";
cardContent.style.color="#183247";
cardContent.style.fontweight="600";
cardContent.style.fontFamily= "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif";
cardContent.style.whiteSpace = "pre-wrap"; // Ensure text wraps
cardContent.style.overflow = "hidden"; // Hide overflow content
cardContent.style.textOverflow = "ellipsis"; // Add ellipsis for overflow
cardContent.style.maxWidth = "75%"; // Limit the card width to half the container's width
cardContent.style.fontSize="12px";
cardContent.style.marginLeft="15px";


     // Create the container for card actions
const cardActionsContainer = document.createElement("div");
cardActionsContainer.style.display = "flex"; // Display actions horizontally
cardActionsContainer.style.justifyContent = "flex-end"; // Align to the right
cardActionsContainer.style.marginTop = "10px"; // Add some spacing above the actions
cardActionsContainer.style.gap = "8px"; // Set space between the toggle and the delete icon

      // Add fw-toggle
      // const fwToggle = document.createElement("fw-toggle");
      // fwToggle.setAttribute("size", "medium");
      // fwToggle.setAttribute("checked", "");

      // Add fw-icon
      const fwIcon = document.createElement("fw-icon");
      fwIcon.setAttribute("name", "delete");
      fwIcon.setAttribute("size", "18");
      fwIcon.style.cursor = "pointer";
      fwIcon.style.color = "red"; // Set the color to red
      // Add a pointer cursor for interactivity
      fwIcon.title = "Delete";

      fwIcon.addEventListener("click", () => {
        console.log("Delete icon clicked");
    
        currentRuleId = id; // Store the rule ID globally
        currentAutomationId = automation_type_id;
    
        console.log("rule id:", currentRuleId);
        console.log("automationid:", currentAutomationId);
    
        showDeletePopup(); 
    });
    
 
function showDeletePopup() {
  document.getElementById("deleteConfirmationPopup").style.display = "flex";
}


function hideDeletePopup() {
  document.getElementById("deleteConfirmationPopup").style.display = "none";
}
async function Fetchentity(automationTypeId, nextMarker = null, allRecords1 = []) {
  try {
    if (!newRulePloadDB5) {
      console.error(" Entity is not initialized yet!");
      showLoader();
      setTimeout(() => {
        location.reload();
    }, 1000);
    }

    showLoader(); 

    let queryObj = {
      query: {
        $and: [
          { automation_type_id: automationTypeId },
      
          { active: "true" } 
        ]
      } 
    };


    if (nextMarker) {
      console.log("🔄 Next marker found:", nextMarker);
      queryObj.next = { marker: nextMarker };
    }

    console.log("📤 Fetching records with query:", JSON.stringify(queryObj, null, 2));

    const response = await newRulePloadDB5.getAll(queryObj);

    if (!response.records || !Array.isArray(response.records)) {
      console.error("❌ Invalid response format:", response);
      hideLoader(); 
      return allRecords1;
    }

    console.log(`📥 Retrieved ${response.records.length} records`);
    allRecords1 = allRecords1.concat(response.records);

    const newNextMarker = response.links?.next?.marker || null;

    if (newNextMarker) {
      console.log(`🔄 More pages exist. Next marker: ${newNextMarker}`);
      return Fetchentity(automationTypeId, newNextMarker, allRecords1);
    } else {
      console.log("✅ No more pages.");
      console.log(`📌 Total Filtered Records: ${allRecords1.length}`);

      hideLoader();


        return allRecords1;
      
    }
  } catch (error) {
    console.error("❌ Error fetching filtered records:", error);
    hideLoader(); 
    return [];
  }
}
async function recenetconfirmDeletion() {
console.log(" Deleting rule with ID:", currentRuleId);

try {
  // Start progress loader
  let progressLoader = document.querySelector("#progress-container");
  if (progressLoader && typeof progressLoader.start === "function") {
    progressLoader.start();
  }

  let getdeleteruleResponse = await client.request.invokeTemplate("deleterule", {
    context: {
      automationid: currentAutomationId,
      ruleid: currentRuleId,
    },
  });

  console.log("getdeleteruleResponse", getdeleteruleResponse);

  if (getdeleteruleResponse.status === 204) {
    console.log("✅ Rule deleted successfully!");

    // Show success toast
    let valid = document.getElementById("type_toast");
    valid.setAttribute("content", "Rule deleted successfully");
    valid.setAttribute("type", "success");
    valid.setAttribute("open", true);

    // ✅ Remove the rule from the UI
   
    // displayGroupedRules4(duplicatesType1, "Ticketcreation1", automation_type_id, globalAgents);
    hideDeletePopup();

    if (currentAutomationId === 1) {
     

       
      const ruleIndex = duplicatesType1.findIndex(rule => rule.id === currentRuleId);
      
      if (ruleIndex === -1) {
        console.warn(`❌ Rule with ID ${currentRuleId} not found in duplicatesType1.`);
      } else {
        const ruleToDelete = duplicatesType1[ruleIndex];
      
        try {
          console.log("🗑️ Deleting rule with ID:", ruleToDelete.id);
       
      
          // ✅ Optionally remove it from the array to update UI or logic
          duplicatesType1.splice(ruleIndex, 1);
          console.log("✅ Rule deleted and removed from duplicatesType1 array.",duplicatesType1);
          displayGroupedRules4(duplicatesType1, "Ticketcreation1", automation_type_id, globalAgents);
      let progressLoader = document.querySelector("#progress-container");
  if (progressLoader && typeof progressLoader.start === "function") {
    progressLoader.done();
  }
        } catch (error) {
          console.error(`❌ Error deleting rule with ID ${ruleToDelete.id}:`, error);
        }
      }
      
      
      
              if (entitytype1.length === 0) {
                console.log(" entitytype1 is empty. Fetching records...");
                entitytype1 = await Fetchentity(1); 
                console.log("entity fethed after clicking recent data",entitytype1);
                const displayId = getDisplayIdByRuleId(entitytype1, currentRuleId);
                console.log("Matching Display ID:", displayId);
                if (!displayId) return; // Ensure rule ID is available
              
                try {
                    console.log(" Deleting rule with ID:", displayId);
                    await newRulePloadDB5.delete(displayId);
              
                } catch (error) {
                    console.warn(` Error deleting record with Display ID ${displayId}, but continuing...`);
                }    
        
              }
              const displayId = getDisplayIdByRuleId(entitytype1, currentRuleId);
              console.log("Matching Display ID:", displayId);
              if (!displayId) return; // Ensure rule ID is available
            
              try {
                  console.log(" Deleting rule with ID:", displayId);
                  await newRulePloadDB5.delete(displayId);
            
              } catch (error) {
                  console.warn(` Error deleting record with Display ID ${displayId}, but continuing...`);
              }    
             
          }
          else if (currentAutomationId === 3) {
           
            const ruleIndex = duplicatesType3.findIndex(rule => rule.id === currentRuleId);
      
            if (ruleIndex === -1) {
              console.warn(`❌ Rule with ID ${currentRuleId} not found in duplicatesType3.`);
            } else {
              const ruleToDelete = duplicatesType3[ruleIndex];
            
              try {
                console.log("🗑️ Deleting rule with ID:", ruleToDelete.id);
              
            
                // ✅ Optionally remove it from the array to update UI or logic
                duplicatesType3.splice(ruleIndex, 1);
                console.log("✅ Rule deleted and removed from duplicatesType3 array.",duplicatesType3);
                displayGroupedRules4(duplicatesType3, "HourlyTriggers1", automation_type_id, globalAgents);
                let progressLoader = document.querySelector("#progress-container");
                if (progressLoader && typeof progressLoader.start === "function") {
                  progressLoader.done();
                }
              } catch (error) {
                console.error(`❌ Error deleting rule with ID ${ruleToDelete.id}:`, error);
              }}
      
            if (entitytype3.length === 0) {
              console.log(" entitytype3 is empty. Fetching records...");
              entitytype3 = await Fetchentity(3); 
              console.log("entity fethed after clicking recent data",entitytype3);
        
              const displayId = getDisplayIdByRuleId(entitytype3, currentRuleId);
              console.log("Matching Display ID:", displayId);
              if (!displayId) return; 
            
              try {
                  console.log(" Deleting rule with ID:", displayId);
                  await newRulePloadDB5.delete(displayId);
            
              } catch (error) {
                  console.warn(` Error deleting record with Display ID ${displayId}, but continuing...`);
              }    
            }
            const displayId = getDisplayIdByRuleId(entitytype3, currentRuleId);
            console.log("Matching Display ID:", displayId);
            if (!displayId) return; 
          
            try {
                console.log(" Deleting rule with ID:", displayId);
                await newRulePloadDB5.delete(displayId);
          
            } catch (error) {
                console.warn(` Error deleting record with Display ID ${displayId}, but continuing...`);
            }    
            }

 

  }
} catch (error) {
  console.error(" Error deleting rule:", error);
}
}
function getDisplayIdByRuleId(entityRecords, currentRuleId) {
  console.log("Checking all records for Rule ID:", currentRuleId);
  
  if (!Array.isArray(entityRecords) || entityRecords.length === 0) {
      console.warn(" No records found in entity storage.");
      return null;
  }

  console.log(" Sample Record Structure:", entityRecords.slice(0, 5));
  console.log(" Available Keys in First Record:", Object.keys(entityRecords[0]));

  

  // Find the record where rule_id matches currentRuleId
  const matchedRecord = entityRecords.find(record => 
    String(record?.data?.rule_id) === String(currentRuleId) // Ensure type conversion
  );

  console.log("Does Rule ID exist in records?", matchedRecord !== undefined);

  return matchedRecord ? matchedRecord.display_id : null;
}
    
    
    
    // Attach event listeners to the confirmation buttons (only once)
    document.getElementById("confirmDeleteBtn").addEventListener("click", recenetconfirmDeletion);
    document.getElementById("cancelDeleteBtn").addEventListener("click", hideDeletePopup);
    

             
             
          // Append fw-toggle and fw-icon to cardActions
          // cardActionsContainer.appendChild(fwToggle);
          cardActionsContainer.appendChild(fwIcon);
          card.appendChild(cardHeader);
          cardBody.appendChild(cardContent);
          cardBody.appendChild(cardActionsContainer);
          card.appendChild(cardBody);
          cardContainer.appendChild(horizontalLine);
          // card.appendChild(horizontalLine);
         
          cardContainer.appendChild(lastModifiedRow);
          card.appendChild(cardContainer)
          groupContainer.appendChild(card);
        });
    
        container.appendChild(groupContainer);
      });
    // Add pagination component
    addFwPagination4(containerId,records,totalgroup,automation_type_id);
    }

// Function to add pagination for displayGroupedRules4
function addFwPagination4(containerId, records, totalgroup, automation_type_id) {
  console.log('Adding pagination to container:', containerId);
  console.log("Automation Type ID at Page Change:", automation_type_id);

  

  let container1 = document.getElementById(containerId);
  if (!container1) {
      console.warn(`Container with ID "${containerId}" not found.`);
      return;
  }

  if (totalgroup <= itemsPerPage4) {
      console.log("Total records are less than or equal to items per page, skipping pagination.");
      return;
  }

  let existingPagination1 = container1.querySelector("#fw-pagination-4");
  if (existingPagination1) {
      existingPagination1.remove(); // Remove old pagination if it exists
  }

  const pagination1 = document.createElement("fw-pagination");
  pagination1.id = "fw-pagination-4";

  pagination1.setAttribute("total", totalgroup);
  pagination1.setAttribute("per-page", itemsPerPage4);
  pagination1.setAttribute("page", currentPage4);

  console.log("Pagination Element:", pagination1);

  const paginationWrapper1 = document.createElement("div");
  paginationWrapper1.style.display = "flex";
  paginationWrapper1.style.justifyContent = "flex-start";
  paginationWrapper1.style.alignItems = "center";
  paginationWrapper1.style.width = "100%";
  paginationWrapper1.style.marginLeft = "70%";

  paginationWrapper1.appendChild(pagination1);
  container1.appendChild(paginationWrapper1);

  
  pagination1.addEventListener("fwChange", (event) => {
      console.log("fwChange Event Triggered", event);
      currentPage4 = event.detail.page;
      console.log("Updated Page:", currentPage4);

      // Retrieve automation_type_id from localStorage if missing
      let storedAutomationTypeId = localStorage.getItem("automation_type_id");

      console.log("Retrieved automation_type_id from localStorage:", storedAutomationTypeId);

      // Update the displayed rules for the current container, passing automation_type_id correctly
      displayGroupedRules4(records, containerId, storedAutomationTypeId,globalAgents);
  });
}

// function stripHTMLupdates(htmlString) {
//   return htmlString.replace(/<\/?[^>]+(>|$)/g, "");
// }


// function combineConditionsAndActions(data) {
//   const { 
//     performer = "", 
//     eventText = [], 
//     condition_set_1 = [], 
//     condition_set_2 = [], 
//     operator, 
//     actions = [] 
//   } = data;

//   const processedConditionSet1 = condition_set_1.map(stripHTML);
//   const processedConditionSet2 = condition_set_2.map(stripHTML);

//   const conditions = [
//     ...processedConditionSet1,
//     operator ? ` ${operator} ` : "",
//     ...processedConditionSet2,
//   ].join(" ");

//   const actionText = actions.length
//     ? actions.map(action => typeof action === 'string' ? stripHTML(action) : action).join(" ")
//     : "";

//   const eventTextContent = eventText.length
//     ? eventText.map(event => typeof event === 'string' ? stripHTML(event) : event).join(" ")
//     : "";

//   const performerText = performer ? stripHTML(performer) : "";

//   const combinedContent = [
//     performerText,
//     eventTextContent,
//     conditions,
//     actionText,
//   ].filter(Boolean).join(" ");

//   return combinedContent.trim();
// }


function combineConditionsAndActions(data) {
  const { 
    performer = "", 
    eventText = [], 
    condition_set_1 = [], 
    condition_set_2 = [], 
    operator, 
    actions = [] 
  } = data;

  // ✅ Process performer (Remove HTML, trim)
  const processedPerformer = performer ? stripHTML(performer).trim() : "";

  // ✅ Process event text (Remove HTML, join)
  const processedEventText = eventText.length 
    ? eventText.map(stripHTML).join(" ").trim()
    : "";

  // ✅ Remove HTML from conditions and keep order
  const processedConditionSet1 = condition_set_1.map(stripHTML);
  const processedConditionSet2 = condition_set_2.map(stripHTML);

  // ✅ Combine conditions with operator
  const originalConditions = [
    ...processedConditionSet1,
    operator ? ` ${operator} ` : "",
    ...processedConditionSet2,
  ].filter(Boolean).join(" ").trim(); 

  // ✅ Process actions
  const originalActions = actions.length
    ? actions.map(stripHTML).join(" ").trim()
    : "";

  // ✅ Create the final **original** content for display
  const originalContent = [
    processedPerformer,
    processedEventText,
    originalConditions,
    originalActions,
  ].filter(Boolean).join(" ").trim();

  // === ✅ SORTING LOGIC FIX ===
  
  // ✅ Sort conditions **independently** (keeps set1/set2 separate but sorted)
  const sortedConditionSet1 = [...processedConditionSet1].map(text => text.toLowerCase()).sort();
  const sortedConditionSet2 = [...processedConditionSet2].map(text => text.toLowerCase()).sort();

  const sortedConditions = [
    ...sortedConditionSet1,
    operator ? ` ${operator.toLowerCase()} ` : "",
    ...sortedConditionSet2,
  ].filter(Boolean).join(" ").trim();

  // ✅ Sort actions separately
  const sortedActions = actions.length
    ? [...actions.map(stripHTML).map(text => text.toLowerCase())].sort().join(" ").trim()
    : "";

  // ✅ Sort event text
  const sortedEventText = eventText.length
    ? [...eventText.map(stripHTML).map(text => text.toLowerCase())].sort().join(" ").trim()
    : "";

  // ✅ Sort performer (single value, so just lowercase)
  const sortedPerformer = processedPerformer.toLowerCase();

  // ✅ Create the final **sorted** content for grouping (keeping structure)
  const sortedContent = [
    sortedPerformer,  
    sortedEventText,  
    sortedConditions,  
    sortedActions  
  ].filter(Boolean).join(" ").trim();

  return { originalContent, sortedContent };
}



let currentPageDuplicates = 1;
const itemsPerPageDuplicates = 5;

function processAndDisplayDuplicates(duplicates, containerId,globalAgents) {
  console.log("function processAndDisplayDuplicates called");

  const container = document.getElementById(containerId);
  if (!container) {
    console.error(`Container with ID "${containerId}" not found.`);
    return;
  }

  container.innerHTML = ""; // Clear container

 
  if (duplicates.length === 0) {
    container.innerHTML = `
    <div style="
        display: flex;
        justify-content: center;
        align-items: center;
        height: 100vh;
        width: 100%;
        font-size: 24px;
        font-weight: bold;
        color: #333;
        margin-left: 400px; 
        text-align: center;
    ">
        No duplicate rules found.
    </div>`;
return;
  }


  const groupedRules = new Map();

  duplicates.forEach((record) => {
    const rule = record.parsedPayload || record.rule || record;

    if (!rule || !rule.summary) {
      console.warn("Skipping record due to missing data:", record);
      return;
    }

    const { name, summary, position, updated_at, last_updated_by, affected_tickets_count, id } = rule;

    if (summary && summary.conditions) {
      const actions = summary.actions || [];
      const performer = summary.performer || "";
      const eventText = summary.events || [];

      // ✅ Get both sorted and original content
      const { originalContent, sortedContent } = combineConditionsAndActions({
        performer: performer,
        eventText: eventText,
        condition_set_1: summary.conditions.condition_set_1,
        condition_set_2: summary.conditions.condition_set_2,
        operator: summary.conditions.operator,
        actions: actions,
      });

      // ✅ Use sortedContent for grouping
      if (!groupedRules.has(sortedContent)) {
        groupedRules.set(sortedContent, []);
      }

      // ✅ Store both sortedContent (for grouping) and originalContent (for display)
      groupedRules.get(sortedContent).push({
        name,
        position,
        combinedContent: originalContent, // ✅ Use originalContent for display
        performer,
        eventText,
        conditions: summary.conditions,
        actions,
        updated_at,
        last_updated_by,
        affected_tickets_count,
        id,
      });
    }
  });

  const groupedRulesArray = Array.from(groupedRules.values());

  const totalgroup = Math.ceil(groupedRulesArray.length );
  console.log(totalgroup,"*********************")
  const totalPagesDuplicates = Math.ceil(groupedRulesArray.length / itemsPerPageDuplicates);
  currentPageDuplicates = Math.max(1, Math.min(currentPageDuplicates, totalPagesDuplicates));

  console.log("Total Pages:", totalPagesDuplicates, "Current Page:", currentPageDuplicates);

  const startIdx = (currentPageDuplicates - 1) * itemsPerPageDuplicates;
  const paginatedRules = groupedRulesArray.slice(startIdx, startIdx + itemsPerPageDuplicates);

  console.log("Displaying Records:", paginatedRules);
  
  let arrayLength = paginatedRules.length;
  console.log("Records Length:", arrayLength);

  paginatedRules.forEach((titles) => {
    const rulesCount = titles.length;

    // ✅ Skip the group if it contains only one rule
    if (rulesCount === 1) {
        console.log(`Skipping group with only 1 rule: ${titles[0].name}`);
        return; // Stop further execution for this group
    }
    const groupContainer = document.createElement("div");
    groupContainer.style.border = "1px solid #ccc";
    groupContainer.style.padding = "16px";
    groupContainer.style.margin = "16px";
    groupContainer.style.borderRadius = "8px";
    groupContainer.style.backgroundColor = "#f5f7f9";
    groupContainer.style.width = "1200px";
  
    titles.forEach(({ name, position, combinedContent, performer, 
      eventText, conditions, actions,updated_at,
      last_updated_by,
      affected_tickets_count,id}, index) => {
      const card = document.createElement("div");
      card.style.border = "1px solid #ccc";
      card.style.padding = "16px";
      card.style.margin = "8px 0";
      card.style.fontFamily =
        "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif";
      card.style.borderRadius = "8px";
      card.style.backgroundColor = index === 0 ? "#fff" : "#e5f2fd";
      card.style.marginBottom = "10px";
      card.style.paddingBottom = "0";
     
  
      const cardHeader = document.createElement("div");
      cardHeader.style.display = "flex";
      cardHeader.style.justifyContent = "space-between";
      cardHeader.style.alignItems = "center";
    // Create a wrapper for the title
const cardTitle = document.createElement("h4");
cardTitle.style.margin = "0";
cardTitle.style.cursor = "pointer";
cardTitle.style.fontSize = "14px";
cardTitle.style.fontFamily = "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif";
cardTitle.style.color = "#183247";
cardTitle.style.transition = "color 0.2s ease";
cardTitle.style.fontWeight = "600"; 

// Create the serial number (position)
if (position) {
const serialNumber = document.createElement("span");
serialNumber.textContent = position + ". ";
serialNumber.style.color = "#183247"; // Keep serial number color fixed
cardTitle.appendChild(serialNumber);
}

// Create the actual name (clickable part)
const titleText = document.createElement("span");
titleText.textContent = name;
titleText.style.color = "#183247"; 
titleText.style.transition = "color 0.2s ease";

// Add hover effect for only the name
titleText.addEventListener("mouseover", () => {
titleText.style.color = "#007bff"; // Change only name color on hover
});
titleText.addEventListener("mouseout", () => {
titleText.style.color = "#183247"; // Reset name color when not hovering
});
titleText.addEventListener("click", () => {
titleText.style.color = "#ff5733"; // Change title color on click
showPopupCard1(name, { performer: performer, 
eventText: eventText, conditions: conditions, actions: actions, });
});

// Append name to title
cardTitle.appendChild(titleText);
      // Append title and actions to the cardHeader
      cardHeader.appendChild(cardTitle);
      

      const cardContainer = document.createElement("div");

// Style the container to have a background color in the gap
cardContainer.style.backgroundColor = "#f0f0f0";  // Set the background color for the gap (change to desired color)
cardContainer.style.paddingBottom = "20px";  
cardContainer.style.marginLeft="-15px";
cardContainer.style.borderRadius = "4px";
cardContainer.style.width="102.7%";

// Create a horizontal line after the cardBody
const horizontalLine = document.createElement("div");
horizontalLine.style.height = "1px"; // Set the height to 1px for a thin line
horizontalLine.style.backgroundColor = "#ccc"; // Set the color of the horizontal line
horizontalLine.style.marginTop = "16px"; // Add space above the line (adjust as needed)
horizontalLine.style.width = "100%"; // Ensure the line stretches the full width of the container
horizontalLine.style.marginLeft="-3px";


function truncateContent(content, maxLength, lines) {
// Truncate the content to the desired number of characters
let truncated = content;

// Adjust for the desired line count and maximum length
if (content.length > maxLength) {
  truncated = content.slice(0, maxLength) + "...";
}

// Break content into lines manually for multi-line truncation
const words = truncated.split(" ");
const result = [];
let line = "";
let currentLine = 1;

for (let i = 0; i < words.length; i++) {
  if (line.length + words[i].length + 1 <= maxLength / lines) {
    line += (line ? " " : "") + words[i];
  } else {
    result.push(line);
    line = words[i];
    currentLine++;
    if (currentLine > lines) break; // Stop adding more lines if max lines are reached
  }
}

if (currentLine <= lines && line) {
  result.push(line);
}

return result.join(" ") + (currentLine > lines ? "..." : "");
}
function calculateLastModified(updated_at) {
const updatedDate = new Date(updated_at);
const currentDate = new Date();

const diffInMilliseconds = currentDate - updatedDate;
const seconds = Math.floor(diffInMilliseconds / 1000);
const minutes = Math.floor(seconds / 60);
const hours = Math.floor(minutes / 60);
const days = Math.floor(hours / 24);
const months = Math.floor(days / 30);  // Approximate months
const years = Math.floor(days / 365);  // Approximate years

if (years > 0) {
    return years === 1 ? "a year ago" : `${years} years ago`;
} else if (months > 0) {
    return months === 1 ? "a month ago" : `${months} months ago`;
} else if (days > 0) {
    return `${days} day${days > 1 ? "s" : ""} ago`;
} else if (hours > 0) {
    return `${hours} hour${hours > 1 ? "s" : ""} ago`;
} else if (minutes > 0) {
    return `${minutes} minute${minutes > 1 ? "s" : ""} ago`;
} else {
    return "Just now";
}
}

// console.log("updated at",calculateLastModified(updated_at));

// Create a row for "Last Modified"
const lastModifiedRow = document.createElement("div");
lastModifiedRow.style.display = "grid";
lastModifiedRow.style.gridTemplateColumns = "150px 150px 2px 150px 150px 2px 150px 150px"; // Consistent width for each section
lastModifiedRow.style.alignItems = "center";
lastModifiedRow.style.marginTop = "10px";
lastModifiedRow.style.fontSize = "12px";
lastModifiedRow.style.gap = "20px";
lastModifiedRow.style.width = "100%"; // Ensures full width alignment

const lastModifiedLabel = document.createElement("span");
lastModifiedLabel.textContent = "Last Modified :";
lastModifiedLabel.style.color = "#183247";
lastModifiedLabel.style.fontSize = "12px";
lastModifiedLabel.style.display = "inline-flex";
lastModifiedLabel.style.fontFamily =" -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif"
lastModifiedLabel.style.marginLeft = "40px"

const lastModifiedValue = document.createElement("span");
const lastModifiedText = calculateLastModified(updated_at);
lastModifiedValue.textContent = lastModifiedText;
lastModifiedValue.style.color = "#183247";
lastModifiedValue.style.fontWeight = "600";
lastModifiedValue.style.display = "inline-flex";
lastModifiedValue.style.fontSize = "12px";
lastModifiedValue.style.marginLeft = "-50px"
lastModifiedValue.style.justifySelf = "start";
lastModifiedValue.style.fontFamily =" -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif"

const verticalLine = document.createElement("div");
verticalLine.style.height = "20px";
verticalLine.style.borderLeft = "2px solid #ccc";
verticalLine.style.alignSelf = "stretch";

lastModifiedRow.appendChild(lastModifiedLabel);
lastModifiedRow.appendChild(lastModifiedValue);
lastModifiedRow.appendChild(verticalLine);

const agentsid = last_updated_by;




const matchingAgent = globalAgents.find(agent => String(agent.id) === String(agentsid));

if (matchingAgent) {
  console.log(`✅ Matching agent found:`, matchingAgent);
} else {
  console.log(`❌ No agent found with id: ${agentsid}`);
}

 const agentNameLabel = document.createElement("span");
 agentNameLabel.textContent = "By :";
 agentNameLabel.style.fontSize = "12px";
 agentNameLabel.style.color = "#183247";
 agentNameLabel.style.whiteSpace = "nowrap";
 agentNameLabel.style.marginLeft="149px"
 agentNameLabel.style.fontFamily =" -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif"

 const agentNameValue = document.createElement("span");
 if (matchingAgent) {
  agentNameValue.textContent = matchingAgent.contact.name|| "Unknown Agent"; 
} else {
  agentNameValue.textContent = "Unknown Agent"; 
}
 agentNameValue.style.color = "#183247";
 agentNameValue.style.fontWeight = "600";
 agentNameValue.style.whiteSpace = "nowrap";
 agentNameValue.style.fontFamily =" -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif"
 const verticalLine2 = document.createElement("div");
 verticalLine2.style.height = "20px";
 verticalLine2.style.borderLeft = "2px solid #ccc";
 verticalLine2.style.alignSelf = "stretch";
 verticalLine2.style.marginLeft = "100px";  // Increase for more right shift


 lastModifiedRow.appendChild(agentNameLabel);
 lastModifiedRow.appendChild(agentNameValue);
 lastModifiedRow.appendChild(verticalLine2);

 const affectedTicketsLabel = document.createElement("span");
 affectedTicketsLabel.textContent = "Impacted tickets (Last 7 days) : ";
 affectedTicketsLabel.style.fontSize = "12px";
 affectedTicketsLabel.style.color = "#183247";
 affectedTicketsLabel.style.marginLeft="140px";
 affectedTicketsLabel.style.whiteSpace = "nowrap";
 affectedTicketsLabel.style.fontFamily =" -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif"

 const affectedTicketsValue = document.createElement("span");
 affectedTicketsValue.textContent = affected_tickets_count === 0 ? "--" : affected_tickets_count;
 affectedTicketsValue.style.color = "#183247";
 affectedTicketsValue.style.fontWeight = "600";
 affectedTicketsValue.style.marginLeft ="134px"
 affectedTicketsValue.style.whiteSpace = "nowrap";
 affectedTicketsValue.style.fontFamily =" -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif"

 lastModifiedRow.appendChild(affectedTicketsLabel);
 lastModifiedRow.appendChild(affectedTicketsValue);




const cardBody = document.createElement("div"); // Create a container for card content and actions
cardBody.style.display = "flex"; // Flexbox to align items horizontally
cardBody.style.justifyContent = "space-between"; // Ensure there's space between content and actions
cardBody.style.alignItems = "flex-start"; // Align items to the top (optional, depending on your needs)
       

const truncatedContent = truncateContent(combinedContent, 200, 2);

const cardContent = document.createElement("pre");
cardContent.textContent = truncatedContent;

// Style the card content
cardContent.style.marginTop = "8px";
cardContent.style.padding = "8px";
cardContent.style.whiteSpace = "pre-wrap"; // Ensure text wraps
cardContent.style.overflow = "hidden"; // Hide overflow content
cardContent.style.textOverflow = "ellipsis"; // Add ellipsis for overflow
cardContent.style.maxWidth = "75%"; // Limit the card width to half the container's width
cardContent.style.fontSize="12px";
cardContent.style.color="#183247";
cardContent.style.fontweight="600";
cardContent.style.fontFamily= "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif";
cardContent.style.marginLeft="15px"

// Create the container for card actions
const cardActionsContainer = document.createElement("div");
cardActionsContainer.style.display = "flex"; // Display actions horizontally
cardActionsContainer.style.justifyContent = "flex-end"; // Align to the right
cardActionsContainer.style.marginTop = "10px"; // Add some spacing above the actions
cardActionsContainer.style.gap = "8px"; // Set space between the toggle and the delete icon

// Add fw-toggle
// const fwToggle = document.createElement("fw-toggle");
// fwToggle.setAttribute("size", "medium");
// fwToggle.setAttribute("checked", "");

// Add fw-icon
const fwIcon = document.createElement("fw-icon");
fwIcon.setAttribute("name", "delete");
fwIcon.setAttribute("size", "18");
fwIcon.style.cursor = "pointer";
fwIcon.style.color = "red"; // Set the color to red
// Add a pointer cursor for interactivity
fwIcon.title = "Delete";
fwIcon.addEventListener("click", () => {
  console.log("Delete icon clicked");
  console.log("Rule ID:", id);

  // Show the confirmation popup before deleting
  showDeletePopup();

  // Function to show the confirmation popup
  function showDeletePopup() {
      document.getElementById("deleteConfirmationPopup").style.display = "flex";
  }

  // Function to hide the confirmation popup
  function hideDeletePopup() {
      document.getElementById("deleteConfirmationPopup").style.display = "none";
  }
  async function Fetchentity(automationTypeId, nextMarker = null, allRecords1 = []) {
    try {
      if (!newRulePloadDB5) {
        console.error(" Entity is not initialized yet!");
        showLoader();
        setTimeout(() => {
          location.reload();
      }, 1000);
      }
  
      showLoader(); 
  
      let queryObj = {
        query: {
          $and: [
            { automation_type_id: automationTypeId },
        
            { active: "true" } 
          ]
        } 
      };
  
  
      if (nextMarker) {
        console.log("🔄 Next marker found:", nextMarker);
        queryObj.next = { marker: nextMarker };
      }
  
      console.log("📤 Fetching records with query:", JSON.stringify(queryObj, null, 2));
  
      const response = await newRulePloadDB5.getAll(queryObj);
  
      if (!response.records || !Array.isArray(response.records)) {
        console.error("❌ Invalid response format:", response);
        hideLoader(); 
        return allRecords1;
      }
  
      console.log(`📥 Retrieved ${response.records.length} records`);
      allRecords1 = allRecords1.concat(response.records);
  
      const newNextMarker = response.links?.next?.marker || null;
  
      if (newNextMarker) {
        console.log(`🔄 More pages exist. Next marker: ${newNextMarker}`);
        return Fetchentity(automationTypeId, newNextMarker, allRecords1);
      } else {
        console.log("✅ No more pages.");
        console.log(`📌 Total Filtered Records: ${allRecords1.length}`);
  
        hideLoader();
  
  
          return allRecords1;
        
      }
    } catch (error) {
      console.error("❌ Error fetching filtered records:", error);
      hideLoader(); 
      return [];
    }
  }
  async function confirmDeletions() {
    console.log(" Deleting rule with ID:", id);

    // Start progress loader
    let progressLoader = document.querySelector("#progress-container");
    if (progressLoader && typeof progressLoader.start === "function") {
        progressLoader.start();
    }

    try {
        let getdeleteruleResponse = await client.request.invokeTemplate("deleterule", {
            context: { 
                automationid: 4, 
                ruleid: id 
            }
        });

        console.log("getdeleteruleResponse", getdeleteruleResponse);

        if (getdeleteruleResponse.status === 204) {
            console.log("✅ Rule deleted successfully!");

            // Show success toast
            let valid = document.getElementById('type_toast');
            valid.setAttribute('content', 'Rule deleted successfully');
            valid.setAttribute('type', 'success');
            valid.setAttribute('open', true);

            // ✅ Remove from UI
            removeDeletedRuleFromUI(id);
            hideDeletePopup();

            console.log("Before deletion, existing rule IDs:", duplicatesType4.map(rule => rule.id));

            // ✅ Convert to string for comparison
            const ruleIdToDelete = String(id);

            // ✅ Find and delete rule from duplicatesType4
            const index = duplicatesType4.findIndex(rule => String(rule.id) === ruleIdToDelete);
            console.log("Rule index found:", index);

            if (index !== -1) {
                duplicatesType4.splice(index, 1); // Remove rule from array
                console.log("✅ Rule removed from duplicatesType4.");
            } else {
                console.warn("⚠️ Rule not found in duplicatesType4. Possible ID mismatch.");
            }

          
                console.log("Duplicates after deleting:", duplicatesType4);
                processAndDisplayDuplicates(duplicatesType4, "TicketUpdates1",globalAgents);


                let progressLoader = document.querySelector("#progress-container");
                if (progressLoader && typeof progressLoader.start === "function") {
                  progressLoader.done();
                }


                if (entitytype4.length === 0) {
                  console.log(" entitytype4 is empty. Fetching records...");
                  entitytype4 = await Fetchentity(4); 
                  console.log("entity fethed after clicking recent data",entitytype4);
                  const displayId = getDisplayIdByRuleId(entitytype4, id);
                  console.log("Matching Display ID:", displayId);
                  if (!displayId) return; // Ensure rule ID is available
                
                  try {
                      console.log(" Deleting rule with ID:", displayId);
                      await newRulePloadDB5.delete(displayId);
                
                  } catch (error) {
                      console.warn(` Error deleting record with Display ID ${displayId}, but continuing...`);
                  }    
          
                }
                const displayId = getDisplayIdByRuleId(entitytype4, id);
                console.log("Matching Display ID:", displayId);
                if (!displayId) return; // Ensure rule ID is available
              
                try {
                    console.log(" Deleting rule with ID:", displayId);
                    await newRulePloadDB5.delete(displayId);
              
                } catch (error) {
                    console.warn(` Error deleting record with Display ID ${displayId}, but continuing...`);
                }    
               
            

               
        
        }
    } catch (error) {
        console.error("❌ Error deleting rule:", error);

        // Show error toast
        let errorToast = document.getElementById('type_toast');
        errorToast.setAttribute('content', "Failed to delete rule. Please try again.");
        errorToast.setAttribute('type', 'error');
        errorToast.setAttribute('open', true);
    } finally {
        // Ensure progress loader stops if an error occurs
        if (progressLoader && typeof progressLoader.done === "function") {
            progressLoader.done();
        }
    }

    // Hide the popup after action
    hideDeletePopup();
}

  // Function to remove the deleted rule from UI
  function removeDeletedRuleFromUI(ruleId) {
      let ruleCard = document.querySelector(`[data-rule-id="${ruleId}"]`);
      if (ruleCard) {
          ruleCard.remove();
      }
  }
  function getDisplayIdByRuleId(entityRecords, id) {
    console.log("Checking all records for Rule ID:", id);
    
    if (!Array.isArray(entityRecords) || entityRecords.length === 0) {
        console.warn(" No records found in entity storage.");
        return null;
    }
  
    console.log(" Sample Record Structure:", entityRecords.slice(0, 5));
    console.log(" Available Keys in First Record:", Object.keys(entityRecords[0]));
  
    
  
    // Find the record where rule_id matches currentRuleId
    const matchedRecord = entityRecords.find(record => 
      String(record?.data?.rule_id) === String(id) 
    );
  
    console.log("Does Rule ID exist in records?", matchedRecord !== undefined);
  
    return matchedRecord ? matchedRecord.display_id : null;
  }
      
  // Attach event listeners once (outside the click event)
  document.getElementById("confirmDeleteBtn").addEventListener("click", confirmDeletions);
  document.getElementById("cancelDeleteBtn").addEventListener("click", hideDeletePopup);
});

// fwIcon.addEventListener("click", async () => {
//   console.log("Delete icon clicked");
  

//    console.log("rule id:", id);
 
//   // Show the confirmation popup before deleting
//   showDeletePopup();
//     // Function to show the confirmation popup
// function showDeletePopup() {
// document.getElementById("deleteConfirmationPopup").style.display = "flex";
// }

// // Function to hide the confirmation popup
// function hideDeletePopup() {
// document.getElementById("deleteConfirmationPopup").style.display = "none";
// }

// // Function to handle deletion after confirmation
// async function confirmDeletion() {
// console.log("Deleting rule with ID:", id);

// try {
//     let getdeleteruleResponse = await client.request.invokeTemplate("deleterule", {
//       context:{  automationid:4,
//                   ruleid: id ,}
//     });

//     console.log("getdeleteruleResponse", getdeleteruleResponse);

//     // Show success toast
//     let valid = document.getElementById('type_toast');
//     console.log("toat message called", valid);
//     valid.setAttribute('content', 'Rule deleted successfully');
//     valid.setAttribute('type', 'success');
//     valid.setAttribute('open', true);

//     // Remove the deleted rule from UI
//     removeDeletedRuleFromUI(window.currentRuleId);

// } catch (error) {
//     console.error("Error deleting rule:", error);

//     // Show error toast
//     let errorToast = document.getElementById('type_toast');
//     errorToast.setAttribute('content', 'Error deleting rule. Please try again.');
//     errorToast.setAttribute('type', 'error');
//     errorToast.setAttribute('open', true);
// }

// // Hide the popup after action
// hideDeletePopup();
// }

// // Function to remove the deleted rule from UI
// function removeDeletedRuleFromUI(ruleId) {
// let ruleCard = document.querySelector(`[data-rule-id="${ruleId}"]`);
// if (ruleCard) {
//     ruleCard.remove();
// }
// }

// // Attach event listeners once (outside the click event)
// document.getElementById("confirmDeleteBtn").addEventListener("click", confirmDeletion);
// document.getElementById("cancelDeleteBtn").addEventListener("click", hideDeletePopup);
// });

// Append fw-toggle and fw-icon to cardActions
// cardActionsContainer.appendChild(fwToggle);
cardActionsContainer.appendChild(fwIcon);
card.appendChild(cardHeader);
cardBody.appendChild(cardContent);
cardBody.appendChild(cardActionsContainer);
card.appendChild(cardBody);
cardContainer.appendChild(horizontalLine);
// card.appendChild(horizontalLine);

cardContainer.appendChild(lastModifiedRow);
card.appendChild(cardContainer)
groupContainer.appendChild(card);
    });

    
    container.appendChild(groupContainer);
  });

  // Add pagination component
  addFwPaginationDuplicates(containerId, duplicates,totalgroup);
}

// Function to add pagination for processAndDisplayDuplicates
function addFwPaginationDuplicates(containerId,duplicates,totalgroup) {
  console.log("Adding pagination to container:", containerId);

  let container = document.getElementById(containerId);

  if (!container) {
    console.warn(`Container with ID "${containerId}" not found.`);
    return;
  }
  console.log("itemsperpage duplicates*********",itemsPerPageDuplicates)
  if (totalgroup <= itemsPerPageDuplicates) {
    
    console.log("Total records are less than or equal to items per page, skipping pagination.");
    return;
  }

  let existingPagination2 = container.querySelector("#fw-pagination-duplicates");
  if (existingPagination2) {
    existingPagination2.remove(); // Remove old pagination if it exists
  }

  const pagination2 = document.createElement("fw-pagination");
  pagination2.id = "fw-pagination-duplicates";
console.log("total group inside", )
  pagination2.setAttribute("total", totalgroup);
  pagination2.setAttribute("per-page", itemsPerPageDuplicates);
  pagination2.setAttribute("page", currentPageDuplicates);

  console.log("Pagination Element:", pagination2);

  const paginationWrapper2 = document.createElement("div");
  paginationWrapper2.style.display = "flex";
  paginationWrapper2.style.justifyContent = "flex-start";
  paginationWrapper2.style.alignItems = "center";
  paginationWrapper2.style.width = "100%";
  paginationWrapper2.style.marginLeft = "70%";

  paginationWrapper2.appendChild(pagination2);
  container.appendChild(paginationWrapper2);

  pagination2.addEventListener("fwChange", (event) => {
    console.log("fwChange Event Triggered", event);
    currentPageDuplicates = event.detail.page;
    console.log("Updated Page:", currentPageDuplicates);

    // Update the displayed rules for the current container
    processAndDisplayDuplicates(duplicates, containerId,globalAgents);
  });
}


let entitytype1 = [];
let entitytype3 = [];
let entitytype4 = [];
async function Filterrecords(automationTypeId, nextMarker = null, allRecords = []) {


  // console.log("filterrecords called for automationtypeid",automationTypeId);

  try {
    if (!newRulePloadDB5) {
      console.error(" Entity is not initialized yet!");
      showLoader();
      setTimeout(() => {
        location.reload();
    }, 1000);
    }

    showLoader(); // Show spinner before fetching starts

    let queryObj = {
      query: {
        $and: [
          { automation_type_id: automationTypeId },
      
          { active: "true" } 
        ]
      } 
    };

    if (nextMarker) {
      console.log("🔄 Next marker found:", nextMarker);
      queryObj.next = { marker: nextMarker };
    }

    console.log("📤 Fetching records with query:", JSON.stringify(queryObj, null, 2));

    const response = await newRulePloadDB5.getAll(queryObj);

    if (!response.records || !Array.isArray(response.records)) {
      console.error("❌ Invalid response format:", response);
      hideLoader(); // Hide spinner on failure
      return allRecords;
    }

    console.log(`📥 Retrieved ${response.records.length} records`);
    allRecords = allRecords.concat(response.records);

    const newNextMarker = response.links?.next?.marker || null;

    if (newNextMarker) {
      console.log(`🔄 More pages exist. Next marker: ${newNextMarker}`);
      return Filterrecords(automationTypeId, newNextMarker, allRecords);
    } else {
      console.log("✅ No more pages.");
      console.log(`📌 Total Filtered Records: ${allRecords.length}`);

      hideLoader(); // Hide spinner once fetching is complete

      //  Conditional function call based on automationTypeId
      if (automationTypeId === 1) {
      
         entitytype1 = allRecords;
         console.log("entity copy array",entitytype1);
        return findDuplicateRulestype1and3(allRecords);
      } else if(automationTypeId === 3)
      {
        entitytype3 = allRecords;
         console.log("entity copy array",entitytype3);
        return findDuplicateRulestype1and3(allRecords);
      }
      else if (automationTypeId === 4) {
        entitytype4 = allRecords;
         console.log("entity copy array",entitytype4);
        return findDuplicateRulestype4(allRecords);
      } else {
        console.warn("⚠️ Unknown automationTypeId:", automationTypeId);
        return allRecords;
      }
    }
  } catch (error) {
    console.error("❌ Error fetching filtered records:", error);
    hideLoader(); // Hide spinner on error
    return [];
  }
}


  
// async function Filterrecords(automationTypeId, nextMarker = null, allRecords = []) {


//   // console.log("filterrecords called for automationtypeid",automationTypeId);

//   try {
//     if (!newRulePloadDB5) {
//       console.error(" Entity is not initialized yet!");
//       showLoader();
//       setTimeout(() => {
//         location.reload();
//     }, 1000);
//     }

//     showLoader(); // Show spinner before fetching starts

//     let queryObj = {
//       query: { automation_type_id: automationTypeId }
//     };

//     if (nextMarker) {
//       console.log("🔄 Next marker found:", nextMarker);
//       queryObj.next = { marker: nextMarker };
//     }

//     console.log("📤 Fetching records with query:", JSON.stringify(queryObj, null, 2));

//     const response = await newRulePloadDB5.getAll(queryObj);

//     if (!response.records || !Array.isArray(response.records)) {
//       console.error("❌ Invalid response format:", response);
//       hideLoader(); // Hide spinner on failure
//       return allRecords;
//     }

//     console.log(`📥 Retrieved ${response.records.length} records`);
//     allRecords = allRecords.concat(response.records);

//     const newNextMarker = response.links?.next?.marker || null;

//     if (newNextMarker) {
//       console.log(`🔄 More pages exist. Next marker: ${newNextMarker}`);
//       return Filterrecords(automationTypeId, newNextMarker, allRecords);
//     } else {
//       console.log("✅ No more pages.");
//       console.log(`📌 Total Filtered Records: ${allRecords.length}`);

//       hideLoader(); // Hide spinner once fetching is complete

//       //  Conditional function call based on automationTypeId
//       if (automationTypeId === 1 || automationTypeId === 3) {
//         console.log("allrecords fetched from entity", allRecords)
//         return findDuplicateRulestype1and3(allRecords);
//       } else if (automationTypeId === 4) {
//         console.log("allrecords fetched from entity", allRecords)
//         return findDuplicateRulestype4(allRecords);
//       } else {
//         console.warn("⚠️ Unknown automationTypeId:", automationTypeId);
//         return allRecords;
//       }
//     }
//   } catch (error) {
//     console.error("❌ Error fetching filtered records:", error);
//     hideLoader(); // Hide spinner on error
//     return [];
//   }
// }

function showLoader() {
  console.log("showloader function called");
  document.getElementById("spinner").style.display = "block";
}

function hideLoader() {
  console.log("*********hide loader")
  document.getElementById("spinner").style.display = "none";
}



// 3 Function to find duplicate rules

function findDuplicateRulestype1and3(records) {
  const seenRules = new Map(); // Store unique rules with their first occurrence
  const duplicateRecords = []; // Store all duplicate records

  records.forEach((record) => {
    const { summary, conditions, actions, operator} = record.data;

    // if (!record.data.active) return; // Skip inactive records

    // console.log("Processing active record:", record); // Log full record

    // Function to remove all <img> tags from HTML content
    const stripImageTags = (html) => html.replace(/<img[^>]*>/g, "");

    // // Log conditions and actions before sorting
    // console.log("Original Conditions:", conditions);
    // console.log("Original Actions:", actions);

    // Normalize and sort conditions
    const normalizedConditions = conditions
      ? conditions
          .split(",") // Split into an array
          .map((c) => c.trim().toLowerCase()) // Trim and lowercase
          .sort() // Sort for consistency
          .join(",") // Join back into a string
      : "";

    // Normalize and sort actions
    const normalizedActions = actions
      ? stripImageTags(actions)
          .split(",") // Split into an array
          .map((a) => a.trim().toLowerCase()) // Trim and lowercase
          .sort() // Sort for consistency
          .join(",") // Join back into a string
      : "";

    // Log conditions and actions after sorting
    // console.log("Sorted Conditions:", normalizedConditions);
    // console.log("Sorted Actions:", normalizedActions);

    // Check for punctuation in summary
    if (summary && /[.,\/#!$%\^&\*;:{}=\-_`~()]/.test(summary)) {
      console.log("Punctuation found in summary:", summary);
    }

    // Normalize and sort summary (if structured)
    const normalizedSummary = summary
      ? summary
          .toLowerCase()
          .split(/\s+/) // Split by whitespace
          .sort() // Sort words alphabetically
          .join(" ") // Rejoin into a sorted sentence
      : "";

    // Log the sorted summary
    // console.log("Sorted Summary:", normalizedSummary);

    // Normalize operator
    const normalizedOperator = operator ? operator.trim().toLowerCase() : null;

    // Create a unique key to compare records
    const recordKey = `${normalizedSummary}|${normalizedConditions}|${normalizedActions}|${normalizedOperator}`;

    if (seenRules.has(recordKey)) {
      if (!duplicateRecords.includes(seenRules.get(recordKey))) {
        duplicateRecords.push(seenRules.get(recordKey)); // Add original rule
      }
      duplicateRecords.push(record); // Add duplicate rule
    } else {
      seenRules.set(recordKey, record);
    }
  });

  return duplicateRecords;
}

let isFetchingType1 = false; // Global flag to track fetching state

async function handleDuplicateRulestype1() {
  if (isFetchingType1|| type1 > 0) return; // Prevent duplicate calls if already fetching

  isFetchingType1 = true; // Set flag before execution starts
  console.log("handleDuplicateRulestype1 called");

  try {
    const duplicatesType1 = await Filterrecords(1); // Get duplicates
    console.log("🔄 Final duplicate records:", duplicatesType1);

    // Pass to grouping function with container ID
    displayGroupedRules(duplicatesType1, "Ticketcreation");
    type1++;
  } catch (error) {
    console.error("❌ Error handling duplicate rules for type 1:", error);
  } finally {
    isFetchingType1 = false; // ✅ Reset flag after execution completes
  }
}


 
// 3️⃣ Handle duplicate rule detection & pass to grouping function
// async function handleDuplicateRulestype1() {
//   const duplicatesType1 = await Filterrecords(1); // Get duplicates
//   console.log("🔄 Final duplicate records:", duplicatesType1,);


  


//   // Pass to grouping function with container ID
//   displayGroupedRules(duplicatesType1, "Ticketcreation");
// }

function stripHTML(htmlString) {
  return htmlString.replace(/<\/?[^>]+(>|$)/g, "");
}

// Function to show popup card with blur effect
function showPopupCard(title, content, automation_type_id) {

  if (automation_type_id !== undefined && automation_type_id !== null) {
      localStorage.setItem("automation_type_id", automation_type_id); 
  } else {
      automation_type_id = localStorage.getItem("automation_type_id") || "Unknown";
  }

  console.log("logPopup", automation_type_id);



const overlay = document.createElement("div");
overlay.style.position = "fixed";


overlay.style.top = "0";
overlay.style.left = "0";
overlay.style.width = "100%";
overlay.style.height = "100%";
overlay.style.backgroundColor = "rgba(0, 0, 0, 0.3)"; // Semi-transparent dark background
overlay.style.backdropFilter = "blur(5px)"; // Apply blur effect
overlay.style.zIndex = "999"; // Ensure it appears above everything else

// Create popup container
const popupContainer = document.createElement("div");
popupContainer.style.position = "fixed";
popupContainer.style.top = "50%";
popupContainer.style.left = "50%";
popupContainer.style.transform = "translate(-50%, -50%)";
popupContainer.style.width = "1000px"; // Increased default width
popupContainer.style.maxWidth = "95%"; // Ensure it fits on smaller screens
popupContainer.style.height = "60vh"; // Use viewport height to limit size
popupContainer.style.backgroundColor = "#fff";
popupContainer.style.border = "1px solid #ccc";
popupContainer.style.boxShadow = "0 4px 8px rgba(0, 0, 0, 0.2)";
popupContainer.style.borderRadius = "12px"; // Increased border radius for a smoother look
popupContainer.style.overflow = "hidden"; // Prevent content overflow
popupContainer.style.fontFamily =
  "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif"; // Apply a system font
popupContainer.style.zIndex = "1000";
popupContainer.style.display = "flex";
popupContainer.style.flexDirection = "column";


// Create header for title (fixed position)
const popupHeader = document.createElement("div");
popupHeader.style.padding = "16px 24px";
popupHeader.style.borderBottom = "1px solid #ddd"; // Separate the title visually
popupHeader.style.backgroundColor = "#fff";
popupHeader.style.zIndex = "10"; // Ensure it appears above the scrollable content

// Popup title
const popupTitle = document.createElement("h2");
popupTitle.textContent = title;
popupTitle.style.paddingLeft = "15px"; // Move the title slightly to the right
popupTitle.style.fontSize = "20px";
popupTitle.style.color = "#333";
popupTitle.style.textAlign = "left";
popupHeader.appendChild(popupTitle);



// Content wrapper (flex layout)
const contentWrapper = document.createElement("div");
contentWrapper.style.display = "flex";
contentWrapper.style.flexDirection = "column";
contentWrapper.style.flex = "1"; // Automatically take up available space
contentWrapper.style.overflow = "hidden"; // Prevent content overflow

// Content box (with fixed preview label)
const contentBox = document.createElement("div");
contentBox.style.flex = "1";
contentBox.style.border = "1px solid #ddd";
contentBox.style.borderRadius = "8px";
contentBox.style.backgroundColor = "#f9f9f9";
contentBox.style.padding = "16px";
contentBox.style.margin = "16px 16px"; // Add vertical spacing
contentBox.style.overflow = "hidden"; // Prevent outer scrolling
contentBox.style.marginBottom = "75px"; // Add enough space for the close button


// Preview label and line (sticky inside content box)
const previewLabelContainer = document.createElement("div");
previewLabelContainer.style.position = "sticky"; // Fix inside the content box
previewLabelContainer.style.top = "0"; // Stick to the top
previewLabelContainer.style.backgroundColor = "#f9f9f9"; // Match the content box background
previewLabelContainer.style.zIndex = "1";
previewLabelContainer.style.padding = "8px 0";

const previewLabel = document.createElement("p");
previewLabel.textContent = "Preview"; // Label text
previewLabel.style.fontSize = "16px";
previewLabel.style.fontWeight = "500";
previewLabel.style.color = "#92a2b1";
previewLabel.style.margin = "0";

const lineBelowLabel = document.createElement("hr");
lineBelowLabel.style.border = "none";
lineBelowLabel.style.borderTop = "1px solid #ddd";
lineBelowLabel.style.margin = "8px 0";

previewLabelContainer.appendChild(previewLabel);
previewLabelContainer.appendChild(lineBelowLabel);

// Scrollable content area
const scrollableContent = document.createElement("div");
scrollableContent.style.overflowY = "auto"; // Enable vertical scrolling
scrollableContent.style.height = "calc(100% - 40px)"; // Adjust to fit within the content box



  const eventText = document.createElement("div");
  eventText.style.marginBottom = "12px";
  const createCustomBullet = (text, bulletColor, highlightColor) => {
    const listItem = document.createElement("li");
    listItem.style.position = "relative"; // For positioning the custom bullet
    listItem.style.paddingLeft = "10px"; // Space for custom bullet
  
    // Create the custom double circular bullet using a span element
    const bullet = document.createElement("span");
    bullet.style.position = "absolute";
    bullet.style.left = "-15px"; // Bring the bullet closer to the text
    bullet.style.top = "50%"; // Center the bullet vertically
    bullet.style.transform = "translateY(-50%)"; // Center the bullet exactly
    bullet.style.width = "12px"; // Outer ring size
    bullet.style.height = "12px";
    bullet.style.border = `4px solid ${bulletColor || "#dcdfe1"}`; // Outer ring color and border size
    bullet.style.borderRadius = "50%"; // Make it a ring (circle with border)
    bullet.style.display = "inline-block";
  
    // Create the inner circle (smaller circle inside the outer ring)
    const innerBullet = document.createElement("span");
    innerBullet.style.position = "absolute";
    innerBullet.style.left = "50%";
    innerBullet.style.top = "50%";
    innerBullet.style.transform = "translate(-50%, -50%)"; // Centering the inner circle
    innerBullet.style.width = "2px"; // Inner circle size
    innerBullet.style.height = "2px";
    innerBullet.style.borderRadius = "50%"; // Inner circle rounded
    innerBullet.style.display = "inline-block";
  
    // Append the inner circle to the outer circle (bullet)
    bullet.appendChild(innerBullet);
  
    // Split the text into words
    const words = text.split(" ");
    
    // Extract specific words
    const firstWord = words.shift(); // Remove first word
    const secondWord = words.shift(); // Remove second word
    const lastWord = words.pop(); // Extract last word
    const remainingText = words.join(" "); // Remaining words (excluding first, second, and last)
  
    // Construct the innerHTML with the second word in black and the last word in highlight color
    listItem.innerHTML = `
      <span>${firstWord}</span> 
      <span style="color: black; font-weight: 500;">${secondWord}</span> 
      ${remainingText} 
      <span style="color: ${highlightColor}; font-weight: 500;">${lastWord}</span>
    `;
  
    // Append the custom double circular bullet to the list item
    listItem.insertBefore(bullet, listItem.firstChild);
  
    return listItem;
  };
  

  
  // Create the heading "Event:"
  const eventLabel = document.createElement("p");
  eventLabel.textContent = "Event";
  eventLabel.style.margin = "0";
  eventLabel.style.color = "#00a886"; // Blue color for heading
  eventLabel.style.fontWeight = "bold";
  eventLabel.style.fontSize = "16px";

  // Create the unordered list for the event details
  const eventDetail = document.createElement("ul");
  eventDetail.style.margin = "8px 0 0 -15px"; // Add margin and indentation
  eventDetail.style.color = "#333"; // Normal color for text
  eventDetail.style.listStyleType = "none"; // Remove default bullets
  eventDetail.style.fontSize = "14px";
 
  if (Number(automation_type_id) === 1){
  const eventBullet = createCustomBullet(
    "When Ticket is Created", // Text content
    "#2c5cc5", // Bullet color
    "#00a886" // Highlight color for the last word
  );
  eventDetail.appendChild(eventBullet);
  
  // Append the heading and the event detail to the container
  eventText.appendChild(eventLabel);
  eventText.appendChild(eventDetail);

  }

  const createCustomBullet1 = (text, bulletColor, highlightColor) => {
    const listItem = document.createElement("li");
    listItem.style.position = "relative"; // For positioning the custom bullet
    listItem.style.paddingLeft = "10px"; // Space for custom bullet
  
    // Create the custom double circular bullet using a span element
    const bullet = document.createElement("span");
    bullet.style.position = "absolute";
    bullet.style.left = "-15px"; // Bring the bullet closer to the text
    bullet.style.top = "50%"; // Center the bullet vertically
    bullet.style.transform = "translateY(-50%)"; // Center the bullet exactly
    bullet.style.width = "12px"; // Outer ring size
    bullet.style.height = "12px";
    bullet.style.border = `4px solid ${bulletColor || "#dcdfe1"}`; // Outer ring color and border size
    bullet.style.borderRadius = "50%"; // Make it a ring (circle with border)
    bullet.style.display = "inline-block";
  
    // Create the inner circle (smaller circle inside the outer ring)
    const innerBullet = document.createElement("span");
    innerBullet.style.position = "absolute";
    innerBullet.style.left = "50%";
    innerBullet.style.top = "50%";
    innerBullet.style.transform = "translate(-50%, -50%)"; // Centering the inner circle
    innerBullet.style.width = "2px"; // Inner circle size
    innerBullet.style.height = "2px";
    innerBullet.style.borderRadius = "50%"; // Inner circle rounded
    innerBullet.style.display = "inline-block";
  
    // Append the inner circle to the outer circle (bullet)
    bullet.appendChild(innerBullet);
  
    // Split the text into words
    const words = text.split(" ");
    
    // Extract specific words
    const firstWord = words.shift(); // Remove first word
    const secondWord = words.shift(); // Remove second word
    const lastFourWords = words.splice(-4).join(" "); // Get last four words
    const remainingText = words.join(" "); // Remaining words (excluding first, second, and last four)
  
    // Construct the innerHTML with the second word in black and the last four words in highlight color
    listItem.innerHTML = `
      <span>${firstWord}</span> 
      <span style="color: black; font-weight: 500;">${secondWord}</span> 
      ${remainingText} 
      <span style="color: ${highlightColor}; font-weight: 500;">${lastFourWords}</span>
    `;
  
    // Append the custom double circular bullet to the list item
    listItem.insertBefore(bullet, listItem.firstChild);
  
    return listItem;
  };
  

  
  if (Number(automation_type_id) === 3){
    const eventBullet = createCustomBullet1(
      "When Ticket is is checked every hour", // Text content
      "#2c5cc5", // Bullet color
      "#00a886" // Highlight color for the last word
    );
    eventDetail.appendChild(eventBullet);
    
    // Append the heading and the event detail to the container
    eventText.appendChild(eventLabel);
    eventText.appendChild(eventDetail);
  
    }
  // Create the conditions heading
  const conditionText = document.createElement("div");
  conditionText.textContent = "Condition";
  conditionText.style.marginBottom = "8px";
  conditionText.style.fontWeight = "bold";
  conditionText.style.color = "#e86f25"; // Green color for conditions heading
  conditionText.style.fontSize = "16px";
  
  // Create a container for the conditions list
  const conditionsList = document.createElement("ul");
  conditionsList.style.margin = "0 0 12px";
  conditionsList.style.padding = "8px";
  conditionsList.style.border = "1px solid #ddd";
  conditionsList.style.borderRadius = "4px";
  conditionsList.style.backgroundColor = "#fff";
  conditionsList.style.listStyleType = "none"; // Remove default bullet style
  conditionsList.style.fontSize = "14px";
  
 // Extract condition sets and operator
const conditionsArray1 = Array.isArray(content.conditions.condition_set_1)
? content.conditions.condition_set_1
: [];
const conditionsArray2 = Array.isArray(content.conditions.condition_set_2)
? content.conditions.condition_set_2
: [];
const operator = content.conditions.operator || "";




// Function to create a styled bullet point for conditions/actions
const createConditionBullet = (condition, bulletColor = "#dcdfe1") => {
  


  const listItem = document.createElement("li");
  listItem.style.position = "relative";
  listItem.style.paddingLeft = "30px"; // Space for bullet
  listItem.style.display = "flex"; // Prevents breaking lines
  listItem.style.alignItems = "center"; // Keeps elements aligned

  // Create custom bullet
  const bullet = document.createElement("span");
  bullet.style.position = "absolute";
  bullet.style.left = "0";
  bullet.style.top = "50%";
  bullet.style.transform = "translateY(-50%)";
  bullet.style.width = "12px";
  bullet.style.height = "12px";
  bullet.style.border = `4px solid ${bulletColor || "#dcdfe1"}`;
  bullet.style.borderRadius = "50%";

  // Inner circle of bullet
  const innerBullet = document.createElement("span");
  innerBullet.style.position = "absolute";
  innerBullet.style.left = "50%";
  innerBullet.style.top = "50%";
  innerBullet.style.transform = "translate(-50%, -50%)";
  innerBullet.style.width = "8px";
  innerBullet.style.height = "8px";
  innerBullet.style.borderRadius = "50%";

  bullet.appendChild(innerBullet);

  // **Formatting Condition with Colors**
  let formattedCondition = condition
    .replace(/<div/g, ' <div') // Add space before <div> tags if missing
    .replace(/<div\s+class\s*=\s*["']?SummaryKey["']?\s*>(.*?)<\/div>/gi, ' <span style="color: black; font-weight: 500;">$1</span> ') 
    .replace(/<div\s+class\s*=\s*["']?SummaryValue["']?\s*>(.*?)<\/div>/gi, ' <span style="color: #00a886; font-weight: 500;">$1</span> ') 
    .replace(/<div\s+class\s*=\s*["']?SummaryOperator["']?\s*>(.*?)<\/div>/gi, ' <span> $1 </span> ') // Ensure space around operators
    .replace(/>\s+</g, '> <')  // Ensures space between inline elements
    .replace(/\s+/g, ' ')      // Remove multiple spaces
    .trim();                   // Trim any leading/trailing spaces

 

  // // Set bullet first, then append formatted text
  listItem.appendChild(bullet);
  
  // Create a span for the condition text (for proper spacing)
  const textSpan = document.createElement("span");
  textSpan.innerHTML = formattedCondition;
  textSpan.style.marginLeft = "-5px"; // Ensure space between bullet and text
  listItem.appendChild(textSpan);

  console.log("✅ Final List Item InnerHTML:", listItem.innerHTML); // Log final output

  return listItem;
};


// Add conditions from condition_set_1
conditionsArray1.forEach((condition) => {
if (condition === "AND" || condition === "OR") {
  // Add operator as a separate text element
  const operatorItem = document.createElement("div");
  operatorItem.textContent = condition;
  operatorItem.style.color = "#6c757d";
  operatorItem.style.margin = "8px 0 5px 29px";
  conditionsList.appendChild(operatorItem);
} else {
  conditionsList.appendChild(createConditionBullet(condition, "#2c5cc5")); // Blue bullet
}
});

// Add operator between conditions (if available)
if (operator) {
const operatorItem = document.createElement("div");
operatorItem.textContent = operator;
operatorItem.style.color = "#000000";
operatorItem.style.margin = "8px 0";
operatorItem.style.fontSize = "14px";
operatorItem.style.fontweight="bold"
conditionsList.appendChild(operatorItem);
}

// Add conditions from condition_set_2
conditionsArray2.forEach((condition) => {
if (condition === "AND" || condition === "OR") {
  const operatorItem = document.createElement("div");
  operatorItem.textContent = condition;
  operatorItem.style.color = "#6c757d";
  operatorItem.style.margin = "8px 0 5px 29px";
  conditionsList.appendChild(operatorItem);
} else {
  conditionsList.appendChild(createConditionBullet(condition, "#2c5cc5")); // Blue bullet
}
});

// Create actions heading
const actionText = document.createElement("div");
actionText.textContent = "Action";
actionText.style.marginBottom = "8px";
actionText.style.fontWeight = "bold";
actionText.style.color = "#2c5cc5";
actionText.style.fontSize = "16px";

// Create actions content
const actionContent = document.createElement("ul");
actionContent.style.margin = "0";
actionContent.style.padding = "8px";
actionContent.style.border = "1px solid #ddd";
actionContent.style.borderRadius = "4px";
actionContent.style.backgroundColor = "#fff";
actionContent.style.listStyleType = "none";
actionContent.style.fontSize = "14px";

const actionsArray = Array.isArray(content.actions) ? content.actions : [];

// Add actions with custom bullets
actionsArray.forEach((action) => {
if (action === "AND" || action === "OR") {
  const operatorItem = document.createElement("div");
  operatorItem.textContent = action;
  operatorItem.style.color = "#6c757d";
  operatorItem.style.margin = "8px 0 5px 29px";
  actionContent.appendChild(operatorItem);
} else {
  actionContent.appendChild(createConditionBullet(action, "#2c5cc5")); // Blue bullet for actions
}
});
  
  // Append the label and line to the content box
  contentBox.appendChild(previewLabel);
  contentBox.appendChild(lineBelowLabel);
  
  scrollableContent.appendChild(eventText);
  scrollableContent.appendChild(conditionText);
  scrollableContent.appendChild(conditionsList);
  scrollableContent.appendChild(actionText);
  scrollableContent.appendChild(actionContent);
  
  // Append content to the scrollable wrapper
  
  contentBox.appendChild(scrollableContent);
  
  // Create fw-button element with "primary" color
  const closeButton = document.createElement("fw-button");
  closeButton.setAttribute("color", "primary");
  closeButton.textContent = "Close";
  closeButton.style.position = "absolute";
  closeButton.style.bottom = "16px"; // Distance from the bottom
  closeButton.style.right = "16px"; // Distance from the right
  closeButton.style.padding = "8px 16px"; // Padding for the button
  closeButton.style.borderRadius = "4px"; // Rounded corners
  closeButton.style.cursor = "pointer";
  
  // Close popup and remove overlay when the button is clicked
  closeButton.addEventListener("click", () => {
    document.body.removeChild(popupContainer);
    document.body.removeChild(overlay);
  });
  
  popupContainer.appendChild(popupHeader); // Fixed title
  popupContainer.appendChild(contentBox);
  
  popupContainer.appendChild(closeButton); // Close button
  
  // Append elements to the document
  document.body.appendChild(overlay);
  document.body.appendChild(popupContainer);
  
  }





let currentPage = 1;
const itemsPerPage = 5;

function normalizeText2(text) {
  return text
    .toLowerCase()
    .replace(/[.,\/#!$%\^&\*;:{}=\-_`~()]/g, "") // Remove punctuation
    .split(/\s+/) // Split words
    .sort() // Sort for consistency
    .join(" "); // Rejoin sorted words
}

function normalizeList(text) {
  return text
    ? text
        .split(",") // Convert to array
        .map((item) => item.trim().toLowerCase()) // Trim & lowercase
        .sort() // Sort to ensure same order
        .join(",") // Join back to a string
    : "";
}
function stripHTML2(htmlString) {
  // Create a temporary div to parse the HTML
  const div = document.createElement("div");
  div.innerHTML = htmlString;

  // Remove all elements except <img>
  [...div.querySelectorAll("*")].forEach(el => {
      if (el.tagName.toLowerCase() !== "img") {
          el.replaceWith(...el.childNodes);
      }
  });

  return div.innerHTML.trim(); // Return cleaned HTML
}
function removeImgTags(htmlString) {
return htmlString.replace(/<img\b[^>]*>/g, "").trim();
}

function displayGroupedRules(records, containerId) {
  const container = document.getElementById(containerId);
  if (!container) {
    console.error(`Container with ID "${containerId}" not found.`);
    return;
  }

  container.innerHTML = ""; // Clear container
  if (records.length === 0) {
    container.innerHTML = `
        <div style="
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            width: 100%;
            font-size: 24px;
            font-weight: bold;
            color: #333;
            margin-left: 400px; 
            text-align: center;
        ">
            No duplicate rules found.
        </div>`;
    return;
  }

  const groupedRules = new Map();

  records.forEach((record) => {
    const { data, display_id } = record;
    const { name, summary, position, updated_at, last_updated_by, affected_tickets_count, rule_id, automation_type_id, conditions, actions,agentName
    } = data;
  
    if (summary) {
      // console.log(`🔍 Original Summary: ${summary}`);
  
      // **Remove all HTML except <img> for display, but remove <img> for grouping**
      const cleanSummary = stripHTML2(summary);
  
      // **Ensure `actions` is a string before removing <img> tags**
      const actionsText = Array.isArray(actions) ? actions.join(" ") : String(actions || ""); 
      const cleanedActions = removeImgTags(actionsText); // Remove <img> from actions
  
      // console.log(`✅ Cleaned Summary: ${cleanSummary}`);
      // console.log(`🖼️ Actions without <img>: ${cleanedActions}`); // Log cleaned actions
  
      const normalizedSummary = normalizeText2(cleanSummary);
      const normalizedConditions = normalizeList(conditions);
      const normalizedActions = normalizeList(cleanedActions); // Use cleaned actions
  
      // **Generate Group Key (WITHOUT <img> tags)**
      const groupKey = `${normalizedSummary}|${normalizedConditions}|${normalizedActions}`;
  
      // console.log(`📌 Group Key: ${groupKey}`);
  
      if (!groupedRules.has(groupKey)) {
        groupedRules.set(groupKey, { originalSummary: cleanSummary, rules: [] });
      }
  
      groupedRules.get(groupKey).rules.push({
        name,
        position,
        summary,
        updated_at,
        last_updated_by,
        affected_tickets_count,
        rule_id,
        automation_type_id,
        display_id,
        agentName
      });
    }
  });    
  
  const groupedRulesArray = Array.from(groupedRules.values());
  const totalgroup = groupedRulesArray.length;
  console.log(totalgroup, "*********************");

  const totalPages = Math.ceil(totalgroup / itemsPerPage);
  currentPage = Math.max(1, Math.min(currentPage, totalPages)); // Ensure valid page number

  console.log("Total Pages:", totalPages, "Current Page:", currentPage);

  const startIdx = (currentPage - 1) * itemsPerPage;
  const paginatedRules = groupedRulesArray.slice(startIdx, startIdx + itemsPerPage);

  console.log("Displaying Records:", paginatedRules);

  let arrayLength = paginatedRules.length;
  console.log("Records Length:", arrayLength);

  // Display paginated rules
  paginatedRules.forEach((group) => {
    const rulesCount = group.rules.length;

    
    if (rulesCount === 1) {
        console.log(`Skipping group with only 1 rule: ${group.originalSummary}`);
        return; 
    }

    const groupContainer = document.createElement("div");
    groupContainer.style.border = "1px solid #ccc";
    groupContainer.style.padding = "16px";
    groupContainer.style.margin = "16px";
    groupContainer.style.borderRadius = "8px";
    groupContainer.style.backgroundColor = "#f5f7f9";
    groupContainer.style.width = "1200px";

    

    // ✅ Correctly loop through the rules array inside the group object
    group.rules.forEach(({ name, position, summary, updated_at, affected_tickets_count, display_id, rule_id, automation_type_id,agentName }, index) => {
      const card = document.createElement("div");
    card.style.border = "1px solid #ccc";
    card.style.padding = "16px";
    card.style.margin = "8px 0"
    card.style.fontFamily =
      "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif";
    card.style.borderRadius = "8px";
    card.style.backgroundColor = index === 0 ? "#fff" : "#e5f2fd";
    card.style.marginBottom = "10px";
    card.style.paddingBottom = "0";
   
   
      const cardHeader = document.createElement("div");
      cardHeader.style.display = "flex";
      cardHeader.style.justifyContent = "space-between";
      cardHeader.style.alignItems = "center";
      
      // Create a wrapper for the title
const cardTitle = document.createElement("h4");
cardTitle.style.margin = "0";
cardTitle.style.cursor = "pointer";
cardTitle.style.fontSize = "14px";
cardTitle.style.fontFamily = "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif";
cardTitle.style.color = "#183247";
cardTitle.style.transition = "color 0.2s ease";
cardTitle.style.fontWeight = "600"; 

// Create the serial number (position)
if (position) {
    const serialNumber = document.createElement("span");
    serialNumber.textContent = position + ". ";
    serialNumber.style.color = "#183247"; // Keep serial number color fixed
    cardTitle.appendChild(serialNumber);
}

// Create the actual name (clickable part)
const titleText = document.createElement("span");
titleText.textContent = name;
titleText.style.color = "#183247"; 
titleText.style.transition = "color 0.2s ease";

// Add hover effect for only the name
titleText.addEventListener("mouseover", () => {
    titleText.style.color = "#007bff"; // Change only name color on hover
});
titleText.addEventListener("mouseout", () => {
    titleText.style.color = "#183247"; // Reset name color when not hovering
});
titleText.addEventListener("click", () => {
    titleText.style.color = "#ff5733"; // Change title color on click
   

    
    // let ruleid=rule_id;
    console.log("ruleid",rule_id);
    // let automationid= automation_type_id;
    console.log("automationtypeid",automation_type_id);
    GetRules();
    async function GetRules() {
      //  console.log('GetRules called');
       try {
           const GetRulesResponse = await client.request.invokeTemplate("getid", {
               context: 
               { 
                ruleid: rule_id ,
                automationid:automation_type_id
               },
           });
   
           const responses = GetRulesResponse.response;
           const rulesData = JSON.parse(responses);
           console.log("Rules", rulesData);
           console.log("Rules", rulesData.summary.conditions);
           console.log("Rules", rulesData.summary.actions);
           if(automation_type_id === 1||automation_type_id === 3)
        {
           showPopupCard(rulesData.name, { conditions: rulesData.summary.conditions, actions:rulesData.summary.actions },automation_type_id);
      }else{
        showPopupCard1(rulesData.name, {performer:rulesData.summary.performer,events:rulesData.summary.events, conditions: rulesData.summary.conditions, actions:rulesData.summary.actions });
      }
    }
      catch (error) {
        console.error("Error in getting rules",error);
         
         }
    }
   

});

// Append name to title
cardTitle.appendChild(titleText);




      // Append title and actions to the cardHeader
      cardHeader.appendChild(cardTitle);
      // Create a container for the horizontal line and the gap
const cardContainer = document.createElement("div");

// Style the container to have a background color in the gap
cardContainer.style.backgroundColor = "#f0f0f0";  // Set the background color for the gap (change to desired color)
cardContainer.style.paddingBottom = "20px";  
cardContainer.style.marginLeft="-15px";
cardContainer.style.borderRadius = "4px";
cardContainer.style.width="102.7%";

// Create a horizontal line after the cardBody
const horizontalLine = document.createElement("div");
horizontalLine.style.height = "1px"; // Set the height to 1px for a thin line
horizontalLine.style.backgroundColor = "#ccc"; // Set the color of the horizontal line
horizontalLine.style.marginTop = "16px"; // Add space above the line (adjust as needed)
horizontalLine.style.width = "100%"; // Ensure the line stretches the full width of the container
horizontalLine.style.marginLeft="-3px";
      

      function truncateContent(content, maxLength, lines) {
        // Truncate the content to the desired number of characters
        let truncated = content;
      
        // Adjust for the desired line count and maximum length
        if (content.length > maxLength) {
          truncated = content.slice(0, maxLength) + "...";
        }
      
        // Break content into lines manually for multi-line truncation
        const words = truncated.split(" ");
        const result = [];
        let line = "";
        let currentLine = 1;
      
        for (let i = 0; i < words.length; i++) {
          if (line.length + words[i].length + 1 <= maxLength / lines) {
            line += (line ? " " : "") + words[i];
          } else {
            result.push(line);
            line = words[i];
            currentLine++;
            if (currentLine > lines) break; // Stop adding more lines if max lines are reached
          }
        }
      
        if (currentLine <= lines && line) {
          result.push(line);
        }
      
        return result.join(" ") + (currentLine > lines ? "..." : "");
      }
      function calculateLastModified(updated_at) {
        const updatedDate = new Date(updated_at);
        const currentDate = new Date();
    
        const diffInMilliseconds = currentDate - updatedDate;
        const seconds = Math.floor(diffInMilliseconds / 1000);
        const minutes = Math.floor(seconds / 60);
        const hours = Math.floor(minutes / 60);
        const days = Math.floor(hours / 24);
        const months = Math.floor(days / 30);  // Approximate months
        const years = Math.floor(days / 365);  // Approximate years
    
        if (years > 0) {
            return years === 1 ? "a year ago" : `${years} years ago`;
        } else if (months > 0) {
            return months === 1 ? "a month ago" : `${months} months ago`;
        } else if (days > 0) {
            return `${days} day${days > 1 ? "s" : ""} ago`;
        } else if (hours > 0) {
            return `${hours} hour${hours > 1 ? "s" : ""} ago`;
        } else if (minutes > 0) {
            return `${minutes} minute${minutes > 1 ? "s" : ""} ago`;
        } else {
            return "Just now";
        }
    }
    
    
      
      
      // console.log("updated at",calculateLastModified(updated_at));
      
 // Create a row for "Last Modified"
 const lastModifiedRow = document.createElement("div");
 lastModifiedRow.style.display = "grid";
 lastModifiedRow.style.gridTemplateColumns = "150px 150px 2px 150px 150px 2px 150px 150px"; // Consistent width for each section
 lastModifiedRow.style.alignItems = "center";
 lastModifiedRow.style.marginTop = "10px";
 lastModifiedRow.style.fontSize = "12px";
 lastModifiedRow.style.gap = "20px";
 lastModifiedRow.style.width = "100%"; // Ensures full width alignment
 
 const lastModifiedLabel = document.createElement("span");
 lastModifiedLabel.textContent = "Last Modified :";
 lastModifiedLabel.style.color = "#183247";
 lastModifiedLabel.style.fontSize = "12px";
 lastModifiedLabel.style.display = "inline-flex";
lastModifiedLabel.style.fontFamily =" -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif"
lastModifiedLabel.style.marginLeft = "40px"

 const lastModifiedValue = document.createElement("span");
 const lastModifiedText = calculateLastModified(updated_at);
 lastModifiedValue.textContent = lastModifiedText;
 lastModifiedValue.style.color = "#183247";
 lastModifiedValue.style.fontWeight = "600";
 lastModifiedValue.style.display = "inline-flex";
 lastModifiedValue.style.fontSize = "12px";
 lastModifiedValue.style.marginLeft = "-50px"
 lastModifiedValue.style.justifySelf = "start";
 lastModifiedValue.style.fontFamily =" -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif"

 const verticalLine = document.createElement("div");
 verticalLine.style.height = "20px";
 verticalLine.style.borderLeft = "2px solid #ccc";
 verticalLine.style.alignSelf = "stretch";
 
 lastModifiedRow.appendChild(lastModifiedLabel);
 lastModifiedRow.appendChild(lastModifiedValue);
 lastModifiedRow.appendChild(verticalLine);
 
//  const agentsid = last_updated_by;
//  console.log("agentsid", agentsid);
//  GetAgents();
 
//  async function GetAgents() {
//     //  console.log('GetAgents called');
//      try {
//          const GetAgentsResponse = await client.request.invokeTemplate('getAgents', {
//              context: { id: agentsid },
//          });
 
//          const responses = GetAgentsResponse.response;
//          const agentData = JSON.parse(responses);
        //  console.log("Name:", agentData.contact.name);
 
         const agentNameLabel = document.createElement("span");
         agentNameLabel.textContent = "By :";
         agentNameLabel.style.fontSize = "12px";
         agentNameLabel.style.color = "#183247";
         agentNameLabel.style.whiteSpace = "nowrap";
         agentNameLabel.style.marginLeft="149px"
         agentNameLabel.style.fontFamily =" -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif"

         const agentNameValue = document.createElement("span");
         agentNameValue.textContent = agentName;
         agentNameValue.style.color = "#183247";
         agentNameValue.style.fontWeight = "600";
         agentNameValue.style.whiteSpace = "nowrap";
         agentNameValue.style.fontFamily =" -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif"
         const verticalLine2 = document.createElement("div");
         verticalLine2.style.height = "20px";
         verticalLine2.style.borderLeft = "2px solid #ccc";
         verticalLine2.style.alignSelf = "stretch";
         verticalLine2.style.marginLeft = "100px";  // Increase for more right shift

 
         lastModifiedRow.appendChild(agentNameLabel);
         lastModifiedRow.appendChild(agentNameValue);
         lastModifiedRow.appendChild(verticalLine2);
 
         const affectedTicketsLabel = document.createElement("span");
         affectedTicketsLabel.textContent = "Impacted tickets (Last 7 days) : ";
         affectedTicketsLabel.style.fontSize = "12px";
         affectedTicketsLabel.style.color = "#183247";
         affectedTicketsLabel.style.marginLeft="140px";
         affectedTicketsLabel.style.whiteSpace = "nowrap";
         affectedTicketsLabel.style.fontFamily =" -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif"

         const affectedTicketsValue = document.createElement("span");
         affectedTicketsValue.textContent = affected_tickets_count === 0 ? "--" : affected_tickets_count;
         affectedTicketsValue.style.color = "#183247";
         affectedTicketsValue.style.fontWeight = "600";
         affectedTicketsValue.style.marginLeft ="134px"
         affectedTicketsValue.style.whiteSpace = "nowrap";
         affectedTicketsValue.style.fontFamily =" -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif"

         lastModifiedRow.appendChild(affectedTicketsLabel);
         lastModifiedRow.appendChild(affectedTicketsValue);
    // }
    
//     catch (error) {
//       console.error("Agents error",error);
//       if (error.status === 429) {
//         console.warn("⚠️API limit exceeded. App will reload 1 minute after");
//         document.getElementById("Automation-page").style.display = "none";
//         document.getElementById("Workflow-Automation-page").style.display = "none";
        
//         document.getElementById("no_user1").style.display = "block";
//       //   setTimeout(() => {
//       //     window.location.reload();
//       // }, 30000);
// }
// else if(error.status === 401){
//   document.getElementById("Automation-page").style.display = "none";
//   document.getElementById("Workflow-Automation-page").style.display = "none";
  
//   document.getElementById("no_user2").style.display = "block";

// } 
       
//        }
//   }







 
      const cardBody = document.createElement("div"); // Create a container for card content and actions
      cardBody.style.display = "flex"; // Flexbox to align items horizontally
      cardBody.style.justifyContent = "space-between"; // Ensure there's space between content and actions
      cardBody.style.alignItems = "flex-start"; // Align items to the top (optional, depending on your needs)
               

const truncatedContent = truncateContent(summary, 200, 2);

const cardContent = document.createElement("pre");
cardContent.textContent = truncatedContent;

// Style the card content
cardContent.style.marginTop = "8px";
cardContent.style.padding = "8px";
cardContent.style.color="#183247";
cardContent.style.fontweight="600";
cardContent.style.fontFamily= "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif";
cardContent.style.whiteSpace = "pre-wrap"; // Ensure text wraps
cardContent.style.overflow = "hidden"; // Hide overflow content
cardContent.style.textOverflow = "ellipsis"; // Add ellipsis for overflow
cardContent.style.maxWidth = "75%"; // Limit the card width to half the container's width
cardContent.style.fontSize="12px";
cardContent.style.marginLeft="15px";


     // Create the container for card actions
const cardActionsContainer = document.createElement("div");
cardActionsContainer.style.display = "flex"; // Display actions horizontally
cardActionsContainer.style.justifyContent = "flex-end"; // Align to the right
cardActionsContainer.style.marginTop = "10px"; // Add some spacing above the actions
cardActionsContainer.style.gap = "8px"; // Set space between the toggle and the delete icon



//       // Add fw-toggle
//       const fwToggle = document.createElement("fw-toggle");
//       fwToggle.setAttribute("size", "medium");
//       fwToggle.setAttribute("checked", "");
//       // Add event listener to handle state change
// fwToggle.addEventListener("fwChange", (event) => {
//   fwToggle.checked = event.detail.checked; // Keep the state as per user selection
//   console.log("Toggle state changed:", fwToggle.checked);
// });
// const fwToggle = document.createElement("fw-toggle");
// fwToggle.setAttribute("size", "medium");

// // Unique key for storing toggle state (Assuming each card has a unique rule ID)
// const ruleId = rule_id; // Ensure rule_id is unique per rule
// const storedState = localStorage.getItem(`toggleState_${ruleId}`);

// if (storedState !== null) {
//   fwToggle.checked = storedState === "true"; // Convert string to boolean
// } else {
//   fwToggle.setAttribute("checked", ""); // Default state
// }

// // Event listener to update localStorage on state change
// fwToggle.addEventListener("fwChange", (event) => {
//   const isChecked = event.detail.checked;
//   localStorage.setItem(`toggleState_${ruleId}`, isChecked);
//   fwToggle.checked = isChecked; // Ensure UI reflects stored state
//   console.log(`Toggle state changed for ${ruleId}:`, isChecked);
// });


        // Add fw-icon
        const fwIcon = document.createElement("fw-icon");
        fwIcon.setAttribute("name", "delete");
        fwIcon.setAttribute("size", "18");
        fwIcon.style.cursor = "pointer";
        fwIcon.style.color = "red"; // Set the color to red
        // Add a pointer cursor for interactivity
        fwIcon.title = "Delete";
        fwIcon.addEventListener("click", () => {
          console.log("ruleid inside entity deletion", rule_id);
         
      
          showDeletePopup(display_id); 
      
          function showDeletePopup(display_id) {
              currentRuleId = display_id; // Store the rule ID for deletion
              document.getElementById("deleteConfirmationPopup").style.display = "flex";
          }
      
          function hideDeletePopup() {
              document.getElementById("deleteConfirmationPopup").style.display = "none";
          }
      
          function removeDeletedRuleFromUI(display_id) {
              let ruleCard = document.querySelector(`[data-rule-id="${display_id}"]`);
              if (ruleCard) {
                  ruleCard.remove();
              }
          }
      
          
          async function confirmDeletion1(rule_id, automation_type_id) {
              console.log("📢 confirmDeletion1 function triggered with rule_id:", rule_id, "and automation_type_id:", automation_type_id);
      
              if (!rule_id || !automation_type_id) {
                  console.warn("⚠️ Missing rule_id or automation_type_id, aborting function.");
                  return;
              }
      
              try {
                  console.log("🚀 Sending request to delete rule...");
      
                  let getdeleteruleResponse1 = await client.request.invokeTemplate("deleterule", {
                      context: {
                          automationid: automation_type_id,
                          ruleid: rule_id,
                      },
                  });
      
                  console.log("✅ getdeleteruleResponse:", getdeleteruleResponse1);
      
                  if (getdeleteruleResponse1.status === 204) {
                      console.log("✅ Rule deleted successfully!");
                      hideDeletePopup();
                  } else {
                      console.warn("⚠️ Unexpected response:", getdeleteruleResponse1);
                  }
      
              } catch (error) {
                  console.error("❌ Error in confirmDeletion1:", error);
              }
          }
      
          async function entityconfirmDeletion() {
              if (!currentRuleId) return; // Ensure rule ID is available
      
              try {
                  console.log("Deleting rule with ID:", currentRuleId);
                  await newRulePloadDB5.delete(currentRuleId);
  
  
                  
              } catch (error) {
                  console.warn(` Error deleting record with Display ID ${currentRuleId}, but continuing...`);
                  const ruleIndex = records.findIndex(record => record.display_id === currentRuleId);
                if (ruleIndex !== -1) {
              records.splice(ruleIndex, 1);
               console.log(`✅ Rule ${currentRuleId} removed from records array.`);
                } else {
                 console.warn(`⚠️ Rule with display_id ${currentRuleId} not found in records array.`);
                 }
  
                  displayGroupedRules(records, containerId)
                   let toast = document.getElementById('type_toast');
                   toast.setAttribute('content', 'Rule deleted successfully');
                   toast.setAttribute('type', 'success');
                   toast.setAttribute('open', true);
       
                  
                   removeDeletedRuleFromUI(currentRuleId);
                   hideDeletePopup();
       
                   
                 
              }
          }
      
          // Attach event listeners
          document.getElementById("confirmDeleteBtn").addEventListener("click", async () => {
              try {
                  await confirmDeletion1(rule_id, automation_type_id); 
                  await entityconfirmDeletion(); 
      
              } catch (error) {
                  console.error("❌ Error in deletion process:", error);
              }
          });
      
          document.getElementById("cancelDeleteBtn").addEventListener("click", hideDeletePopup);
      });
      
  //   
      // Append fw-toggle and fw-icon to cardActions
      // cardActionsContainer.appendChild(fwToggle);

      cardActionsContainer.appendChild(fwIcon);
      card.appendChild(cardHeader);
      cardBody.appendChild(cardContent);
      cardBody.appendChild(cardActionsContainer);
      card.appendChild(cardBody);
      cardContainer.appendChild(horizontalLine);
      // card.appendChild(horizontalLine);
     
      cardContainer.appendChild(lastModifiedRow);
      card.appendChild(cardContainer)
      groupContainer.appendChild(card);
    });

    container.appendChild(groupContainer);
  });
  
  // Add pagination component
  addFwPagination(containerId,  records, totalgroup);
}


function addFwPagination(containerId, records, totalgroup) {
  console.log('Adding pagination to container:', containerId);

  let container = document.getElementById(containerId);

  if (!container) {
    console.warn(`Container with ID "${containerId}" not found.`);
    return;
  }

  if (totalgroup <= itemsPerPage) {
    console.log("Total records are less than or equal to items per page, skipping pagination.");
    return;
  }

  let existingPagination= container.querySelector("#fw-pagination-4");
  if (existingPagination) {
    existingPagination.remove(); // Remove old pagination if it exists
  }

  const pagination = document.createElement("fw-pagination");
  pagination.id = "fw-pagination-4";

  pagination.setAttribute("total", totalgroup);
  // pagination1.setAttribute("total", totalPages4 * arrayLength);

  // console.log("totalpages",totalPages4 * arrayLength)
  pagination.setAttribute("per-page", itemsPerPage);
  pagination.setAttribute("page", currentPage);

  console.log("Pagination Element:", pagination);

  const paginationWrapper = document.createElement("div");
  paginationWrapper.style.display = "flex";
  paginationWrapper.style.justifyContent = "flex-start";
  paginationWrapper.style.alignItems = "center";
  paginationWrapper.style.width = "100%";
  paginationWrapper.style.marginLeft = "70%";

  paginationWrapper.appendChild(pagination);
  container.appendChild(paginationWrapper);

  pagination.addEventListener("fwChange", (event) => {
    console.log("fwChange Event Triggered", event);
    currentPage = event.detail.page;
    console.log("Updated Page:", currentPage);

   // Update the displayed rules for the current container
   displayGroupedRules(records, containerId);


  });
}

 
function showPopupCard1(title, content) {
  console.log("logPopup" ,content);
  const overlay = document.createElement("div");
  overlay.style.position = "fixed";
  overlay.style.top = "0";
  overlay.style.left = "0";
  overlay.style.width = "100%";
  overlay.style.height = "100%";
  overlay.style.backgroundColor = "rgba(0, 0, 0, 0.3)"; // Semi-transparent dark background
  overlay.style.backdropFilter = "blur(5px)"; // Apply blur effect
  overlay.style.zIndex = "999"; // Ensure it appears above everything else
  
  // Create popup container
  const popupContainer = document.createElement("div");
  popupContainer.style.position = "fixed";
  popupContainer.style.top = "50%";
  popupContainer.style.left = "50%";
  popupContainer.style.transform = "translate(-50%, -50%)";
  popupContainer.style.width = "1000px"; // Increased default width
  popupContainer.style.maxWidth = "95%"; // Ensure it fits on smaller screens
  popupContainer.style.height = "60vh"; // Use viewport height to limit size
  popupContainer.style.backgroundColor = "#fff";
  popupContainer.style.border = "1px solid #ccc";
  popupContainer.style.boxShadow = "0 4px 8px rgba(0, 0, 0, 0.2)";
  popupContainer.style.borderRadius = "12px"; // Increased border radius for a smoother look
  popupContainer.style.overflow = "hidden"; // Prevent content overflow
  popupContainer.style.fontFamily =
    "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif"; // Apply a system font
  popupContainer.style.zIndex = "1000";
  popupContainer.style.display = "flex";
  popupContainer.style.flexDirection = "column";
  
  
  // Create header for title (fixed position)
  const popupHeader = document.createElement("div");
  popupHeader.style.padding = "16px 24px";
  popupHeader.style.borderBottom = "1px solid #ddd"; // Separate the title visually
  popupHeader.style.backgroundColor = "#fff";
  popupHeader.style.zIndex = "10"; // Ensure it appears above the scrollable content
  
  // Popup title
  const popupTitle = document.createElement("h2");
  popupTitle.textContent = title;
  popupTitle.style.paddingLeft = "15px"; // Move the title slightly to the right
  popupTitle.style.fontSize = "20px";
  popupTitle.style.color = "#333";
  popupTitle.style.textAlign = "left";
  popupHeader.appendChild(popupTitle);
  
  
  
  // Content wrapper (flex layout)
  const contentWrapper = document.createElement("div");
  contentWrapper.style.display = "flex";
  contentWrapper.style.flexDirection = "column";
  contentWrapper.style.flex = "1"; // Automatically take up available space
  contentWrapper.style.overflow = "hidden"; // Prevent content overflow
  
  // Content box (with fixed preview label)
  const contentBox = document.createElement("div");
  contentBox.style.flex = "1";
  contentBox.style.border = "1px solid #ddd";
  contentBox.style.borderRadius = "8px";
  contentBox.style.backgroundColor = "#f9f9f9";
  contentBox.style.padding = "16px";
  contentBox.style.margin = "16px 16px"; // Add vertical spacing
  contentBox.style.overflow = "hidden"; // Prevent outer scrolling
  contentBox.style.marginBottom = "75px"; // Add enough space for the close button
  
  
  // Preview label and line (sticky inside content box)
  const previewLabelContainer = document.createElement("div");
  previewLabelContainer.style.position = "sticky"; // Fix inside the content box
  previewLabelContainer.style.top = "0"; // Stick to the top
  previewLabelContainer.style.backgroundColor = "#f9f9f9"; // Match the content box background
  previewLabelContainer.style.zIndex = "1";
  previewLabelContainer.style.padding = "8px 0";
  
  const previewLabel = document.createElement("p");
  previewLabel.textContent = "Preview"; // Label text
  previewLabel.style.fontSize = "16px";
  previewLabel.style.fontWeight = "500";
  previewLabel.style.color = "#92a2b1";
  previewLabel.style.margin = "0";
  
  const lineBelowLabel = document.createElement("hr");
  lineBelowLabel.style.border = "none";
  lineBelowLabel.style.borderTop = "1px solid #ddd";
  lineBelowLabel.style.margin = "8px 0";
  
  previewLabelContainer.appendChild(previewLabel);
  previewLabelContainer.appendChild(lineBelowLabel);
  
  // Scrollable content area
  const scrollableContent = document.createElement("div");
  scrollableContent.style.overflowY = "auto"; // Enable vertical scrolling
  scrollableContent.style.height = "calc(100% - 40px)"; // Adjust to fit within the content box
  
  
  
    const eventText = document.createElement("div");
    eventText.style.marginBottom = "12px";
    
    const createCustomBullet = (text, bulletColor, highlightColor) => {
      const listItem = document.createElement("li");
      listItem.style.position = "relative"; // For positioning the custom bullet
      listItem.style.paddingLeft = "10px"; // Space for custom bullet
    
      // Create the custom double circular bullet using a span element
      const bullet = document.createElement("span");
      bullet.style.position = "absolute";
      bullet.style.left = "-15px"; // Bring the bullet closer to the text (adjust this value)
      bullet.style.top = "50%"; // Center the bullet vertically
      bullet.style.transform = "translateY(-50%)"; // Center the bullet exactly
      bullet.style.width = "12px"; // Outer ring size
      bullet.style.height = "12px";
      bullet.style.border = `4px solid ${bulletColor || "#dcdfe1"}`; // Outer ring color and border size
      bullet.style.borderRadius = "50%"; // Make it a ring (circle with border)
      bullet.style.display = "inline-block";
    
      // Create the inner circle (smaller circle inside the outer ring)
      const innerBullet = document.createElement("span");
      innerBullet.style.position = "absolute";
      innerBullet.style.left = "50%";
      innerBullet.style.top = "50%";
      innerBullet.style.transform = "translate(-50%, -50%)"; // Centering the inner circle
      innerBullet.style.width = "2px"; // Inner circle size
      innerBullet.style.height = "2px";
      // innerBullet.style.backgroundColor = bulletColor || "#dcdfe1"; // Inner circle color
      innerBullet.style.borderRadius = "50%"; // Inner circle rounded
      innerBullet.style.display = "inline-block";
    
      // Append the inner circle to the outer circle (bullet)
      bullet.appendChild(innerBullet);
   // Split the text into words
   const words = text.split(" ");
      
   // Extract specific words
   const firstWord = words.shift(); // Remove first word
   const secondWord = words.shift(); // Remove second word
   const lastWord = words.pop(); // Extract last word
   const remainingText = words.join(" "); // Remaining words (excluding first, second, and last)
 
   // Construct the innerHTML with the second word in black and the last word in highlight color
   listItem.innerHTML = `
     <span>${firstWord}</span> 
     <span style="color: black; font-weight: 500;">${secondWord}</span> 
     ${remainingText} 
     <span style="color: ${highlightColor}; font-weight: 500;">${lastWord}</span>
   `;
 
   // Append the custom double circular bullet to the list item
   listItem.insertBefore(bullet, listItem.firstChild);
 
   return listItem;
  
    };
    
    // Function to remove HTML tags while preserving spaces
// const stripHTMLWithSpacing = (htmlString) => {
//   const tempElement = document.createElement("div");
//   tempElement.innerHTML = htmlString;
//   return tempElement.textContent.replace(/\s+/g, ' ').trim(); // Ensure proper spacing
// };

   // Function to create a styled bullet point for conditions/actions
const createConditionBullet = (condition, bulletColor = "#dcdfe1") => {
  // console.log("🔹 Original Condition:", condition); // Log initial condition


  const listItem = document.createElement("li");
  listItem.style.position = "relative";
  listItem.style.paddingLeft = "30px"; // Space for bullet
  listItem.style.display = "flex"; // Prevents breaking lines
  listItem.style.alignItems = "center"; // Keeps elements aligned

  // Create custom bullet
  const bullet = document.createElement("span");
  bullet.style.position = "absolute";
  bullet.style.left = "0";
  bullet.style.top = "50%";
  bullet.style.transform = "translateY(-50%)";
  bullet.style.width = "12px";
  bullet.style.height = "12px";
  bullet.style.border = `4px solid ${bulletColor || "#dcdfe1"}`;
  bullet.style.borderRadius = "50%";

  // Inner circle of bullet
  const innerBullet = document.createElement("span");
  innerBullet.style.position = "absolute";
  innerBullet.style.left = "50%";
  innerBullet.style.top = "50%";
  innerBullet.style.transform = "translate(-50%, -50%)";
  innerBullet.style.width = "8px";
  innerBullet.style.height = "8px";
  innerBullet.style.borderRadius = "50%";

  bullet.appendChild(innerBullet);

  // **Formatting Condition with Colors**
  let formattedCondition = condition
    .replace(/<div/g, ' <div') // Add space before <div> tags if missing
    .replace(/<div\s+class\s*=\s*["']?SummaryKey["']?\s*>(.*?)<\/div>/gi, ' <span style="color: black; font-weight: 500;">$1</span> ') 
    .replace(/<div\s+class\s*=\s*["']?SummaryValue["']?\s*>(.*?)<\/div>/gi, ' <span style="color: #00a886; font-weight: 500;">$1</span> ') 
    .replace(/<div\s+class\s*=\s*["']?SummaryOperator["']?\s*>(.*?)<\/div>/gi, ' <span> $1 </span> ') // Ensure space around operators
    .replace(/>\s+</g, '> <')  // Ensures space between inline elements
    .replace(/\s+/g, ' ')      // Remove multiple spaces
    .trim();                   // Trim any leading/trailing spaces

  // console.log("🟢 Formatted Condition (With Colors):", formattedCondition);

  // **Convert to Plain Text with Spaces**
  // const plainTextCondition = stripHTMLWithSpacing(formattedCondition);
  // console.log("🔹 Plain Text Condition (With Spaces):", plainTextCondition);

  // // Set bullet first, then append formatted text
  listItem.appendChild(bullet);
  
  // Create a span for the condition text (for proper spacing)
  const textSpan = document.createElement("span");
  textSpan.innerHTML = formattedCondition;
  textSpan.style.marginLeft = "-5px"; // Ensure space between bullet and text
  listItem.appendChild(textSpan);

  console.log("✅ Final List Item InnerHTML:", listItem.innerHTML); // Log final output

  return listItem;
};
 // Create the heading "Event:"
    const eventLabel = document.createElement("p");
    eventLabel.textContent = "Event";
    eventLabel.style.margin = "0";
    eventLabel.style.color = "#00a886"; // Blue color for heading
    eventLabel.style.fontWeight = "bold";
    eventLabel.style.fontSize = "16px";
  
    // Create the unordered list for the event details
    const eventDetail = document.createElement("ul");
    eventDetail.style.margin = "8px 0 0 -15px"; // Add margin and indentation
    eventDetail.style.color = "#333"; // Normal color for text
    eventDetail.style.listStyleType = "none"; // Remove default bullets
    eventDetail.style.fontSize = "14px";
    // Add event detail with the custom bullet
    const eventBullet = createCustomBullet(
      "When Ticket is Updated", // Text content
      "#2c5cc5", // Bullet color
      "#00a886" // Highlight color for the last word
    );
    eventDetail.appendChild(eventBullet);
    
    // Append the heading and the event detail to the container
    eventText.appendChild(eventLabel);
    eventText.appendChild(eventDetail);
    // Extract performer text (assuming it's a single string)
      const performerText = typeof content.performer === "string" ? stripHTML(content.performer) : "";
      
      // Add the performer to the content if it exists
      if (performerText) {
        console.log("performerText",performerText)
        const performerItem = createConditionBullet(content.performer, "#2c5cc5"); // Green bullet for performer
        performerItem.style.marginBottom = "10px";
        performerItem.style.marginTop = "10px"; // Add space after performer text
        performerItem.style.marginLeft = "10px"; 
        performerItem.style.fontSize ="14px";
        eventText.appendChild(performerItem);
      }
  // Add Event data to Event content
const eventArray = (Array.isArray(content.events) && content.events.length) 
    ? content.events 
    : (Array.isArray(content.eventText) && content.eventText.length) 
        ? content.eventText 
        : (content.events ? [content.events] : (content.eventText ? [content.eventText] : []));

eventArray.forEach(event => {
    if (event) {
        const eventItem = createConditionBullet(event,  "#2c5cc5");
        eventItem.style.marginBottom = "10px";
        eventItem.style.marginTop = "10px"; // Add space after performer text
        eventItem.style.marginLeft = "10px"; 
        eventItem.style.fontSize ="14px";
        eventText.appendChild(eventItem);

    }
});
     
    
  // Create the conditions heading
  const conditionText = document.createElement("div");
  conditionText.textContent = "Condition";
  conditionText.style.marginBottom = "8px";
  conditionText.style.fontWeight = "bold";
  conditionText.style.color = "#e86f25"; // Green color for conditions heading
  conditionText.style.fontSize = "16px";
  
  // Create a container for the conditions list
  const conditionsList = document.createElement("ul");
  conditionsList.style.margin = "0 0 12px";
  conditionsList.style.padding = "8px";
  conditionsList.style.border = "1px solid #ddd";
  conditionsList.style.borderRadius = "4px";
  conditionsList.style.backgroundColor = "#fff";
  conditionsList.style.listStyleType = "none"; // Remove default bullet style
  conditionsList.style.fontSize = "14px";
  
 // Extract condition sets and operator
const conditionsArray1 = Array.isArray(content.conditions.condition_set_1)
? content.conditions.condition_set_1
: [];
const conditionsArray2 = Array.isArray(content.conditions.condition_set_2)
? content.conditions.condition_set_2
: [];
const operator = content.conditions.operator || "";
console.log("conditions array 1",conditionsArray1);




// // Create condition list container
// const conditionsList = document.createElement("ul");
// conditionsList.style.listStyleType = "none";
// conditionsList.style.padding = "0";

// Add conditions from condition_set_1
conditionsArray1.forEach((condition) => {
if (condition === "AND" || condition === "OR") {
  // Add operator as a separate text element
  const operatorItem = document.createElement("div");
  operatorItem.textContent = condition;
  operatorItem.style.color = "#6c757d";
  operatorItem.style.margin = "8px 0 5px 29px";
  conditionsList.appendChild(operatorItem);
} else {
  conditionsList.appendChild(createConditionBullet(condition, "#2c5cc5")); // Blue bullet
}
});

// Add operator between conditions (if available)
if (operator) {
const operatorItem = document.createElement("div");
operatorItem.textContent = operator;
operatorItem.style.color = "#000000";
operatorItem.style.margin = "8px 0";
operatorItem.style.fontSize = "14px";
operatorItem.style.fontweight = "500";
conditionsList.appendChild(operatorItem);
}

// Add conditions from condition_set_2
conditionsArray2.forEach((condition) => {
if (condition === "AND" || condition === "OR") {
  const operatorItem = document.createElement("div");
  operatorItem.textContent = condition;
  operatorItem.style.color = "#6c757d";
  operatorItem.style.margin = "8px 0 5px 29px";
  conditionsList.appendChild(operatorItem);
} else {
  conditionsList.appendChild(createConditionBullet(condition, "#2c5cc5")); // Blue bullet
}
});

// Create actions heading
const actionText = document.createElement("div");
actionText.textContent = "Action";
actionText.style.marginBottom = "8px";
actionText.style.fontWeight = "bold";
actionText.style.color = "#2c5cc5";
actionText.style.fontSize = "16px";

// Create actions content
const actionContent = document.createElement("ul");
actionContent.style.margin = "0";
actionContent.style.padding = "8px";
actionContent.style.border = "1px solid #ddd";
actionContent.style.borderRadius = "4px";
actionContent.style.backgroundColor = "#fff";
actionContent.style.listStyleType = "none";
actionContent.style.fontSize = "14px";

const actionsArray = Array.isArray(content.actions) ? content.actions : [];

// Add actions with custom bullets
actionsArray.forEach((action) => {
if (action === "AND" || action === "OR") {
  const operatorItem = document.createElement("div");
  operatorItem.textContent = action;
  operatorItem.style.color = "#6c757d";
  operatorItem.style.margin = "8px 0 5px 29px";
  actionContent.appendChild(operatorItem);
} else {
  actionContent.appendChild(createConditionBullet(action, "#2c5cc5")); // Blue bullet for actions
}
});
  
  // Append the label and line to the content box
  contentBox.appendChild(previewLabel);
  contentBox.appendChild(lineBelowLabel);
  
  scrollableContent.appendChild(eventText);
  scrollableContent.appendChild(conditionText);
  scrollableContent.appendChild(conditionsList);
  scrollableContent.appendChild(actionText);
  scrollableContent.appendChild(actionContent);
  
  // Append content to the scrollable wrapper
  
  contentBox.appendChild(scrollableContent);
  
  // Create fw-button element with "primary" color
  const closeButton = document.createElement("fw-button");
  closeButton.setAttribute("color", "primary");
  closeButton.textContent = "Close";
  closeButton.style.position = "absolute";
  closeButton.style.bottom = "16px"; // Distance from the bottom
  closeButton.style.right = "16px"; // Distance from the right
  closeButton.style.padding = "8px 16px"; // Padding for the button
  closeButton.style.borderRadius = "4px"; // Rounded corners
  closeButton.style.cursor = "pointer";
  
  // Close popup and remove overlay when the button is clicked
  closeButton.addEventListener("click", () => {
    document.body.removeChild(popupContainer);
    document.body.removeChild(overlay);
  });
  
  popupContainer.appendChild(popupHeader); // Fixed title
  popupContainer.appendChild(contentBox);
  // popupContainer.appendChild(headerContainer); // Fixed preview label and line
  // popupContainer.appendChild(wrapper); // Scrollable content
  popupContainer.appendChild(closeButton); // Close button
  
  // Append elements to the document
  document.body.appendChild(overlay);
  document.body.appendChild(popupContainer);
  
  }

  const normalizeText5 = (text) => {
    return text
        ? text
            .toLowerCase() // Convert everything to lowercase
            .split(/\s+/) // Split by spaces
            .filter(word => word.trim() !== "") // Remove empty words
            .sort() // Sort words alphabetically
            .join(" ") // Join words back into a string
        : "";
  };
  
  // Function to normalize, sort, and format list-based values (Case-Insensitive)
  const normalizeList5 = (value, label) => {
    if (!value) return "";
  
    const list = value
        .toLowerCase() // Convert everything to lowercase
        .split(/\s*[,|]\s*/) // Split by commas or pipes (remove spaces)
        .map((v) => normalizeText5(v)) // Normalize each item in the list
        .sort(); // Sort alphabetically
  
    console.log(`🔹 Normalized ${label}:`, list);
    return list.join(",");
  };
  
  // Function to find duplicate rules (Case-Insensitive)
  function findDuplicateRulestype4(records) { 
    console.log("function called");
  
    const seenRules = new Map(); // Store unique rules with their first occurrence
    const duplicateRecords = []; // Store all duplicate records
  
    // Function to remove all <img> tags from HTML content
    const stripImageTags = (html) => html ? html.replace(/<img[^>]*>/gi, "") : "";
  
    records.forEach((record) => {
        const { summary, conditions, actions, operator, events, performer, active } = record.data;
  
        if (!active) return; // Skip inactive records
  
        console.log("✅ Active Record:", record);
  
        // Normalize and sort fields (Ensure **case-insensitive** processing)
        const normalizedSummary = normalizeText5(summary);
        const normalizedConditions = normalizeList5(conditions, "Conditions");
        const normalizedActions = normalizeList5(stripImageTags(actions), "Actions");
        const normalizedEvents = normalizeList5(events, "Events");
        const normalizedPerformer = normalizeList5(performer, "Performer");
        const normalizedOperator = operator ? operator.trim().toLowerCase() : null; // Ensure lowercase
  
        console.log("🔹 Normalized Summary:", normalizedSummary);
        console.log("🔹 Normalized Conditions:", normalizedConditions);
        console.log("🔹 Normalized Actions:", normalizedActions);
        console.log("🔹 Normalized Events:", normalizedEvents);
        console.log("🔹 Normalized Performer:", normalizedPerformer);
        console.log("🔹 Normalized Operator:", normalizedOperator);
  
        // Create a unique key to compare records (All in lowercase now)
        const recordKey = `${normalizedSummary}|${normalizedConditions}|${normalizedActions}|${normalizedOperator}|${normalizedEvents}|${normalizedPerformer}`;
  
        console.log("🔍 Generated Record Key:", recordKey);
  
        if (seenRules.has(recordKey)) {
            console.log("⚠️ Duplicate Found:", record.display_id);
            
            if (!duplicateRecords.includes(seenRules.get(recordKey))) {
                duplicateRecords.push(seenRules.get(recordKey)); // Add original rule
            }
            duplicateRecords.push(record); // Add duplicate rule
        } else {
            seenRules.set(recordKey, record);
        }
    });
  
    return duplicateRecords;
  }
  
  



  
async function handleDuplicateRulestype4() {
  if (isFetchingType4 || type4 > 0) return; // Stop if already fetching or has run before

  isFetchingType4 = true; // Set flag to true before execution starts
  console.log("handleDuplicateRulestype4 called");

  try {
    const duplicatesType4 = await Filterrecords(4); // Get duplicate records
    console.log("🔄 Final duplicate records:", duplicatesType4);

    displayGroupedRules(duplicatesType4, "TicketUpdates"); // Display grouped rules

    type4++; // ✅ Increment count to prevent multiple calls
  } catch (error) {
    console.error("Error handling duplicate rules for type 4:", error);
  } finally {
    isFetchingType4 = false; // ✅ Reset flag after execution completes
  }
}



async function handleDuplicateRulestype3() {
  if (isFetchingType3 || type3 > 0) return; // Stop if already fetching or has run before

  isFetchingType3 = true; // Set flag to true before execution starts
  console.log("handleDuplicateRulestype3 called");

  try {
    const duplicatesType3 = await Filterrecords(3); // Get duplicate records
    console.log("🔄 Final duplicate records for hourly triggers:", duplicatesType3);

    displayGroupedRules(duplicatesType3, "HourlyTriggers"); // Display grouped rules

    type3++; // ✅ Increment count to prevent multiple calls
  } catch (error) {
    console.error("Error handling duplicate rules for type 3:", error);
  } finally {
    isFetchingType3 = false; // ✅ Reset flag after execution completes
  }
}

  

how role access functionality works?
ASSISTANT
The **RoleAccess** function is designed to control access to parts of the app based on the logged-in user's agent, group, or role membership. It works by checking if the current user is included in a predefined list of allowed agents, roles, or groups, which is configured through the app's installation parameters. Here's a detailed explanation of how it works step-by-step:

---

### 1. **Fetch Installed Parameters**

```js
let iparamSelectedCategory = await client.iparams.get();
```
The function fetches the app's installation parameters (`iparams`), which contain configuration data such as which agents, roles, or groups should have access, stored in:

- `iparamSelectedCategory.accessvalue` - An array of IDs allowed for access (agents, roles, or groups).
- `iparamSelectedCategory.fd_fields` - A string indicating what type is used for access control. It can be `"agent"`, `"role"`, or `"group"`.

---

### 2. **Format and Prepare Allowed Access List**

```js
let selectedCategoryArray = iparamSelectedCategory.accessvalue || [];
let fdFields = iparamSelectedCategory.fd_fields; // 'group', 'role', or 'agent'

selectedCategoryArray = selectedCategoryArray.map(value => value.toString().trim());
```

- Ensures the access value list is an array and trims all its string elements.
- `fdFields` determines **what type** of access is being checked.

---

### 3. **Get Logged-In User’s Data**

```js
const contactData = await client.data.get("loggedInUser");
```

Retrieve detailed data about the current logged-in user, including:

- Agent ID (`contactData.loggedInUser.id`)
- Group IDs (`contactData.loggedInUser.group_ids` - an array)
- Role IDs (`contactData.loggedInUser.role_ids` - an array)

They are converted to string and trimmed for consistent comparison:

```js
let loggedInAgentIdStr = contactData.loggedInUser.id.toString().trim();
let loggedInGroupsStr = (contactData.loggedInUser.group_ids || []).map(g => g.toString().trim());
let loggedInRolesStr = (contactData.loggedInUser.role_ids || []).map(r => r.toString().trim());
```

---

### 4. **Check Access Based on Type**

The function then compares the logged-in user's relevant IDs with the allowed list according to `fdFields`:

```js
let hasAccess = false;

if (fdFields === "agent") {
  hasAccess = selectedCategoryArray.includes(loggedInAgentIdStr);
} else if (fdFields === "role") {
  hasAccess = loggedInRolesStr.some(role => selectedCategoryArray.includes(role));
} else if (fdFields === "group") {
  hasAccess = loggedInGroupsStr.some(group => selectedCategoryArray.includes(group));
} else {
  console.error("❌ Unknown fd_fields value:", fdFields);
}
```

- **Agent check**: Does the logged in user's agent ID exist in the allowed list?
- **Role check**: Does at least one of the logged in user's roles exist in the allowed list?
- **Group check**: Does at least one of the logged in user's groups exist in the allowed list?

`hasAccess` is a **boolean** matching whether access is allowed.

---

### 5. **Grant or Deny Access in UI**

If access is granted:

```js
if (hasAccess) {
  document.getElementById("loader").style.display = "none";
  document.getElementById("Automation-page").style.display = "block";
  document.getElementById("no_user").style.display = "none";

  await checkAndSetButtonState();   // Enable or disable buttons based on other logic
  await initializeDatabase();       // Initialize database or setup further UI
}
```

- The main automation page is shown.
- The loading spinner is hidden.
- The "no user access" warning is hidden.
- Additional initialization happens.

If access is denied:

```js
else {
  document.getElementById("Automation-page").style.display = "none";
  document.getElementById("no_user").style.display = "block";
}
```

- The main automation page is hidden.
- A "no access" message or page (`no_user`) is shown.

---

### 6. **Error Handling**

If an error occurs fetching parameters or user data, it logs the error to console for debugging.

---

## **Summary**

- The function verifies if the current logged-in user has the necessary **agent ID**, **role ID**, or **group ID** to use the app.
- It uses the installed parameters configuration as the source of allowed IDs.
- Based on the check, it either shows or hides the main page with automation features.
- This secures the app and its functionality to only authorized users/groups/roles specified during app setup.

---

**This pattern is common for role-based access control (RBAC) in apps**, where you restrict feature access based on user attributes pulled from the system and configured by admins.

If you want, I can also explain how to extend or customize this function further!

turns-00069.parquet:31541

4ef1eaae5ed852300fa77330
turn 2/2gpt-4.1-mini-2025-04-14EnglishIndia16887 words
degenerate_repetitionAbsentFinal dense release
USER

let client;
let newRulePloadDB5; 
const duplicates = [];
let type1 = 0;
let type3 = 0;
let type4 = 0;
let storedvalue;

let counthourly = 0;
let countupdates = 0;
let countcreate = 0;
let isFetching = false; 
let isFetchingHourly = false;
let isFetchingType4 = false; 
let isFetchingType3 = false; 
let currentRuleId = null;
let currentAutomationId = null;
let globalAgents = []; 
let isFetchingRules = false; 
const automationTypeIdOneRecords = [];
const automationTypeIdfourRecords = [];
const automationTypeIdthreeRecords = [];
  
  const duplicatesType1 = [];
  const duplicatesType3 = [];
  const duplicatesType4 = [];


  async function setupTabListener(tabContainerId, sharedKey) {
    console.log(" setup tab listener function called ");

    while (typeof client === "undefined") {
        console.warn("⚠️ Waiting for 'client' to be ready...");
        await new Promise((resolve) => setTimeout(resolve, 500));
    }

    let fwTabs = document.querySelector(`#${tabContainerId} fw-tabs`);

    if (!fwTabs) {
        console.error(`❌ ERROR: <fw-tabs> NOT found inside #${tabContainerId}!`);
        return;
    }

    console.log(`✅ Found <fw-tabs> inside #${tabContainerId}. Attaching event listener...`);

    let savedTab;
    try {
        let storedValue = await client.db.get("TabDB");
        savedTab = storedValue?.[sharedKey];

        if (!savedTab) {
            savedTab = "Ticket Creation";
            storedValue = storedValue || {};
            storedValue[sharedKey] = savedTab;
            await client.db.set("TabDB", storedValue);
            console.log(`✅ No previous tab found. Setting default tab: ${savedTab}`);
        } else {
            console.log(`🔍 Retrieved active tab from DB:`, savedTab);
        }
    } catch (error) {
        if (error.status === 404) {
            console.warn(`⚠️ No previous tab found in DB. Using default.`);
            savedTab = "Ticket Creation";
            let defaultData = { [sharedKey]: savedTab };
            await client.db.set("TabDB", defaultData);
            console.log(`✅ Default tab stored: ${savedTab}`);
        } else {
            console.error(`❌ Error retrieving tab from DB:`, error);
        }
    }

    if (savedTab) {
        let tabElement = fwTabs.querySelector(`fw-tab[panel='${savedTab}']`);
        let pageContainer = document.getElementById(tabContainerId);

        if (tabElement) {
            if (pageContainer.style.display !== "none") {
                console.log(`✅ Restoring tab in visible page: #${tabContainerId}:`, savedTab);
                tabElement.click();
            } else {
                console.warn(`⚠️ Page #${tabContainerId} hidden. Waiting to restore tab:`, savedTab);

                const observer = new MutationObserver((mutationsList, observer) => {
                    for (let mutation of mutationsList) {
                        if (mutation.attributeName === "style" && pageContainer.style.display !== "none") {
                            console.log(`✅ Page #${tabContainerId} is now visible. Restoring tab:`, savedTab);
                            tabElement.click();
                            observer.disconnect();
                        }
                    }
                });

                observer.observe(pageContainer, { attributes: true });
            }
        } else {
            console.warn(`⚠️ Saved tab not found in DOM inside #${tabContainerId}:`, savedTab);
        }
    }

    // Attach event listener for tab changes
    fwTabs.addEventListener("fwChange", async (event) => {
        let tabIndex = event.detail.tabIndex;
        let tabs = fwTabs.querySelectorAll("fw-tab");

        if (tabs[tabIndex]) {
            let activeTab = tabs[tabIndex].getAttribute("panel");
            console.log(`✅ Active tab detected: ${activeTab}. Storing in DB.`);

            try {
                let storedValue = (await client.db.get("TabDB")) || {};
                storedValue[sharedKey] = activeTab;
                await client.db.set("TabDB", storedValue);
                console.log(`💾 Tab stored in DB (shared):`, activeTab);
            } catch (error) {
                console.error(`❌ Error storing active tab in DB:`, error);
            }
        } else {
            console.warn(`⚠️ No active tab found at index ${tabIndex} inside #${tabContainerId}.`);
        }
    });
}
document.addEventListener("DOMContentLoaded", async () => {
  console.log("📌 Page Loaded! Restoring last visited tab...");
  await setupTabListener("Automation-page", "LastVisitedTab");
});









document.addEventListener("DOMContentLoaded", function () {
  let progressBar = document.getElementById("progress-container");

  if (progressBar) {
      // Set initial styles for fast animation
      progressBar.style.transition = "width 0.2s linear, opacity 0.3s"; // Faster transition
      progressBar.style.width = "0%"; 
      progressBar.style.height = "3px"; 
      // progressBar.style.backgroundColor = "#007bff"; 
      progressBar.style.opacity = "0";

      progressBar.start = function () {
          progressBar.style.width = "70%"; // Moves faster initially
          progressBar.style.opacity = "1";
      };

      progressBar.done = function () {
          progressBar.style.width = "100%"; // Moves to near completion quickly
          setTimeout(() => {
              progressBar.style.width = "0%"; // Resets quickly
              progressBar.style.opacity = "0";
          }, 1000); // Reduced reset time
      };
  } else {
      console.error("❌ Progress bar element not found!");
  }
});

  function createLoadingBanner(targetElementId) {
    console.log("main banner function called");
    // Check if the banner already exists to avoid duplicates
    if (document.getElementById("loadingBanner")) return;
  
    // Create the banner div
    let banner = document.createElement("div");
    banner.id = "loadingBanner";
    banner.className = "loading-banner";
      
banner.innerHTML = `⚠️ The system is still processing additional data. Please wait...
<span class="spinner"></span>`;

// Force the browser to recognize the new element and its styles
setTimeout(() => {
document.querySelector('.spinner').style.animation = 'spin 1s linear infinite';
}, 10);
  
    // Style dynamically (optional, you can also use CSS)
    banner.style.position = "fixed";
    banner.style.top = "20px";
    banner.style.right = "700px";
    banner.style.backgroundColor =" #fff3cd";
    banner.style.padding = "12px";
    banner.style.borderRadius = "5px";
    banner.style.boxShadow = "0px 2px 5px rgba(0,0,0,0.2)";
    banner.style.display = "none"; // Initially hidden
    banner.style.color =" #856404";
  
    // Insert the banner in the desired location
    let targetElement = document.getElementById(targetElementId);
    if (targetElement) {
      targetElement.appendChild(banner);
    } else {
      document.body.appendChild(banner); // Default to body if no target found
    }
  }
  function showLoadingBanner() {
    console.log("showbanner called")
    let banner = document.getElementById("loadingBanner");
    if (banner) banner.style.display = "block";
  }
  
  function hideLoadingBanner() {
    console.log("hidebanner called")
    let banner = document.getElementById("loadingBanner");
    if (banner) banner.style.display = "none";
  }
    
  function removeLoadingBanner() {
    console.log("remove banner called")
    let banner = document.getElementById("loadingBanner");
    if (banner) {
        banner.remove(); // Removes the element from the DOM permanently
        console.log("✅ Loading banner removed permanently.");
    }
}

// Initialize the app
init();

async function init() {
  client = await app.initialized();

  // Event Listener: App Activated
  client.events.on("app.activated", async function () {
    console.log("🟢 App activated! Calling RoleAccess first...");
    
    await RoleAccess();
  
  });
}

// Function to check role access
async function RoleAccess() {
  try {
    let iparamSelectedCategory = await client.iparams.get();
    console.log("🔍 iparamSelectedCategory:", iparamSelectedCategory);

    let selectedCategoryArray = iparamSelectedCategory.accessvalue || [];
    let fdFields = iparamSelectedCategory.fd_fields; // 'group', 'role', or 'agent'

    if (!Array.isArray(selectedCategoryArray)) {
      console.error("❌ accessvalue is not an array", selectedCategoryArray);
      return;
    }

    selectedCategoryArray = selectedCategoryArray.map(value => value.toString().trim());

    console.log("✅ Formatted selectedCategoryArray:", selectedCategoryArray);

    const contactData = await client.data.get("loggedInUser");
    console.log("👤 Logged-in user data:", contactData);

    let loggedInAgentIdStr = contactData.loggedInUser.id.toString().trim();
    let loggedInGroupsStr = (contactData.loggedInUser.group_ids || []).map(g => g.toString().trim());
    let loggedInRolesStr = (contactData.loggedInUser.role_ids || []).map(r => r.toString().trim());

    console.log("🔹 loggedInAgentIdStr:", loggedInAgentIdStr);
    console.log("🔹 loggedInGroupsStr:", loggedInGroupsStr);
    console.log("🔹 loggedInRolesStr:", loggedInRolesStr);
    console.log("🔹 fdFields:", fdFields);

    let hasAccess = false;

    if (fdFields === "agent") {
      console.log("🔍 Checking agent access...");
      hasAccess = selectedCategoryArray.includes(loggedInAgentIdStr);
    } else if (fdFields === "role") {
      console.log("🔍 Checking role access...");
      hasAccess = loggedInRolesStr.some(role => selectedCategoryArray.includes(role));
    } else if (fdFields === "group") {
      console.log("🔍 Checking group access...");
      hasAccess = loggedInGroupsStr.some(group => selectedCategoryArray.includes(group));
    } else {
      console.error("❌ Unknown fd_fields value:", fdFields);
    }

    console.log("🔹 Final hasAccess:", hasAccess);

    if (hasAccess) {
     
      console.log("✅ Access granted! Initializing database...");
      document.getElementById("loader").style.display = "none";
      document.getElementById("Automation-page").style.display = "block";
      document.getElementById("no_user").style.display = "none";
      await  checkAndSetButtonState();
      await initializeDatabase();
    } else {
      console.log(" Access denied! Hiding automation page...");
      document.getElementById("Automation-page").style.display = "none";
      document.getElementById("no_user").style.display = "block";
    }
  } catch (error) {
    console.error(" Error in RoleAccess function:", error);
  }
}
let intervalId;

async function checkAndSetButtonState() {
  try {
    // Fetch stored value
    let storedvalue1 = await client.db.get("RulesDB");
    console.log("Initial stored value from RulesDB:", storedvalue1.stored);

    // Determine button state
    const isButtonEnabled = !!storedvalue1.stored;

    // Get button element
    const button = document.querySelector("fw-button");

    // Show loading banner if not already displayed
    if (!isButtonEnabled) {
      createLoadingBanner("banner");
      showLoadingBanner();
    }

    // Set button state
    if (button) {
      button.disabled = !isButtonEnabled;
      console.log(`🔘 Button is now ${isButtonEnabled ? "ENABLED" : "DISABLED"}`);
    }

    // If stored value is true, stop checking and remove the banner
    if (isButtonEnabled) {
      hideLoadingBanner();
      removeLoadingBanner();
      console.log("✅ Loading banner removed.");
      clearInterval(intervalId); // Stop checking
      return;
    }

    // Set interval only once
    if (!intervalId) {
      intervalId = setInterval(checkAndSetButtonState, 60000);
    }

  } catch (error) {
    if (error.status === 404) {
      console.warn("⚠️ RulesDB not found, assuming first-time install.");
      const button = document.querySelector("fw-button");
      if (button) {
        button.disabled = true;
      }
    } else {
      console.error("❌ Error retrieving stored value from RulesDB:", error);
    }
  }
}




async function initializeDatabase() {
  try {
    console.log("Initializing database...");
    const entity = await client.db.entity({ version: "v1" });
    console.log("Entity Initialized:", entity);

    
    // Assign global variable
    newRulePloadDB5 = entity.get("newRulePloadDB5");
    console.log("📌 Entity Reference:", newRulePloadDB5);

    // Fetch schema
    const data1 = await newRulePloadDB5.schema();
    console.log("📄 Schema Data:", data1);

  } catch (error) {
    console.error("❌ Error initializing database:", error);
  }
}

async function recentdata() {
  console.log("recentdata called");
  console.log(` Setting up Workflow-Automation-page...`);
  await setupTabListener("Workflow-Automation-page", "LastVisitedTab");
 
  await  GetAgents().then(agents => {
    console.log(" Agents fetching completed. Final List:", agents);
    globalAgents = agents; 
    console.log(" Checking globalAgents before function call:", globalAgents);
    
  });
  document.getElementById("Automation-page").style.display = "none";
  document.getElementById("button").style.display = "none";

  let workflowPage = document.getElementById("Workflow-Automation-page");
  if (workflowPage) {
    workflowPage.style.visibility = "visible"; // Make it visible
    workflowPage.style.opacity = "1"; // Fade in smoothly
  } else {
    console.error("❌ Still not found!");
  }
  // await fetchAndUseRules()
  
  
 
}


async function GetAgents(page = 1, agentsArray = []) {
  console.log(`Fetching agents for page ${page}`);

  try {
      const GetAgentsResponse = await client.request.invokeTemplate('recentagents', {
          context: { page: page }
      });

      const responses = GetAgentsResponse.response;
      const agentData = JSON.parse(responses);

      if (agentData.length === 0) {
          console.log("✅ No more agents to fetch. Total agents:", agentsArray.length);
          return agentsArray; // Stop recursion when no more agents
      }

      agentsArray.push(...agentData);

      // Fetch the next page
      return await GetAgents(page + 1, agentsArray);

  } catch (error) {
      console.error("❌ Error fetching agents:", error);

      if (error.headers && error.headers.status.includes("401")) {  
          document.getElementById("Automation-page").style.display = "none";
          document.getElementById("Workflow-Automation-page").style.display = "none";
          document.getElementById("no_user2").style.display = "block";
      }

      return agentsArray; // Return fetched data before the error
  }
}


async function fetchAndUseRules() {
  if (isFetchingRules|| countcreate > 0) return; // Prevent duplicate calls if already fetching

  isFetchingRules = true; // Set flag before execution
  showLoader(); // Show loader before fetching data

  try {
    const allRules = await listrules(); // Fetch data
    console.log("Ticket Creation Rules:", allRules);

    allRules.forEach(rule => {
      if (rule.active) automationTypeIdOneRecords.push(rule);
    });

    console.log("automationTypeIdOneRecords", automationTypeIdOneRecords);
    findDuplicatesWithinType(automationTypeIdOneRecords, duplicatesType1);
    console.log("Duplicate Records for Automation Type ID 1:", duplicatesType1);

    let automation_type_id = 1;
    displayGroupedRules4(duplicatesType1, "Ticketcreation1", automation_type_id, globalAgents);
    countcreate ++;
  } catch (error) {
    console.error("❌ Error fetching rules:", error);

    if (error.status === 401) {
      document.getElementById("Automation-page").style.display = "none";
      document.getElementById("Workflow-Automation-page").style.display = "none";
      document.getElementById("no_user2").style.display = "block";
    } else if (error.status === 429) {
      document.getElementById("Automation-page").style.display = "none";
      document.getElementById("Workflow-Automation-page").style.display = "none";
      document.getElementById("no_user1").style.display = "block";
    }
  } finally {
    hideLoader(); // Hide loader after execution
    isFetchingRules = false; // ✅ Reset flag after completion
  }
}

async function fetchupdaterules() {
  if (isFetching || countupdates > 0) return; // Stop if already fetching or already loaded

  isFetching = true; // Set flag to true before execution starts
  console.log("Fetching rules...");
  
  showLoader();

  try {
    const updateRules = await listupdaterules();
    console.log("Ticket updates Rules:", updateRules);

    updateRules.forEach(rule => {
      if (rule.active) automationTypeIdfourRecords.push(rule);
    });

    console.log("automationTypeIdfourRecords", automationTypeIdfourRecords);
    findDuplicatesWithinType(automationTypeIdfourRecords, duplicatesType4);
    console.log("Duplicate Records for Automation Type ID 4:", duplicatesType4);

    processAndDisplayDuplicates(duplicatesType4, "TicketUpdates1",globalAgents);

    countupdates++; 
  } catch (error) {
    console.error("Error fetching rules:", error);
    if (error.status === 401) {
      document.getElementById("Automation-page").style.display = "none";
      document.getElementById("Workflow-Automation-page").style.display = "none";
      
      document.getElementById("no_user2").style.display = "block";
    
     
    }
    else if(error.status === 429)
      {
        document.getElementById("Automation-page").style.display = "none";
        document.getElementById("Workflow-Automation-page").style.display = "none";
        
        document.getElementById("no_user1").style.display = "block";
      }
  } finally {
    hideLoader();
    isFetching = false; 
  }
}

async function fetchHourlyrules() {
  if (isFetchingHourly || counthourly > 0) return; // Stop if already fetching or loaded before

  isFetchingHourly = true; // Set flag to true before execution starts
  console.log("hourlycount at start", counthourly);

  showLoader();

  try {
    const hourlyRules = await listhourlyrules();
    console.log("Hourly Rules:", hourlyRules);

    hourlyRules.forEach(rule => {
      if (rule.active) automationTypeIdthreeRecords.push(rule);
    });

    console.log("automationTypeIdthreeRecords", automationTypeIdthreeRecords);
    findDuplicatesWithinType(automationTypeIdthreeRecords, duplicatesType3);
    console.log("Duplicate Records for Automation Type ID 3:", duplicatesType3);

    let automation_type_id = 3;
    displayGroupedRules4(duplicatesType3, "HourlyTriggers1", automation_type_id,globalAgents);

    counthourly++; // ✅ Increment count to ensure it runs only once
  } catch (error) {
    console.error("Error fetching hourly rules:", error);
    if (error.status === 401) {
      document.getElementById("Automation-page").style.display = "none";
      document.getElementById("Workflow-Automation-page").style.display = "none";
      
      document.getElementById("no_user2").style.display = "block";
      
    }
    else if(error.status === 429)
      {
        document.getElementById("Automation-page").style.display = "none";
        document.getElementById("Workflow-Automation-page").style.display = "none";
        
        document.getElementById("no_user1").style.display = "block";
      }
  } finally {
    hideLoader();
    isFetchingHourly = false; // ✅ Reset flag after execution completes
  }
}
async function listrules(page = 1, rulesArray = []) {
  console.log(`Fetching rules for page ${page}`);

  try {
      const rulesResponse = await client.request.invokeTemplate('listrules', {
          context: {
              page: page
          }
      });

      const responses = rulesResponse.response;
      const rulesData = JSON.parse(responses);

      if (rulesData.length === 0) {
          console.log("✅ No more rules to fetch. Total rules:", rulesArray.length);
          return rulesArray; // Stop recursion when no more rules
      }

      rulesArray.push(...rulesData);

      // Fetch the next page
      return await listrules(page + 1, rulesArray);

  } catch (error) {
      console.error("❌ Error fetching rules:", error);
      if (error.headers && error.headers.status.includes("401")) { 
        document.getElementById("Automation-page").style.display = "none";
        document.getElementById("Workflow-Automation-page").style.display = "none";
        
        document.getElementById("no_user2").style.display = "block";
        // let container = document.getElementById("Ticketcreation1");
    
        // if (container) {
        //     container.innerHTML = `
        //          <div style="
        //       display: flex;
        //       justify-content: center;
        //       align-items: center;
        //       height: 100vh;
        //       width: 100%;
        //       font-size: 24px;
        //       font-weight: bold;
        //       color: #333;
        //       margin-left: 400px; 
        //       text-align: center;
        //   ">
        //       ⚠️ Access Denied: The API key used has expired
        //   </div>`;
        // }
        // return;
    }
    else  if (error.status === 429 || (error.headers && error.headers.status && error.headers.status.includes("429"))) { 
      document.getElementById("Automation-page").style.display = "none";
      document.getElementById("Workflow-Automation-page").style.display = "none";
      
      document.getElementById("no_user1").style.display = "block";
    }
      return rulesArray; // Return whatever data was fetched before the error
  }
}
async function listupdaterules(page = 1, rulesArray = []) {
  console.log(`Fetching rules for page ${page}`);

  try {
      const rulesResponse = await client.request.invokeTemplate('listupdaterules', {
          context: {
              page: page
          }
      });

      const responses = rulesResponse.response;
      const rulesData = JSON.parse(responses);

      if (rulesData.length === 0) {
          console.log("✅ No more rules to fetch. Total rules:", rulesArray.length);
          return rulesArray; // Stop recursion when no more rules
      }

      rulesArray.push(...rulesData);

      // Fetch the next page
      return await listupdaterules(page + 1, rulesArray);

  } catch (error) {
      console.error("❌ Error fetching rules:", error);
      if (error.headers && error.headers.status.includes("401"))  {
        document.getElementById("Automation-page").style.display = "none";
        document.getElementById("Workflow-Automation-page").style.display = "none";
        
        document.getElementById("no_user2").style.display = "block";
        // let updateContainer = document.getElementById("TicketUpdates1"); 
  
        // if (updateContainer) {
        //   updateContainer.innerHTML = ""; // Clear the container
  
        //   updateContainer.innerHTML = `
        //   <div style="
        //       display: flex;
        //       justify-content: center;
        //       align-items: center;
        //       height: 100vh;
        //       width: 100%;
        //       font-size: 24px;
        //       font-weight: bold;
        //       color: #333;
        //       margin-left: 400px; 
        //       text-align: center;
        //   ">
        //       ⚠️ Access Denied: The API key used has expired
        //   </div>`;
      
      
        // }
        // return;
      }
      else  if (error.status === 429 || (error.headers && error.headers.status && error.headers.status.includes("429"))) { 
        document.getElementById("Automation-page").style.display = "none";
        document.getElementById("Workflow-Automation-page").style.display = "none";
        
        document.getElementById("no_user1").style.display = "block";
      }
      return rulesArray; // Return whatever data was fetched before the error
  }
}
async function listhourlyrules(page = 1, rulesArray = []) {
  console.log(`Fetching rules for page ${page}`);

  try {
      const rulesResponse = await client.request.invokeTemplate('listhourlyrules', {
          context: {
              page: page
          }
      });

      const responses = rulesResponse.response;
      const rulesData = JSON.parse(responses);

      if (rulesData.length === 0) {
          console.log("✅ No more rules to fetch. Total rules:", rulesArray.length);
          return rulesArray; // Stop recursion when no more rules
      }

      rulesArray.push(...rulesData);

      // Fetch the next page
      return await listhourlyrules(page + 1, rulesArray);

  } catch (error) {
      console.error("❌ Error fetching rules:", error);
      if (error.headers && error.headers.status.includes("401"))  {
        document.getElementById("Automation-page").style.display = "none";
        document.getElementById("Workflow-Automation-page").style.display = "none";
        
        document.getElementById("no_user2").style.display = "block";
        
      }
    else  if (error.status === 429 || (error.headers && error.headers.status && error.headers.status.includes("429"))) { 
        document.getElementById("Automation-page").style.display = "none";
        document.getElementById("Workflow-Automation-page").style.display = "none";
        
        document.getElementById("no_user1").style.display = "block";
      }
      return rulesArray; // Return whatever data was fetched before the error
  }
}


function deepEqual(obj1, obj2) {
  if (obj1 === obj2) return true;

  if (typeof obj1 === 'string' && typeof obj2 === 'string') {
    return normalizeText(stripHTML4(obj1)) === normalizeText(stripHTML4(obj2));
  }

  if (typeof obj1 !== 'object' || typeof obj2 !== 'object' || obj1 === null || obj2 === null) {
    return false;
  }

  const keys1 = Object.keys(obj1).sort();  // Sort keys to prevent order mismatch
  const keys2 = Object.keys(obj2).sort();

  if (keys1.length !== keys2.length) return false;

  for (const key of keys1) {
    let val1 = obj1[key];
    let val2 = obj2[key];

    if (typeof val1 === 'string' && typeof val2 === 'string') {
      val1 = normalizeText(stripHTML4(val1));
      val2 = normalizeText(stripHTML4(val2));
    }

    // Sort arrays before comparing (for condition sets)
    if (Array.isArray(val1) && Array.isArray(val2)) {
      val1 = val1.map(item => (typeof item === 'string' ? normalizeText(stripHTML4(item)) : item))
                 .sort((a, b) => JSON.stringify(a).localeCompare(JSON.stringify(b)));
      val2 = val2.map(item => (typeof item === 'string' ? normalizeText(stripHTML4(item)) : item))
                 .sort((a, b) => JSON.stringify(a).localeCompare(JSON.stringify(b)));
    }

    if (!keys2.includes(key) || !deepEqual(val1, val2)) {
      // console.log(`🚨 Mismatch found at key: ${key}`);
      return false;
    }
  }

  return true;
}

function normalizeText(text) {
  if (typeof text !== 'string') {
    return '';  // Return an empty string if not a valid string
  }
  return text.replace(/\s+/g, ' ').trim().toLowerCase();
}


// ✅ Remove HTML tags
function stripHTML4(htmlString) {
  return htmlString.replace(/<\/?[^>]+(>|$)/g, "").trim();
}




// // Helper function to remove <img> tags
// function stripImages(htmlString) {
//   return htmlString.replace(/<img[^>]*>/g, '').trim();
// }

// Function to find duplicate rules for ticket creation and hourly triggers
function findDuplicatesWithinType(records, duplicatesArray) {
  const seenRecords = [];

  records.forEach((rule, index) => {
    const { summary, actions, conditions } = rule;

    if (summary && actions && conditions) {
      console.log(`\n🔍 Checking Rule [${index + 1}]: ${rule.name}`);

      // 🔄 **Sort arrays in summary, actions, and conditions before comparison**
      const normalizedSummary = sortObjectValues(summary);
      const normalizedActions = sortObjectValues(actions);
      const normalizedConditions = sortObjectValues(conditions);

      const duplicate = seenRecords.find((seen) => {
        return (
          deepEqual(sortObjectValues(seen.summary), normalizedSummary) &&
          deepEqual(sortObjectValues(seen.conditions), normalizedConditions) &&
          deepEqual(sortObjectValues(seen.actions), normalizedActions)
        );
      });

      if (duplicate) {
        console.log(`✅ Duplicate Found: ${rule.name}`);
        duplicatesArray.push(rule);
        if (!duplicatesArray.includes(duplicate.rule)) {
          duplicatesArray.push(duplicate.rule);
        }
      } else {
        seenRecords.push({ summary: normalizedSummary, actions: normalizedActions, conditions: normalizedConditions, rule });
      }
    }
  });


}


function sortObjectValues(obj) {
  if (Array.isArray(obj)) {
    return obj
      .map(item => (typeof item === 'object' && item !== null ? sortObjectValues(item) : normalizeText(item)))
      .sort((a, b) => JSON.stringify(a).localeCompare(JSON.stringify(b)));
  } else if (typeof obj === 'object' && obj !== null) {
    return Object.fromEntries(
      Object.entries(obj)
        .map(([key, value]) => [key, sortObjectValues(value)])
        .sort(([keyA], [keyB]) => keyA.localeCompare(keyB)) 
    );
  }
  return normalizeText(obj);
}


function combineConditionsAndActions4(data) {
  const processedConditionSet1 = (data.condition_set_1 || []).map(stripHTML);
  const processedConditionSet2 = (data.condition_set_2 || []).map(stripHTML);

  // ✅ Keep the original order for display
  const originalConditions = [
    ...processedConditionSet1,
    data.operator ? ` ${data.operator} ` : "",
    ...processedConditionSet2,
  ].join(" ");

  let originalActionText = (data.actions || []).length
    ? data.actions.map(stripHTML4).join(" ")
    : "";

  const originalContent = `${originalConditions} ${originalActionText}`.trim();

  // ✅ Create sorted copies for grouping/comparison (Case-Insensitive)
  const sortedConditionSet1 = [...processedConditionSet1].map(text => text.toLowerCase()).sort();
  const sortedConditionSet2 = [...processedConditionSet2].map(text => text.toLowerCase()).sort();

  const sortedConditions = [
    ...sortedConditionSet1,
    data.operator ? ` ${data.operator.toLowerCase()} ` : "",
    ...sortedConditionSet2,
  ].join(" ");

  let sortedActionText = (data.actions || []).length
    ? [...data.actions.map(stripHTML4).map(text => text.toLowerCase())].sort().join(" ")
    : "";

  const sortedContent = `${sortedConditions} ${sortedActionText}`.trim();

  return { originalContent, sortedContent };
}

function normalizeText1(text) {
  if (typeof text !== "string") return text;
  return text
    .replace(/<[^>]*>/g, "") // Remove HTML tags
    .replace(/\s+/g, " ")    // Remove extra spaces
    .trim();
}

let currentPage4 = 1;
const itemsPerPage4 = 5;

function displayGroupedRules4(records, containerId, automation_type_id,globalAgents) {
  console.log("automationtypeid log at start of displaygroups",automation_type_id  )
  const container = document.getElementById(containerId);
  if (!container) {
    console.error(`Container with ID "${containerId}" not found.`);
    return;
  }

  container.innerHTML = ""; // Clear container

  if (records.length === 0) {
    container.innerHTML = `
        <div style="
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            width: 100%;
            font-size: 24px;
            font-weight: bold;
            color: #333;
                margin-left: 400px; 
            text-align: center;
        ">
            No duplicate rules found.
        </div>`;
    return;
}

const groupedRules = new Map();

records.forEach((record) => {
  const rule = record.parsedPayload || record.rule || record;
  if (!rule || !rule.summary) return;

  const { name, summary, position, updated_at, last_updated_by, affected_tickets_count, id } = rule;

  if (summary.conditions) {
    const actions = summary.actions || [];

    // ✅ Get both sorted and original content
    const { originalContent, sortedContent } = combineConditionsAndActions4({
      condition_set_1: summary.conditions.condition_set_1,
      condition_set_2: summary.conditions.condition_set_2,
      operator: summary.conditions.operator,
      actions: actions,
    });

    // ✅ Use sortedContent for grouping
    if (!groupedRules.has(sortedContent)) {
      groupedRules.set(sortedContent, []);
    }

    // ✅ Store both sortedContent (for grouping) and originalContent (for display)
    groupedRules.get(sortedContent).push({
      name,
      position,
      combinedContent: originalContent,  // ✅ Use originalContent for display
      conditions: summary.conditions,
      actions: actions,
      updated_at,
      last_updated_by,
      affected_tickets_count,
      id,automation_type_id
    });
  }
});

  const groupedRulesArray = Array.from(groupedRules.values());
  const totalgroup = Math.ceil(groupedRulesArray.length );
  console.log(totalgroup,"*********************")
  const totalPages4 = Math.ceil(groupedRulesArray.length / itemsPerPage4);
  currentPage4 = Math.max(1, Math.min(currentPage4, totalPages4)); // Ensure valid page number

  console.log("Total Pages:", totalPages4, "Current Page:", currentPage4);

  const startIdx = (currentPage4 - 1) * itemsPerPage4;
  const paginatedRules = groupedRulesArray.slice(startIdx, startIdx + itemsPerPage4);

  console.log("Displaying Records:", paginatedRules);

  let arrayLength = paginatedRules.length;
  console.log("Records Length:", arrayLength);

  // Display the paginated grouped rules
  paginatedRules.forEach((titles) => {
    const rulesCount = titles.length;

    // ✅ Skip the group if it contains only one rule
    if (rulesCount === 1) {
        console.log(`Skipping group with only 1 rule: ${titles[0].name}`);
        return; // Stop further execution for this group
    }
    const groupContainer = document.createElement("div");
    groupContainer.style.border = "1px solid #ccc";
    groupContainer.style.padding = "16px";
    groupContainer.style.margin = "16px";
    groupContainer.style.borderRadius = "8px";
    groupContainer.style.backgroundColor = "#f5f7f9";
    groupContainer.style.width = "1200px";

    titles.forEach(({  name, position, combinedContent, conditions, actions,updated_at,last_updated_by,affected_tickets_count,automation_type_id,id
    }, index) => {
      const card = document.createElement("div");
      card.style.border = "1px solid #ccc";
      card.style.padding = "16px";
      card.style.margin = "8px 0"
      card.style.fontFamily =
        "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif";
      card.style.borderRadius = "8px";
      card.style.backgroundColor = index === 0 ? "#fff" : "#e5f2fd";
      card.style.marginBottom = "10px";
      card.style.paddingBottom = "0";
     
     
      
      const cardHeader = document.createElement("div");
      cardHeader.style.display = "flex";
      cardHeader.style.justifyContent = "space-between";
      cardHeader.style.alignItems = "center";
      
      // Create a wrapper for the title
const cardTitle = document.createElement("h4");
cardTitle.style.margin = "0";
cardTitle.style.cursor = "pointer";
cardTitle.style.fontSize = "14px";
cardTitle.style.fontFamily = "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif";
cardTitle.style.color = "#183247";
cardTitle.style.transition = "color 0.2s ease";
cardTitle.style.fontWeight = "600"; 

// Create the serial number (position)
if (position) {
    const serialNumber = document.createElement("span");
    serialNumber.textContent = position + ". ";
    serialNumber.style.color = "#183247"; // Keep serial number color fixed
    cardTitle.appendChild(serialNumber);
}

// Create the actual name (clickable part)
const titleText = document.createElement("span");
titleText.textContent = name;
titleText.style.color = "#183247"; 
titleText.style.transition = "color 0.2s ease";

// Add hover effect for only the name
titleText.addEventListener("mouseover", () => {
    titleText.style.color = "#007bff"; // Change only name color on hover
});
titleText.addEventListener("mouseout", () => {
    titleText.style.color = "#183247"; // Reset name color when not hovering
});
titleText.addEventListener("click", () => {
    titleText.style.color = "#ff5733"; // Change title color on click
    console.log("automation type id before popup",automation_type_id)
    showPopupCard(name, { conditions: conditions, actions: actions },automation_type_id)
});

// Append name to title
cardTitle.appendChild(titleText);




      // Append title and actions to the cardHeader
      cardHeader.appendChild(cardTitle);
      // Create a container for the horizontal line and the gap
const cardContainer = document.createElement("div");

// Style the container to have a background color in the gap
cardContainer.style.backgroundColor = "#f0f0f0";  // Set the background color for the gap (change to desired color)
cardContainer.style.paddingBottom = "20px";  
cardContainer.style.marginLeft="-15px";
cardContainer.style.borderRadius = "4px";
cardContainer.style.width="102.7%";

// Create a horizontal line after the cardBody
const horizontalLine = document.createElement("div");
horizontalLine.style.height = "1px"; // Set the height to 1px for a thin line
horizontalLine.style.backgroundColor = "#ccc"; // Set the color of the horizontal line
horizontalLine.style.marginTop = "16px"; // Add space above the line (adjust as needed)
horizontalLine.style.width = "100%"; // Ensure the line stretches the full width of the container
horizontalLine.style.marginLeft="-3px";
      

      function truncateContent(content, maxLength, lines) {
        // Truncate the content to the desired number of characters
        let truncated = content;
      
        // Adjust for the desired line count and maximum length
        if (content.length > maxLength) {
          truncated = content.slice(0, maxLength) + "...";
        }
      
        // Break content into lines manually for multi-line truncation
        const words = truncated.split(" ");
        const result = [];
        let line = "";
        let currentLine = 1;
      
        for (let i = 0; i < words.length; i++) {
          if (line.length + words[i].length + 1 <= maxLength / lines) {
            line += (line ? " " : "") + words[i];
          } else {
            result.push(line);
            line = words[i];
            currentLine++;
            if (currentLine > lines) break; // Stop adding more lines if max lines are reached
          }
        }
      
        if (currentLine <= lines && line) {
          result.push(line);
        }
      
        return result.join(" ") + (currentLine > lines ? "..." : "");
      }
      function calculateLastModified(updated_at) {
        const updatedDate = new Date(updated_at);
        const currentDate = new Date();
    
        const diffInMilliseconds = currentDate - updatedDate;
        const seconds = Math.floor(diffInMilliseconds / 1000);
        const minutes = Math.floor(seconds / 60);
        const hours = Math.floor(minutes / 60);
        const days = Math.floor(hours / 24);
        const months = Math.floor(days / 30);  // Approximate months
        const years = Math.floor(days / 365);  // Approximate years
    
        if (years > 0) {
            return years === 1 ? "a year ago" : `${years} years ago`;
        } else if (months > 0) {
            return months === 1 ? "a month ago" : `${months} months ago`;
        } else if (days > 0) {
            return `${days} day${days > 1 ? "s" : ""} ago`;
        } else if (hours > 0) {
            return `${hours} hour${hours > 1 ? "s" : ""} ago`;
        } else if (minutes > 0) {
            return `${minutes} minute${minutes > 1 ? "s" : ""} ago`;
        } else {
            return "Just now";
        }
    }
    
    
      
      
      // console.log("updated at",calculateLastModified(updated_at));
      
 // Create a row for "Last Modified"
 const lastModifiedRow = document.createElement("div");
 lastModifiedRow.style.display = "grid";
 lastModifiedRow.style.gridTemplateColumns = "150px 150px 2px 150px 150px 2px 150px 150px"; // Consistent width for each section
 lastModifiedRow.style.alignItems = "center";
 lastModifiedRow.style.marginTop = "10px";
 lastModifiedRow.style.fontSize = "12px";
 lastModifiedRow.style.gap = "20px";
 lastModifiedRow.style.width = "100%"; // Ensures full width alignment
 
 const lastModifiedLabel = document.createElement("span");
 lastModifiedLabel.textContent = "Last Modified :";
 lastModifiedLabel.style.color = "#183247";
 lastModifiedLabel.style.fontSize = "12px";
 lastModifiedLabel.style.display = "inline-flex";
lastModifiedLabel.style.fontFamily =" -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif"
lastModifiedLabel.style.marginLeft = "40px"

 const lastModifiedValue = document.createElement("span");
 const lastModifiedText = calculateLastModified(updated_at);
 lastModifiedValue.textContent = lastModifiedText;
 lastModifiedValue.style.color = "#183247";
 lastModifiedValue.style.fontWeight = "600";
 lastModifiedValue.style.display = "inline-flex";
 lastModifiedValue.style.fontSize = "12px";
 lastModifiedValue.style.marginLeft = "-50px"
 lastModifiedValue.style.justifySelf = "start";
 lastModifiedValue.style.fontFamily =" -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif"

 const verticalLine = document.createElement("div");
 verticalLine.style.height = "20px";
 verticalLine.style.borderLeft = "2px solid #ccc";
 verticalLine.style.alignSelf = "stretch";
 
 lastModifiedRow.appendChild(lastModifiedLabel);
 lastModifiedRow.appendChild(lastModifiedValue);
 lastModifiedRow.appendChild(verticalLine);
 
 const agentsid = last_updated_by;

 const matchingAgent = globalAgents.find(agent => String(agent.id) === String(agentsid));

 if (matchingAgent) {
   console.log(`✅ Matching agent found:`, matchingAgent);
 } else {
   console.log(`❌ No agent found with id: ${agentsid}`);
 }
 
         const agentNameLabel = document.createElement("span");
         agentNameLabel.textContent = "By :";
         agentNameLabel.style.fontSize = "12px";
         agentNameLabel.style.color = "#183247";
         agentNameLabel.style.whiteSpace = "nowrap";
         agentNameLabel.style.marginLeft="149px"
         agentNameLabel.style.fontFamily =" -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif"

         const agentNameValue = document.createElement("span");
         if (matchingAgent) {
          agentNameValue.textContent = matchingAgent.contact.name|| "Unknown Agent"; 
      } else {
          agentNameValue.textContent = "Unknown Agent"; 
      }
         agentNameValue.style.color = "#183247";
         agentNameValue.style.fontWeight = "600";
         agentNameValue.style.whiteSpace = "nowrap";
         agentNameValue.style.fontFamily =" -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif"
         const verticalLine2 = document.createElement("div");
         verticalLine2.style.height = "20px";
         verticalLine2.style.borderLeft = "2px solid #ccc";
         verticalLine2.style.alignSelf = "stretch";
         verticalLine2.style.marginLeft = "100px";  // Increase for more right shift

 
         lastModifiedRow.appendChild(agentNameLabel);
         lastModifiedRow.appendChild(agentNameValue);
         lastModifiedRow.appendChild(verticalLine2);
 
         const affectedTicketsLabel = document.createElement("span");
         affectedTicketsLabel.textContent = "Impacted tickets (Last 7 days) : ";
         affectedTicketsLabel.style.fontSize = "12px";
         affectedTicketsLabel.style.color = "#183247";
         affectedTicketsLabel.style.marginLeft="140px";
         affectedTicketsLabel.style.whiteSpace = "nowrap";
         affectedTicketsLabel.style.fontFamily =" -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif"

         const affectedTicketsValue = document.createElement("span");
         affectedTicketsValue.textContent = affected_tickets_count === 0 ? "--" : affected_tickets_count;
         affectedTicketsValue.style.color = "#183247";
         affectedTicketsValue.style.fontWeight = "600";
         affectedTicketsValue.style.marginLeft ="134px"
         affectedTicketsValue.style.whiteSpace = "nowrap";
         affectedTicketsValue.style.fontFamily =" -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif"

         lastModifiedRow.appendChild(affectedTicketsLabel);
         lastModifiedRow.appendChild(affectedTicketsValue);
  
 

 
      const cardBody = document.createElement("div"); // Create a container for card content and actions
      cardBody.style.display = "flex"; // Flexbox to align items horizontally
      cardBody.style.justifyContent = "space-between"; // Ensure there's space between content and actions
      cardBody.style.alignItems = "flex-start"; // Align items to the top (optional, depending on your needs)
               

const truncatedContent = truncateContent(combinedContent, 200, 2);

const cardContent = document.createElement("pre");
cardContent.textContent = truncatedContent;

// Style the card content
cardContent.style.marginTop = "8px";
cardContent.style.padding = "8px";
cardContent.style.color="#183247";
cardContent.style.fontweight="600";
cardContent.style.fontFamily= "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif";
cardContent.style.whiteSpace = "pre-wrap"; // Ensure text wraps
cardContent.style.overflow = "hidden"; // Hide overflow content
cardContent.style.textOverflow = "ellipsis"; // Add ellipsis for overflow
cardContent.style.maxWidth = "75%"; // Limit the card width to half the container's width
cardContent.style.fontSize="12px";
cardContent.style.marginLeft="15px";


     // Create the container for card actions
const cardActionsContainer = document.createElement("div");
cardActionsContainer.style.display = "flex"; // Display actions horizontally
cardActionsContainer.style.justifyContent = "flex-end"; // Align to the right
cardActionsContainer.style.marginTop = "10px"; // Add some spacing above the actions
cardActionsContainer.style.gap = "8px"; // Set space between the toggle and the delete icon

      // Add fw-toggle
      // const fwToggle = document.createElement("fw-toggle");
      // fwToggle.setAttribute("size", "medium");
      // fwToggle.setAttribute("checked", "");

      // Add fw-icon
      const fwIcon = document.createElement("fw-icon");
      fwIcon.setAttribute("name", "delete");
      fwIcon.setAttribute("size", "18");
      fwIcon.style.cursor = "pointer";
      fwIcon.style.color = "red"; // Set the color to red
      // Add a pointer cursor for interactivity
      fwIcon.title = "Delete";

      fwIcon.addEventListener("click", () => {
        console.log("Delete icon clicked");
    
        currentRuleId = id; // Store the rule ID globally
        currentAutomationId = automation_type_id;
    
        console.log("rule id:", currentRuleId);
        console.log("automationid:", currentAutomationId);
    
        showDeletePopup(); 
    });
    
 
function showDeletePopup() {
  document.getElementById("deleteConfirmationPopup").style.display = "flex";
}


function hideDeletePopup() {
  document.getElementById("deleteConfirmationPopup").style.display = "none";
}
async function Fetchentity(automationTypeId, nextMarker = null, allRecords1 = []) {
  try {
    if (!newRulePloadDB5) {
      console.error(" Entity is not initialized yet!");
      showLoader();
      setTimeout(() => {
        location.reload();
    }, 1000);
    }

    showLoader(); 

    let queryObj = {
      query: {
        $and: [
          { automation_type_id: automationTypeId },
      
          { active: "true" } 
        ]
      } 
    };


    if (nextMarker) {
      console.log("🔄 Next marker found:", nextMarker);
      queryObj.next = { marker: nextMarker };
    }

    console.log("📤 Fetching records with query:", JSON.stringify(queryObj, null, 2));

    const response = await newRulePloadDB5.getAll(queryObj);

    if (!response.records || !Array.isArray(response.records)) {
      console.error("❌ Invalid response format:", response);
      hideLoader(); 
      return allRecords1;
    }

    console.log(`📥 Retrieved ${response.records.length} records`);
    allRecords1 = allRecords1.concat(response.records);

    const newNextMarker = response.links?.next?.marker || null;

    if (newNextMarker) {
      console.log(`🔄 More pages exist. Next marker: ${newNextMarker}`);
      return Fetchentity(automationTypeId, newNextMarker, allRecords1);
    } else {
      console.log("✅ No more pages.");
      console.log(`📌 Total Filtered Records: ${allRecords1.length}`);

      hideLoader();


        return allRecords1;
      
    }
  } catch (error) {
    console.error("❌ Error fetching filtered records:", error);
    hideLoader(); 
    return [];
  }
}
async function recenetconfirmDeletion() {
console.log(" Deleting rule with ID:", currentRuleId);

try {
  // Start progress loader
  let progressLoader = document.querySelector("#progress-container");
  if (progressLoader && typeof progressLoader.start === "function") {
    progressLoader.start();
  }

  let getdeleteruleResponse = await client.request.invokeTemplate("deleterule", {
    context: {
      automationid: currentAutomationId,
      ruleid: currentRuleId,
    },
  });

  console.log("getdeleteruleResponse", getdeleteruleResponse);

  if (getdeleteruleResponse.status === 204) {
    console.log("✅ Rule deleted successfully!");

    // Show success toast
    let valid = document.getElementById("type_toast");
    valid.setAttribute("content", "Rule deleted successfully");
    valid.setAttribute("type", "success");
    valid.setAttribute("open", true);

    // ✅ Remove the rule from the UI
   
    // displayGroupedRules4(duplicatesType1, "Ticketcreation1", automation_type_id, globalAgents);
    hideDeletePopup();

    if (currentAutomationId === 1) {
     

       
      const ruleIndex = duplicatesType1.findIndex(rule => rule.id === currentRuleId);
      
      if (ruleIndex === -1) {
        console.warn(`❌ Rule with ID ${currentRuleId} not found in duplicatesType1.`);
      } else {
        const ruleToDelete = duplicatesType1[ruleIndex];
      
        try {
          console.log("🗑️ Deleting rule with ID:", ruleToDelete.id);
       
      
          // ✅ Optionally remove it from the array to update UI or logic
          duplicatesType1.splice(ruleIndex, 1);
          console.log("✅ Rule deleted and removed from duplicatesType1 array.",duplicatesType1);
          displayGroupedRules4(duplicatesType1, "Ticketcreation1", automation_type_id, globalAgents);
      let progressLoader = document.querySelector("#progress-container");
  if (progressLoader && typeof progressLoader.start === "function") {
    progressLoader.done();
  }
        } catch (error) {
          console.error(`❌ Error deleting rule with ID ${ruleToDelete.id}:`, error);
        }
      }
      
      
      
              if (entitytype1.length === 0) {
                console.log(" entitytype1 is empty. Fetching records...");
                entitytype1 = await Fetchentity(1); 
                console.log("entity fethed after clicking recent data",entitytype1);
                const displayId = getDisplayIdByRuleId(entitytype1, currentRuleId);
                console.log("Matching Display ID:", displayId);
                if (!displayId) return; // Ensure rule ID is available
              
                try {
                    console.log(" Deleting rule with ID:", displayId);
                    await newRulePloadDB5.delete(displayId);
              
                } catch (error) {
                    console.warn(` Error deleting record with Display ID ${displayId}, but continuing...`);
                }    
        
              }
              const displayId = getDisplayIdByRuleId(entitytype1, currentRuleId);
              console.log("Matching Display ID:", displayId);
              if (!displayId) return; // Ensure rule ID is available
            
              try {
                  console.log(" Deleting rule with ID:", displayId);
                  await newRulePloadDB5.delete(displayId);
            
              } catch (error) {
                  console.warn(` Error deleting record with Display ID ${displayId}, but continuing...`);
              }    
             
          }
          else if (currentAutomationId === 3) {
           
            const ruleIndex = duplicatesType3.findIndex(rule => rule.id === currentRuleId);
      
            if (ruleIndex === -1) {
              console.warn(`❌ Rule with ID ${currentRuleId} not found in duplicatesType3.`);
            } else {
              const ruleToDelete = duplicatesType3[ruleIndex];
            
              try {
                console.log("🗑️ Deleting rule with ID:", ruleToDelete.id);
              
            
                // ✅ Optionally remove it from the array to update UI or logic
                duplicatesType3.splice(ruleIndex, 1);
                console.log("✅ Rule deleted and removed from duplicatesType3 array.",duplicatesType3);
                displayGroupedRules4(duplicatesType3, "HourlyTriggers1", automation_type_id, globalAgents);
                let progressLoader = document.querySelector("#progress-container");
                if (progressLoader && typeof progressLoader.start === "function") {
                  progressLoader.done();
                }
              } catch (error) {
                console.error(`❌ Error deleting rule with ID ${ruleToDelete.id}:`, error);
              }}
      
            if (entitytype3.length === 0) {
              console.log(" entitytype3 is empty. Fetching records...");
              entitytype3 = await Fetchentity(3); 
              console.log("entity fethed after clicking recent data",entitytype3);
        
              const displayId = getDisplayIdByRuleId(entitytype3, currentRuleId);
              console.log("Matching Display ID:", displayId);
              if (!displayId) return; 
            
              try {
                  console.log(" Deleting rule with ID:", displayId);
                  await newRulePloadDB5.delete(displayId);
            
              } catch (error) {
                  console.warn(` Error deleting record with Display ID ${displayId}, but continuing...`);
              }    
            }
            const displayId = getDisplayIdByRuleId(entitytype3, currentRuleId);
            console.log("Matching Display ID:", displayId);
            if (!displayId) return; 
          
            try {
                console.log(" Deleting rule with ID:", displayId);
                await newRulePloadDB5.delete(displayId);
          
            } catch (error) {
                console.warn(` Error deleting record with Display ID ${displayId}, but continuing...`);
            }    
            }

 

  }
} catch (error) {
  console.error(" Error deleting rule:", error);
}
}
function getDisplayIdByRuleId(entityRecords, currentRuleId) {
  console.log("Checking all records for Rule ID:", currentRuleId);
  
  if (!Array.isArray(entityRecords) || entityRecords.length === 0) {
      console.warn(" No records found in entity storage.");
      return null;
  }

  console.log(" Sample Record Structure:", entityRecords.slice(0, 5));
  console.log(" Available Keys in First Record:", Object.keys(entityRecords[0]));

  

  // Find the record where rule_id matches currentRuleId
  const matchedRecord = entityRecords.find(record => 
    String(record?.data?.rule_id) === String(currentRuleId) // Ensure type conversion
  );

  console.log("Does Rule ID exist in records?", matchedRecord !== undefined);

  return matchedRecord ? matchedRecord.display_id : null;
}
    
    
    
    // Attach event listeners to the confirmation buttons (only once)
    document.getElementById("confirmDeleteBtn").addEventListener("click", recenetconfirmDeletion);
    document.getElementById("cancelDeleteBtn").addEventListener("click", hideDeletePopup);
    

             
             
          // Append fw-toggle and fw-icon to cardActions
          // cardActionsContainer.appendChild(fwToggle);
          cardActionsContainer.appendChild(fwIcon);
          card.appendChild(cardHeader);
          cardBody.appendChild(cardContent);
          cardBody.appendChild(cardActionsContainer);
          card.appendChild(cardBody);
          cardContainer.appendChild(horizontalLine);
          // card.appendChild(horizontalLine);
         
          cardContainer.appendChild(lastModifiedRow);
          card.appendChild(cardContainer)
          groupContainer.appendChild(card);
        });
    
        container.appendChild(groupContainer);
      });
    // Add pagination component
    addFwPagination4(containerId,records,totalgroup,automation_type_id);
    }

// Function to add pagination for displayGroupedRules4
function addFwPagination4(containerId, records, totalgroup, automation_type_id) {
  console.log('Adding pagination to container:', containerId);
  console.log("Automation Type ID at Page Change:", automation_type_id);

  

  let container1 = document.getElementById(containerId);
  if (!container1) {
      console.warn(`Container with ID "${containerId}" not found.`);
      return;
  }

  if (totalgroup <= itemsPerPage4) {
      console.log("Total records are less than or equal to items per page, skipping pagination.");
      return;
  }

  let existingPagination1 = container1.querySelector("#fw-pagination-4");
  if (existingPagination1) {
      existingPagination1.remove(); // Remove old pagination if it exists
  }

  const pagination1 = document.createElement("fw-pagination");
  pagination1.id = "fw-pagination-4";

  pagination1.setAttribute("total", totalgroup);
  pagination1.setAttribute("per-page", itemsPerPage4);
  pagination1.setAttribute("page", currentPage4);

  console.log("Pagination Element:", pagination1);

  const paginationWrapper1 = document.createElement("div");
  paginationWrapper1.style.display = "flex";
  paginationWrapper1.style.justifyContent = "flex-start";
  paginationWrapper1.style.alignItems = "center";
  paginationWrapper1.style.width = "100%";
  paginationWrapper1.style.marginLeft = "70%";

  paginationWrapper1.appendChild(pagination1);
  container1.appendChild(paginationWrapper1);

  
  pagination1.addEventListener("fwChange", (event) => {
      console.log("fwChange Event Triggered", event);
      currentPage4 = event.detail.page;
      console.log("Updated Page:", currentPage4);

      // Retrieve automation_type_id from localStorage if missing
      let storedAutomationTypeId = localStorage.getItem("automation_type_id");

      console.log("Retrieved automation_type_id from localStorage:", storedAutomationTypeId);

      // Update the displayed rules for the current container, passing automation_type_id correctly
      displayGroupedRules4(records, containerId, storedAutomationTypeId,globalAgents);
  });
}

// function stripHTMLupdates(htmlString) {
//   return htmlString.replace(/<\/?[^>]+(>|$)/g, "");
// }


// function combineConditionsAndActions(data) {
//   const { 
//     performer = "", 
//     eventText = [], 
//     condition_set_1 = [], 
//     condition_set_2 = [], 
//     operator, 
//     actions = [] 
//   } = data;

//   const processedConditionSet1 = condition_set_1.map(stripHTML);
//   const processedConditionSet2 = condition_set_2.map(stripHTML);

//   const conditions = [
//     ...processedConditionSet1,
//     operator ? ` ${operator} ` : "",
//     ...processedConditionSet2,
//   ].join(" ");

//   const actionText = actions.length
//     ? actions.map(action => typeof action === 'string' ? stripHTML(action) : action).join(" ")
//     : "";

//   const eventTextContent = eventText.length
//     ? eventText.map(event => typeof event === 'string' ? stripHTML(event) : event).join(" ")
//     : "";

//   const performerText = performer ? stripHTML(performer) : "";

//   const combinedContent = [
//     performerText,
//     eventTextContent,
//     conditions,
//     actionText,
//   ].filter(Boolean).join(" ");

//   return combinedContent.trim();
// }


function combineConditionsAndActions(data) {
  const { 
    performer = "", 
    eventText = [], 
    condition_set_1 = [], 
    condition_set_2 = [], 
    operator, 
    actions = [] 
  } = data;

  // ✅ Process performer (Remove HTML, trim)
  const processedPerformer = performer ? stripHTML(performer).trim() : "";

  // ✅ Process event text (Remove HTML, join)
  const processedEventText = eventText.length 
    ? eventText.map(stripHTML).join(" ").trim()
    : "";

  // ✅ Remove HTML from conditions and keep order
  const processedConditionSet1 = condition_set_1.map(stripHTML);
  const processedConditionSet2 = condition_set_2.map(stripHTML);

  // ✅ Combine conditions with operator
  const originalConditions = [
    ...processedConditionSet1,
    operator ? ` ${operator} ` : "",
    ...processedConditionSet2,
  ].filter(Boolean).join(" ").trim(); 

  // ✅ Process actions
  const originalActions = actions.length
    ? actions.map(stripHTML).join(" ").trim()
    : "";

  // ✅ Create the final **original** content for display
  const originalContent = [
    processedPerformer,
    processedEventText,
    originalConditions,
    originalActions,
  ].filter(Boolean).join(" ").trim();

  // === ✅ SORTING LOGIC FIX ===
  
  // ✅ Sort conditions **independently** (keeps set1/set2 separate but sorted)
  const sortedConditionSet1 = [...processedConditionSet1].map(text => text.toLowerCase()).sort();
  const sortedConditionSet2 = [...processedConditionSet2].map(text => text.toLowerCase()).sort();

  const sortedConditions = [
    ...sortedConditionSet1,
    operator ? ` ${operator.toLowerCase()} ` : "",
    ...sortedConditionSet2,
  ].filter(Boolean).join(" ").trim();

  // ✅ Sort actions separately
  const sortedActions = actions.length
    ? [...actions.map(stripHTML).map(text => text.toLowerCase())].sort().join(" ").trim()
    : "";

  // ✅ Sort event text
  const sortedEventText = eventText.length
    ? [...eventText.map(stripHTML).map(text => text.toLowerCase())].sort().join(" ").trim()
    : "";

  // ✅ Sort performer (single value, so just lowercase)
  const sortedPerformer = processedPerformer.toLowerCase();

  // ✅ Create the final **sorted** content for grouping (keeping structure)
  const sortedContent = [
    sortedPerformer,  
    sortedEventText,  
    sortedConditions,  
    sortedActions  
  ].filter(Boolean).join(" ").trim();

  return { originalContent, sortedContent };
}



let currentPageDuplicates = 1;
const itemsPerPageDuplicates = 5;

function processAndDisplayDuplicates(duplicates, containerId,globalAgents) {
  console.log("function processAndDisplayDuplicates called");

  const container = document.getElementById(containerId);
  if (!container) {
    console.error(`Container with ID "${containerId}" not found.`);
    return;
  }

  container.innerHTML = ""; // Clear container

 
  if (duplicates.length === 0) {
    container.innerHTML = `
    <div style="
        display: flex;
        justify-content: center;
        align-items: center;
        height: 100vh;
        width: 100%;
        font-size: 24px;
        font-weight: bold;
        color: #333;
        margin-left: 400px; 
        text-align: center;
    ">
        No duplicate rules found.
    </div>`;
return;
  }


  const groupedRules = new Map();

  duplicates.forEach((record) => {
    const rule = record.parsedPayload || record.rule || record;

    if (!rule || !rule.summary) {
      console.warn("Skipping record due to missing data:", record);
      return;
    }

    const { name, summary, position, updated_at, last_updated_by, affected_tickets_count, id } = rule;

    if (summary && summary.conditions) {
      const actions = summary.actions || [];
      const performer = summary.performer || "";
      const eventText = summary.events || [];

      // ✅ Get both sorted and original content
      const { originalContent, sortedContent } = combineConditionsAndActions({
        performer: performer,
        eventText: eventText,
        condition_set_1: summary.conditions.condition_set_1,
        condition_set_2: summary.conditions.condition_set_2,
        operator: summary.conditions.operator,
        actions: actions,
      });

      // ✅ Use sortedContent for grouping
      if (!groupedRules.has(sortedContent)) {
        groupedRules.set(sortedContent, []);
      }

      // ✅ Store both sortedContent (for grouping) and originalContent (for display)
      groupedRules.get(sortedContent).push({
        name,
        position,
        combinedContent: originalContent, // ✅ Use originalContent for display
        performer,
        eventText,
        conditions: summary.conditions,
        actions,
        updated_at,
        last_updated_by,
        affected_tickets_count,
        id,
      });
    }
  });

  const groupedRulesArray = Array.from(groupedRules.values());

  const totalgroup = Math.ceil(groupedRulesArray.length );
  console.log(totalgroup,"*********************")
  const totalPagesDuplicates = Math.ceil(groupedRulesArray.length / itemsPerPageDuplicates);
  currentPageDuplicates = Math.max(1, Math.min(currentPageDuplicates, totalPagesDuplicates));

  console.log("Total Pages:", totalPagesDuplicates, "Current Page:", currentPageDuplicates);

  const startIdx = (currentPageDuplicates - 1) * itemsPerPageDuplicates;
  const paginatedRules = groupedRulesArray.slice(startIdx, startIdx + itemsPerPageDuplicates);

  console.log("Displaying Records:", paginatedRules);
  
  let arrayLength = paginatedRules.length;
  console.log("Records Length:", arrayLength);

  paginatedRules.forEach((titles) => {
    const rulesCount = titles.length;

    // ✅ Skip the group if it contains only one rule
    if (rulesCount === 1) {
        console.log(`Skipping group with only 1 rule: ${titles[0].name}`);
        return; // Stop further execution for this group
    }
    const groupContainer = document.createElement("div");
    groupContainer.style.border = "1px solid #ccc";
    groupContainer.style.padding = "16px";
    groupContainer.style.margin = "16px";
    groupContainer.style.borderRadius = "8px";
    groupContainer.style.backgroundColor = "#f5f7f9";
    groupContainer.style.width = "1200px";
  
    titles.forEach(({ name, position, combinedContent, performer, 
      eventText, conditions, actions,updated_at,
      last_updated_by,
      affected_tickets_count,id}, index) => {
      const card = document.createElement("div");
      card.style.border = "1px solid #ccc";
      card.style.padding = "16px";
      card.style.margin = "8px 0";
      card.style.fontFamily =
        "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif";
      card.style.borderRadius = "8px";
      card.style.backgroundColor = index === 0 ? "#fff" : "#e5f2fd";
      card.style.marginBottom = "10px";
      card.style.paddingBottom = "0";
     
  
      const cardHeader = document.createElement("div");
      cardHeader.style.display = "flex";
      cardHeader.style.justifyContent = "space-between";
      cardHeader.style.alignItems = "center";
    // Create a wrapper for the title
const cardTitle = document.createElement("h4");
cardTitle.style.margin = "0";
cardTitle.style.cursor = "pointer";
cardTitle.style.fontSize = "14px";
cardTitle.style.fontFamily = "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif";
cardTitle.style.color = "#183247";
cardTitle.style.transition = "color 0.2s ease";
cardTitle.style.fontWeight = "600"; 

// Create the serial number (position)
if (position) {
const serialNumber = document.createElement("span");
serialNumber.textContent = position + ". ";
serialNumber.style.color = "#183247"; // Keep serial number color fixed
cardTitle.appendChild(serialNumber);
}

// Create the actual name (clickable part)
const titleText = document.createElement("span");
titleText.textContent = name;
titleText.style.color = "#183247"; 
titleText.style.transition = "color 0.2s ease";

// Add hover effect for only the name
titleText.addEventListener("mouseover", () => {
titleText.style.color = "#007bff"; // Change only name color on hover
});
titleText.addEventListener("mouseout", () => {
titleText.style.color = "#183247"; // Reset name color when not hovering
});
titleText.addEventListener("click", () => {
titleText.style.color = "#ff5733"; // Change title color on click
showPopupCard1(name, { performer: performer, 
eventText: eventText, conditions: conditions, actions: actions, });
});

// Append name to title
cardTitle.appendChild(titleText);
      // Append title and actions to the cardHeader
      cardHeader.appendChild(cardTitle);
      

      const cardContainer = document.createElement("div");

// Style the container to have a background color in the gap
cardContainer.style.backgroundColor = "#f0f0f0";  // Set the background color for the gap (change to desired color)
cardContainer.style.paddingBottom = "20px";  
cardContainer.style.marginLeft="-15px";
cardContainer.style.borderRadius = "4px";
cardContainer.style.width="102.7%";

// Create a horizontal line after the cardBody
const horizontalLine = document.createElement("div");
horizontalLine.style.height = "1px"; // Set the height to 1px for a thin line
horizontalLine.style.backgroundColor = "#ccc"; // Set the color of the horizontal line
horizontalLine.style.marginTop = "16px"; // Add space above the line (adjust as needed)
horizontalLine.style.width = "100%"; // Ensure the line stretches the full width of the container
horizontalLine.style.marginLeft="-3px";


function truncateContent(content, maxLength, lines) {
// Truncate the content to the desired number of characters
let truncated = content;

// Adjust for the desired line count and maximum length
if (content.length > maxLength) {
  truncated = content.slice(0, maxLength) + "...";
}

// Break content into lines manually for multi-line truncation
const words = truncated.split(" ");
const result = [];
let line = "";
let currentLine = 1;

for (let i = 0; i < words.length; i++) {
  if (line.length + words[i].length + 1 <= maxLength / lines) {
    line += (line ? " " : "") + words[i];
  } else {
    result.push(line);
    line = words[i];
    currentLine++;
    if (currentLine > lines) break; // Stop adding more lines if max lines are reached
  }
}

if (currentLine <= lines && line) {
  result.push(line);
}

return result.join(" ") + (currentLine > lines ? "..." : "");
}
function calculateLastModified(updated_at) {
const updatedDate = new Date(updated_at);
const currentDate = new Date();

const diffInMilliseconds = currentDate - updatedDate;
const seconds = Math.floor(diffInMilliseconds / 1000);
const minutes = Math.floor(seconds / 60);
const hours = Math.floor(minutes / 60);
const days = Math.floor(hours / 24);
const months = Math.floor(days / 30);  // Approximate months
const years = Math.floor(days / 365);  // Approximate years

if (years > 0) {
    return years === 1 ? "a year ago" : `${years} years ago`;
} else if (months > 0) {
    return months === 1 ? "a month ago" : `${months} months ago`;
} else if (days > 0) {
    return `${days} day${days > 1 ? "s" : ""} ago`;
} else if (hours > 0) {
    return `${hours} hour${hours > 1 ? "s" : ""} ago`;
} else if (minutes > 0) {
    return `${minutes} minute${minutes > 1 ? "s" : ""} ago`;
} else {
    return "Just now";
}
}

// console.log("updated at",calculateLastModified(updated_at));

// Create a row for "Last Modified"
const lastModifiedRow = document.createElement("div");
lastModifiedRow.style.display = "grid";
lastModifiedRow.style.gridTemplateColumns = "150px 150px 2px 150px 150px 2px 150px 150px"; // Consistent width for each section
lastModifiedRow.style.alignItems = "center";
lastModifiedRow.style.marginTop = "10px";
lastModifiedRow.style.fontSize = "12px";
lastModifiedRow.style.gap = "20px";
lastModifiedRow.style.width = "100%"; // Ensures full width alignment

const lastModifiedLabel = document.createElement("span");
lastModifiedLabel.textContent = "Last Modified :";
lastModifiedLabel.style.color = "#183247";
lastModifiedLabel.style.fontSize = "12px";
lastModifiedLabel.style.display = "inline-flex";
lastModifiedLabel.style.fontFamily =" -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif"
lastModifiedLabel.style.marginLeft = "40px"

const lastModifiedValue = document.createElement("span");
const lastModifiedText = calculateLastModified(updated_at);
lastModifiedValue.textContent = lastModifiedText;
lastModifiedValue.style.color = "#183247";
lastModifiedValue.style.fontWeight = "600";
lastModifiedValue.style.display = "inline-flex";
lastModifiedValue.style.fontSize = "12px";
lastModifiedValue.style.marginLeft = "-50px"
lastModifiedValue.style.justifySelf = "start";
lastModifiedValue.style.fontFamily =" -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif"

const verticalLine = document.createElement("div");
verticalLine.style.height = "20px";
verticalLine.style.borderLeft = "2px solid #ccc";
verticalLine.style.alignSelf = "stretch";

lastModifiedRow.appendChild(lastModifiedLabel);
lastModifiedRow.appendChild(lastModifiedValue);
lastModifiedRow.appendChild(verticalLine);

const agentsid = last_updated_by;




const matchingAgent = globalAgents.find(agent => String(agent.id) === String(agentsid));

if (matchingAgent) {
  console.log(`✅ Matching agent found:`, matchingAgent);
} else {
  console.log(`❌ No agent found with id: ${agentsid}`);
}

 const agentNameLabel = document.createElement("span");
 agentNameLabel.textContent = "By :";
 agentNameLabel.style.fontSize = "12px";
 agentNameLabel.style.color = "#183247";
 agentNameLabel.style.whiteSpace = "nowrap";
 agentNameLabel.style.marginLeft="149px"
 agentNameLabel.style.fontFamily =" -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif"

 const agentNameValue = document.createElement("span");
 if (matchingAgent) {
  agentNameValue.textContent = matchingAgent.contact.name|| "Unknown Agent"; 
} else {
  agentNameValue.textContent = "Unknown Agent"; 
}
 agentNameValue.style.color = "#183247";
 agentNameValue.style.fontWeight = "600";
 agentNameValue.style.whiteSpace = "nowrap";
 agentNameValue.style.fontFamily =" -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif"
 const verticalLine2 = document.createElement("div");
 verticalLine2.style.height = "20px";
 verticalLine2.style.borderLeft = "2px solid #ccc";
 verticalLine2.style.alignSelf = "stretch";
 verticalLine2.style.marginLeft = "100px";  // Increase for more right shift


 lastModifiedRow.appendChild(agentNameLabel);
 lastModifiedRow.appendChild(agentNameValue);
 lastModifiedRow.appendChild(verticalLine2);

 const affectedTicketsLabel = document.createElement("span");
 affectedTicketsLabel.textContent = "Impacted tickets (Last 7 days) : ";
 affectedTicketsLabel.style.fontSize = "12px";
 affectedTicketsLabel.style.color = "#183247";
 affectedTicketsLabel.style.marginLeft="140px";
 affectedTicketsLabel.style.whiteSpace = "nowrap";
 affectedTicketsLabel.style.fontFamily =" -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif"

 const affectedTicketsValue = document.createElement("span");
 affectedTicketsValue.textContent = affected_tickets_count === 0 ? "--" : affected_tickets_count;
 affectedTicketsValue.style.color = "#183247";
 affectedTicketsValue.style.fontWeight = "600";
 affectedTicketsValue.style.marginLeft ="134px"
 affectedTicketsValue.style.whiteSpace = "nowrap";
 affectedTicketsValue.style.fontFamily =" -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif"

 lastModifiedRow.appendChild(affectedTicketsLabel);
 lastModifiedRow.appendChild(affectedTicketsValue);




const cardBody = document.createElement("div"); // Create a container for card content and actions
cardBody.style.display = "flex"; // Flexbox to align items horizontally
cardBody.style.justifyContent = "space-between"; // Ensure there's space between content and actions
cardBody.style.alignItems = "flex-start"; // Align items to the top (optional, depending on your needs)
       

const truncatedContent = truncateContent(combinedContent, 200, 2);

const cardContent = document.createElement("pre");
cardContent.textContent = truncatedContent;

// Style the card content
cardContent.style.marginTop = "8px";
cardContent.style.padding = "8px";
cardContent.style.whiteSpace = "pre-wrap"; // Ensure text wraps
cardContent.style.overflow = "hidden"; // Hide overflow content
cardContent.style.textOverflow = "ellipsis"; // Add ellipsis for overflow
cardContent.style.maxWidth = "75%"; // Limit the card width to half the container's width
cardContent.style.fontSize="12px";
cardContent.style.color="#183247";
cardContent.style.fontweight="600";
cardContent.style.fontFamily= "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif";
cardContent.style.marginLeft="15px"

// Create the container for card actions
const cardActionsContainer = document.createElement("div");
cardActionsContainer.style.display = "flex"; // Display actions horizontally
cardActionsContainer.style.justifyContent = "flex-end"; // Align to the right
cardActionsContainer.style.marginTop = "10px"; // Add some spacing above the actions
cardActionsContainer.style.gap = "8px"; // Set space between the toggle and the delete icon

// Add fw-toggle
// const fwToggle = document.createElement("fw-toggle");
// fwToggle.setAttribute("size", "medium");
// fwToggle.setAttribute("checked", "");

// Add fw-icon
const fwIcon = document.createElement("fw-icon");
fwIcon.setAttribute("name", "delete");
fwIcon.setAttribute("size", "18");
fwIcon.style.cursor = "pointer";
fwIcon.style.color = "red"; // Set the color to red
// Add a pointer cursor for interactivity
fwIcon.title = "Delete";
fwIcon.addEventListener("click", () => {
  console.log("Delete icon clicked");
  console.log("Rule ID:", id);

  // Show the confirmation popup before deleting
  showDeletePopup();

  // Function to show the confirmation popup
  function showDeletePopup() {
      document.getElementById("deleteConfirmationPopup").style.display = "flex";
  }

  // Function to hide the confirmation popup
  function hideDeletePopup() {
      document.getElementById("deleteConfirmationPopup").style.display = "none";
  }
  async function Fetchentity(automationTypeId, nextMarker = null, allRecords1 = []) {
    try {
      if (!newRulePloadDB5) {
        console.error(" Entity is not initialized yet!");
        showLoader();
        setTimeout(() => {
          location.reload();
      }, 1000);
      }
  
      showLoader(); 
  
      let queryObj = {
        query: {
          $and: [
            { automation_type_id: automationTypeId },
        
            { active: "true" } 
          ]
        } 
      };
  
  
      if (nextMarker) {
        console.log("🔄 Next marker found:", nextMarker);
        queryObj.next = { marker: nextMarker };
      }
  
      console.log("📤 Fetching records with query:", JSON.stringify(queryObj, null, 2));
  
      const response = await newRulePloadDB5.getAll(queryObj);
  
      if (!response.records || !Array.isArray(response.records)) {
        console.error("❌ Invalid response format:", response);
        hideLoader(); 
        return allRecords1;
      }
  
      console.log(`📥 Retrieved ${response.records.length} records`);
      allRecords1 = allRecords1.concat(response.records);
  
      const newNextMarker = response.links?.next?.marker || null;
  
      if (newNextMarker) {
        console.log(`🔄 More pages exist. Next marker: ${newNextMarker}`);
        return Fetchentity(automationTypeId, newNextMarker, allRecords1);
      } else {
        console.log("✅ No more pages.");
        console.log(`📌 Total Filtered Records: ${allRecords1.length}`);
  
        hideLoader();
  
  
          return allRecords1;
        
      }
    } catch (error) {
      console.error("❌ Error fetching filtered records:", error);
      hideLoader(); 
      return [];
    }
  }
  async function confirmDeletions() {
    console.log(" Deleting rule with ID:", id);

    // Start progress loader
    let progressLoader = document.querySelector("#progress-container");
    if (progressLoader && typeof progressLoader.start === "function") {
        progressLoader.start();
    }

    try {
        let getdeleteruleResponse = await client.request.invokeTemplate("deleterule", {
            context: { 
                automationid: 4, 
                ruleid: id 
            }
        });

        console.log("getdeleteruleResponse", getdeleteruleResponse);

        if (getdeleteruleResponse.status === 204) {
            console.log("✅ Rule deleted successfully!");

            // Show success toast
            let valid = document.getElementById('type_toast');
            valid.setAttribute('content', 'Rule deleted successfully');
            valid.setAttribute('type', 'success');
            valid.setAttribute('open', true);

            // ✅ Remove from UI
            removeDeletedRuleFromUI(id);
            hideDeletePopup();

            console.log("Before deletion, existing rule IDs:", duplicatesType4.map(rule => rule.id));

            // ✅ Convert to string for comparison
            const ruleIdToDelete = String(id);

            // ✅ Find and delete rule from duplicatesType4
            const index = duplicatesType4.findIndex(rule => String(rule.id) === ruleIdToDelete);
            console.log("Rule index found:", index);

            if (index !== -1) {
                duplicatesType4.splice(index, 1); // Remove rule from array
                console.log("✅ Rule removed from duplicatesType4.");
            } else {
                console.warn("⚠️ Rule not found in duplicatesType4. Possible ID mismatch.");
            }

          
                console.log("Duplicates after deleting:", duplicatesType4);
                processAndDisplayDuplicates(duplicatesType4, "TicketUpdates1",globalAgents);


                let progressLoader = document.querySelector("#progress-container");
                if (progressLoader && typeof progressLoader.start === "function") {
                  progressLoader.done();
                }


                if (entitytype4.length === 0) {
                  console.log(" entitytype4 is empty. Fetching records...");
                  entitytype4 = await Fetchentity(4); 
                  console.log("entity fethed after clicking recent data",entitytype4);
                  const displayId = getDisplayIdByRuleId(entitytype4, id);
                  console.log("Matching Display ID:", displayId);
                  if (!displayId) return; // Ensure rule ID is available
                
                  try {
                      console.log(" Deleting rule with ID:", displayId);
                      await newRulePloadDB5.delete(displayId);
                
                  } catch (error) {
                      console.warn(` Error deleting record with Display ID ${displayId}, but continuing...`);
                  }    
          
                }
                const displayId = getDisplayIdByRuleId(entitytype4, id);
                console.log("Matching Display ID:", displayId);
                if (!displayId) return; // Ensure rule ID is available
              
                try {
                    console.log(" Deleting rule with ID:", displayId);
                    await newRulePloadDB5.delete(displayId);
              
                } catch (error) {
                    console.warn(` Error deleting record with Display ID ${displayId}, but continuing...`);
                }    
               
            

               
        
        }
    } catch (error) {
        console.error("❌ Error deleting rule:", error);

        // Show error toast
        let errorToast = document.getElementById('type_toast');
        errorToast.setAttribute('content', "Failed to delete rule. Please try again.");
        errorToast.setAttribute('type', 'error');
        errorToast.setAttribute('open', true);
    } finally {
        // Ensure progress loader stops if an error occurs
        if (progressLoader && typeof progressLoader.done === "function") {
            progressLoader.done();
        }
    }

    // Hide the popup after action
    hideDeletePopup();
}

  // Function to remove the deleted rule from UI
  function removeDeletedRuleFromUI(ruleId) {
      let ruleCard = document.querySelector(`[data-rule-id="${ruleId}"]`);
      if (ruleCard) {
          ruleCard.remove();
      }
  }
  function getDisplayIdByRuleId(entityRecords, id) {
    console.log("Checking all records for Rule ID:", id);
    
    if (!Array.isArray(entityRecords) || entityRecords.length === 0) {
        console.warn(" No records found in entity storage.");
        return null;
    }
  
    console.log(" Sample Record Structure:", entityRecords.slice(0, 5));
    console.log(" Available Keys in First Record:", Object.keys(entityRecords[0]));
  
    
  
    // Find the record where rule_id matches currentRuleId
    const matchedRecord = entityRecords.find(record => 
      String(record?.data?.rule_id) === String(id) 
    );
  
    console.log("Does Rule ID exist in records?", matchedRecord !== undefined);
  
    return matchedRecord ? matchedRecord.display_id : null;
  }
      
  // Attach event listeners once (outside the click event)
  document.getElementById("confirmDeleteBtn").addEventListener("click", confirmDeletions);
  document.getElementById("cancelDeleteBtn").addEventListener("click", hideDeletePopup);
});

// fwIcon.addEventListener("click", async () => {
//   console.log("Delete icon clicked");
  

//    console.log("rule id:", id);
 
//   // Show the confirmation popup before deleting
//   showDeletePopup();
//     // Function to show the confirmation popup
// function showDeletePopup() {
// document.getElementById("deleteConfirmationPopup").style.display = "flex";
// }

// // Function to hide the confirmation popup
// function hideDeletePopup() {
// document.getElementById("deleteConfirmationPopup").style.display = "none";
// }

// // Function to handle deletion after confirmation
// async function confirmDeletion() {
// console.log("Deleting rule with ID:", id);

// try {
//     let getdeleteruleResponse = await client.request.invokeTemplate("deleterule", {
//       context:{  automationid:4,
//                   ruleid: id ,}
//     });

//     console.log("getdeleteruleResponse", getdeleteruleResponse);

//     // Show success toast
//     let valid = document.getElementById('type_toast');
//     console.log("toat message called", valid);
//     valid.setAttribute('content', 'Rule deleted successfully');
//     valid.setAttribute('type', 'success');
//     valid.setAttribute('open', true);

//     // Remove the deleted rule from UI
//     removeDeletedRuleFromUI(window.currentRuleId);

// } catch (error) {
//     console.error("Error deleting rule:", error);

//     // Show error toast
//     let errorToast = document.getElementById('type_toast');
//     errorToast.setAttribute('content', 'Error deleting rule. Please try again.');
//     errorToast.setAttribute('type', 'error');
//     errorToast.setAttribute('open', true);
// }

// // Hide the popup after action
// hideDeletePopup();
// }

// // Function to remove the deleted rule from UI
// function removeDeletedRuleFromUI(ruleId) {
// let ruleCard = document.querySelector(`[data-rule-id="${ruleId}"]`);
// if (ruleCard) {
//     ruleCard.remove();
// }
// }

// // Attach event listeners once (outside the click event)
// document.getElementById("confirmDeleteBtn").addEventListener("click", confirmDeletion);
// document.getElementById("cancelDeleteBtn").addEventListener("click", hideDeletePopup);
// });

// Append fw-toggle and fw-icon to cardActions
// cardActionsContainer.appendChild(fwToggle);
cardActionsContainer.appendChild(fwIcon);
card.appendChild(cardHeader);
cardBody.appendChild(cardContent);
cardBody.appendChild(cardActionsContainer);
card.appendChild(cardBody);
cardContainer.appendChild(horizontalLine);
// card.appendChild(horizontalLine);

cardContainer.appendChild(lastModifiedRow);
card.appendChild(cardContainer)
groupContainer.appendChild(card);
    });

    
    container.appendChild(groupContainer);
  });

  // Add pagination component
  addFwPaginationDuplicates(containerId, duplicates,totalgroup);
}

// Function to add pagination for processAndDisplayDuplicates
function addFwPaginationDuplicates(containerId,duplicates,totalgroup) {
  console.log("Adding pagination to container:", containerId);

  let container = document.getElementById(containerId);

  if (!container) {
    console.warn(`Container with ID "${containerId}" not found.`);
    return;
  }
  console.log("itemsperpage duplicates*********",itemsPerPageDuplicates)
  if (totalgroup <= itemsPerPageDuplicates) {
    
    console.log("Total records are less than or equal to items per page, skipping pagination.");
    return;
  }

  let existingPagination2 = container.querySelector("#fw-pagination-duplicates");
  if (existingPagination2) {
    existingPagination2.remove(); // Remove old pagination if it exists
  }

  const pagination2 = document.createElement("fw-pagination");
  pagination2.id = "fw-pagination-duplicates";
console.log("total group inside", )
  pagination2.setAttribute("total", totalgroup);
  pagination2.setAttribute("per-page", itemsPerPageDuplicates);
  pagination2.setAttribute("page", currentPageDuplicates);

  console.log("Pagination Element:", pagination2);

  const paginationWrapper2 = document.createElement("div");
  paginationWrapper2.style.display = "flex";
  paginationWrapper2.style.justifyContent = "flex-start";
  paginationWrapper2.style.alignItems = "center";
  paginationWrapper2.style.width = "100%";
  paginationWrapper2.style.marginLeft = "70%";

  paginationWrapper2.appendChild(pagination2);
  container.appendChild(paginationWrapper2);

  pagination2.addEventListener("fwChange", (event) => {
    console.log("fwChange Event Triggered", event);
    currentPageDuplicates = event.detail.page;
    console.log("Updated Page:", currentPageDuplicates);

    // Update the displayed rules for the current container
    processAndDisplayDuplicates(duplicates, containerId,globalAgents);
  });
}


let entitytype1 = [];
let entitytype3 = [];
let entitytype4 = [];
async function Filterrecords(automationTypeId, nextMarker = null, allRecords = []) {


  // console.log("filterrecords called for automationtypeid",automationTypeId);

  try {
    if (!newRulePloadDB5) {
      console.error(" Entity is not initialized yet!");
      showLoader();
      setTimeout(() => {
        location.reload();
    }, 1000);
    }

    showLoader(); // Show spinner before fetching starts

    let queryObj = {
      query: {
        $and: [
          { automation_type_id: automationTypeId },
      
          { active: "true" } 
        ]
      } 
    };

    if (nextMarker) {
      console.log("🔄 Next marker found:", nextMarker);
      queryObj.next = { marker: nextMarker };
    }

    console.log("📤 Fetching records with query:", JSON.stringify(queryObj, null, 2));

    const response = await newRulePloadDB5.getAll(queryObj);

    if (!response.records || !Array.isArray(response.records)) {
      console.error("❌ Invalid response format:", response);
      hideLoader(); // Hide spinner on failure
      return allRecords;
    }

    console.log(`📥 Retrieved ${response.records.length} records`);
    allRecords = allRecords.concat(response.records);

    const newNextMarker = response.links?.next?.marker || null;

    if (newNextMarker) {
      console.log(`🔄 More pages exist. Next marker: ${newNextMarker}`);
      return Filterrecords(automationTypeId, newNextMarker, allRecords);
    } else {
      console.log("✅ No more pages.");
      console.log(`📌 Total Filtered Records: ${allRecords.length}`);

      hideLoader(); // Hide spinner once fetching is complete

      //  Conditional function call based on automationTypeId
      if (automationTypeId === 1) {
      
         entitytype1 = allRecords;
         console.log("entity copy array",entitytype1);
        return findDuplicateRulestype1and3(allRecords);
      } else if(automationTypeId === 3)
      {
        entitytype3 = allRecords;
         console.log("entity copy array",entitytype3);
        return findDuplicateRulestype1and3(allRecords);
      }
      else if (automationTypeId === 4) {
        entitytype4 = allRecords;
         console.log("entity copy array",entitytype4);
        return findDuplicateRulestype4(allRecords);
      } else {
        console.warn("⚠️ Unknown automationTypeId:", automationTypeId);
        return allRecords;
      }
    }
  } catch (error) {
    console.error("❌ Error fetching filtered records:", error);
    hideLoader(); // Hide spinner on error
    return [];
  }
}


  
// async function Filterrecords(automationTypeId, nextMarker = null, allRecords = []) {


//   // console.log("filterrecords called for automationtypeid",automationTypeId);

//   try {
//     if (!newRulePloadDB5) {
//       console.error(" Entity is not initialized yet!");
//       showLoader();
//       setTimeout(() => {
//         location.reload();
//     }, 1000);
//     }

//     showLoader(); // Show spinner before fetching starts

//     let queryObj = {
//       query: { automation_type_id: automationTypeId }
//     };

//     if (nextMarker) {
//       console.log("🔄 Next marker found:", nextMarker);
//       queryObj.next = { marker: nextMarker };
//     }

//     console.log("📤 Fetching records with query:", JSON.stringify(queryObj, null, 2));

//     const response = await newRulePloadDB5.getAll(queryObj);

//     if (!response.records || !Array.isArray(response.records)) {
//       console.error("❌ Invalid response format:", response);
//       hideLoader(); // Hide spinner on failure
//       return allRecords;
//     }

//     console.log(`📥 Retrieved ${response.records.length} records`);
//     allRecords = allRecords.concat(response.records);

//     const newNextMarker = response.links?.next?.marker || null;

//     if (newNextMarker) {
//       console.log(`🔄 More pages exist. Next marker: ${newNextMarker}`);
//       return Filterrecords(automationTypeId, newNextMarker, allRecords);
//     } else {
//       console.log("✅ No more pages.");
//       console.log(`📌 Total Filtered Records: ${allRecords.length}`);

//       hideLoader(); // Hide spinner once fetching is complete

//       //  Conditional function call based on automationTypeId
//       if (automationTypeId === 1 || automationTypeId === 3) {
//         console.log("allrecords fetched from entity", allRecords)
//         return findDuplicateRulestype1and3(allRecords);
//       } else if (automationTypeId === 4) {
//         console.log("allrecords fetched from entity", allRecords)
//         return findDuplicateRulestype4(allRecords);
//       } else {
//         console.warn("⚠️ Unknown automationTypeId:", automationTypeId);
//         return allRecords;
//       }
//     }
//   } catch (error) {
//     console.error("❌ Error fetching filtered records:", error);
//     hideLoader(); // Hide spinner on error
//     return [];
//   }
// }

function showLoader() {
  console.log("showloader function called");
  document.getElementById("spinner").style.display = "block";
}

function hideLoader() {
  console.log("*********hide loader")
  document.getElementById("spinner").style.display = "none";
}



// 3 Function to find duplicate rules

function findDuplicateRulestype1and3(records) {
  const seenRules = new Map(); // Store unique rules with their first occurrence
  const duplicateRecords = []; // Store all duplicate records

  records.forEach((record) => {
    const { summary, conditions, actions, operator} = record.data;

    // if (!record.data.active) return; // Skip inactive records

    // console.log("Processing active record:", record); // Log full record

    // Function to remove all <img> tags from HTML content
    const stripImageTags = (html) => html.replace(/<img[^>]*>/g, "");

    // // Log conditions and actions before sorting
    // console.log("Original Conditions:", conditions);
    // console.log("Original Actions:", actions);

    // Normalize and sort conditions
    const normalizedConditions = conditions
      ? conditions
          .split(",") // Split into an array
          .map((c) => c.trim().toLowerCase()) // Trim and lowercase
          .sort() // Sort for consistency
          .join(",") // Join back into a string
      : "";

    // Normalize and sort actions
    const normalizedActions = actions
      ? stripImageTags(actions)
          .split(",") // Split into an array
          .map((a) => a.trim().toLowerCase()) // Trim and lowercase
          .sort() // Sort for consistency
          .join(",") // Join back into a string
      : "";

    // Log conditions and actions after sorting
    // console.log("Sorted Conditions:", normalizedConditions);
    // console.log("Sorted Actions:", normalizedActions);

    // Check for punctuation in summary
    if (summary && /[.,\/#!$%\^&\*;:{}=\-_`~()]/.test(summary)) {
      console.log("Punctuation found in summary:", summary);
    }

    // Normalize and sort summary (if structured)
    const normalizedSummary = summary
      ? summary
          .toLowerCase()
          .split(/\s+/) // Split by whitespace
          .sort() // Sort words alphabetically
          .join(" ") // Rejoin into a sorted sentence
      : "";

    // Log the sorted summary
    // console.log("Sorted Summary:", normalizedSummary);

    // Normalize operator
    const normalizedOperator = operator ? operator.trim().toLowerCase() : null;

    // Create a unique key to compare records
    const recordKey = `${normalizedSummary}|${normalizedConditions}|${normalizedActions}|${normalizedOperator}`;

    if (seenRules.has(recordKey)) {
      if (!duplicateRecords.includes(seenRules.get(recordKey))) {
        duplicateRecords.push(seenRules.get(recordKey)); // Add original rule
      }
      duplicateRecords.push(record); // Add duplicate rule
    } else {
      seenRules.set(recordKey, record);
    }
  });

  return duplicateRecords;
}

let isFetchingType1 = false; // Global flag to track fetching state

async function handleDuplicateRulestype1() {
  if (isFetchingType1|| type1 > 0) return; // Prevent duplicate calls if already fetching

  isFetchingType1 = true; // Set flag before execution starts
  console.log("handleDuplicateRulestype1 called");

  try {
    const duplicatesType1 = await Filterrecords(1); // Get duplicates
    console.log("🔄 Final duplicate records:", duplicatesType1);

    // Pass to grouping function with container ID
    displayGroupedRules(duplicatesType1, "Ticketcreation");
    type1++;
  } catch (error) {
    console.error("❌ Error handling duplicate rules for type 1:", error);
  } finally {
    isFetchingType1 = false; // ✅ Reset flag after execution completes
  }
}


 
// 3️⃣ Handle duplicate rule detection & pass to grouping function
// async function handleDuplicateRulestype1() {
//   const duplicatesType1 = await Filterrecords(1); // Get duplicates
//   console.log("🔄 Final duplicate records:", duplicatesType1,);


  


//   // Pass to grouping function with container ID
//   displayGroupedRules(duplicatesType1, "Ticketcreation");
// }

function stripHTML(htmlString) {
  return htmlString.replace(/<\/?[^>]+(>|$)/g, "");
}

// Function to show popup card with blur effect
function showPopupCard(title, content, automation_type_id) {

  if (automation_type_id !== undefined && automation_type_id !== null) {
      localStorage.setItem("automation_type_id", automation_type_id); 
  } else {
      automation_type_id = localStorage.getItem("automation_type_id") || "Unknown";
  }

  console.log("logPopup", automation_type_id);



const overlay = document.createElement("div");
overlay.style.position = "fixed";


overlay.style.top = "0";
overlay.style.left = "0";
overlay.style.width = "100%";
overlay.style.height = "100%";
overlay.style.backgroundColor = "rgba(0, 0, 0, 0.3)"; // Semi-transparent dark background
overlay.style.backdropFilter = "blur(5px)"; // Apply blur effect
overlay.style.zIndex = "999"; // Ensure it appears above everything else

// Create popup container
const popupContainer = document.createElement("div");
popupContainer.style.position = "fixed";
popupContainer.style.top = "50%";
popupContainer.style.left = "50%";
popupContainer.style.transform = "translate(-50%, -50%)";
popupContainer.style.width = "1000px"; // Increased default width
popupContainer.style.maxWidth = "95%"; // Ensure it fits on smaller screens
popupContainer.style.height = "60vh"; // Use viewport height to limit size
popupContainer.style.backgroundColor = "#fff";
popupContainer.style.border = "1px solid #ccc";
popupContainer.style.boxShadow = "0 4px 8px rgba(0, 0, 0, 0.2)";
popupContainer.style.borderRadius = "12px"; // Increased border radius for a smoother look
popupContainer.style.overflow = "hidden"; // Prevent content overflow
popupContainer.style.fontFamily =
  "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif"; // Apply a system font
popupContainer.style.zIndex = "1000";
popupContainer.style.display = "flex";
popupContainer.style.flexDirection = "column";


// Create header for title (fixed position)
const popupHeader = document.createElement("div");
popupHeader.style.padding = "16px 24px";
popupHeader.style.borderBottom = "1px solid #ddd"; // Separate the title visually
popupHeader.style.backgroundColor = "#fff";
popupHeader.style.zIndex = "10"; // Ensure it appears above the scrollable content

// Popup title
const popupTitle = document.createElement("h2");
popupTitle.textContent = title;
popupTitle.style.paddingLeft = "15px"; // Move the title slightly to the right
popupTitle.style.fontSize = "20px";
popupTitle.style.color = "#333";
popupTitle.style.textAlign = "left";
popupHeader.appendChild(popupTitle);



// Content wrapper (flex layout)
const contentWrapper = document.createElement("div");
contentWrapper.style.display = "flex";
contentWrapper.style.flexDirection = "column";
contentWrapper.style.flex = "1"; // Automatically take up available space
contentWrapper.style.overflow = "hidden"; // Prevent content overflow

// Content box (with fixed preview label)
const contentBox = document.createElement("div");
contentBox.style.flex = "1";
contentBox.style.border = "1px solid #ddd";
contentBox.style.borderRadius = "8px";
contentBox.style.backgroundColor = "#f9f9f9";
contentBox.style.padding = "16px";
contentBox.style.margin = "16px 16px"; // Add vertical spacing
contentBox.style.overflow = "hidden"; // Prevent outer scrolling
contentBox.style.marginBottom = "75px"; // Add enough space for the close button


// Preview label and line (sticky inside content box)
const previewLabelContainer = document.createElement("div");
previewLabelContainer.style.position = "sticky"; // Fix inside the content box
previewLabelContainer.style.top = "0"; // Stick to the top
previewLabelContainer.style.backgroundColor = "#f9f9f9"; // Match the content box background
previewLabelContainer.style.zIndex = "1";
previewLabelContainer.style.padding = "8px 0";

const previewLabel = document.createElement("p");
previewLabel.textContent = "Preview"; // Label text
previewLabel.style.fontSize = "16px";
previewLabel.style.fontWeight = "500";
previewLabel.style.color = "#92a2b1";
previewLabel.style.margin = "0";

const lineBelowLabel = document.createElement("hr");
lineBelowLabel.style.border = "none";
lineBelowLabel.style.borderTop = "1px solid #ddd";
lineBelowLabel.style.margin = "8px 0";

previewLabelContainer.appendChild(previewLabel);
previewLabelContainer.appendChild(lineBelowLabel);

// Scrollable content area
const scrollableContent = document.createElement("div");
scrollableContent.style.overflowY = "auto"; // Enable vertical scrolling
scrollableContent.style.height = "calc(100% - 40px)"; // Adjust to fit within the content box



  const eventText = document.createElement("div");
  eventText.style.marginBottom = "12px";
  const createCustomBullet = (text, bulletColor, highlightColor) => {
    const listItem = document.createElement("li");
    listItem.style.position = "relative"; // For positioning the custom bullet
    listItem.style.paddingLeft = "10px"; // Space for custom bullet
  
    // Create the custom double circular bullet using a span element
    const bullet = document.createElement("span");
    bullet.style.position = "absolute";
    bullet.style.left = "-15px"; // Bring the bullet closer to the text
    bullet.style.top = "50%"; // Center the bullet vertically
    bullet.style.transform = "translateY(-50%)"; // Center the bullet exactly
    bullet.style.width = "12px"; // Outer ring size
    bullet.style.height = "12px";
    bullet.style.border = `4px solid ${bulletColor || "#dcdfe1"}`; // Outer ring color and border size
    bullet.style.borderRadius = "50%"; // Make it a ring (circle with border)
    bullet.style.display = "inline-block";
  
    // Create the inner circle (smaller circle inside the outer ring)
    const innerBullet = document.createElement("span");
    innerBullet.style.position = "absolute";
    innerBullet.style.left = "50%";
    innerBullet.style.top = "50%";
    innerBullet.style.transform = "translate(-50%, -50%)"; // Centering the inner circle
    innerBullet.style.width = "2px"; // Inner circle size
    innerBullet.style.height = "2px";
    innerBullet.style.borderRadius = "50%"; // Inner circle rounded
    innerBullet.style.display = "inline-block";
  
    // Append the inner circle to the outer circle (bullet)
    bullet.appendChild(innerBullet);
  
    // Split the text into words
    const words = text.split(" ");
    
    // Extract specific words
    const firstWord = words.shift(); // Remove first word
    const secondWord = words.shift(); // Remove second word
    const lastWord = words.pop(); // Extract last word
    const remainingText = words.join(" "); // Remaining words (excluding first, second, and last)
  
    // Construct the innerHTML with the second word in black and the last word in highlight color
    listItem.innerHTML = `
      <span>${firstWord}</span> 
      <span style="color: black; font-weight: 500;">${secondWord}</span> 
      ${remainingText} 
      <span style="color: ${highlightColor}; font-weight: 500;">${lastWord}</span>
    `;
  
    // Append the custom double circular bullet to the list item
    listItem.insertBefore(bullet, listItem.firstChild);
  
    return listItem;
  };
  

  
  // Create the heading "Event:"
  const eventLabel = document.createElement("p");
  eventLabel.textContent = "Event";
  eventLabel.style.margin = "0";
  eventLabel.style.color = "#00a886"; // Blue color for heading
  eventLabel.style.fontWeight = "bold";
  eventLabel.style.fontSize = "16px";

  // Create the unordered list for the event details
  const eventDetail = document.createElement("ul");
  eventDetail.style.margin = "8px 0 0 -15px"; // Add margin and indentation
  eventDetail.style.color = "#333"; // Normal color for text
  eventDetail.style.listStyleType = "none"; // Remove default bullets
  eventDetail.style.fontSize = "14px";
 
  if (Number(automation_type_id) === 1){
  const eventBullet = createCustomBullet(
    "When Ticket is Created", // Text content
    "#2c5cc5", // Bullet color
    "#00a886" // Highlight color for the last word
  );
  eventDetail.appendChild(eventBullet);
  
  // Append the heading and the event detail to the container
  eventText.appendChild(eventLabel);
  eventText.appendChild(eventDetail);

  }

  const createCustomBullet1 = (text, bulletColor, highlightColor) => {
    const listItem = document.createElement("li");
    listItem.style.position = "relative"; // For positioning the custom bullet
    listItem.style.paddingLeft = "10px"; // Space for custom bullet
  
    // Create the custom double circular bullet using a span element
    const bullet = document.createElement("span");
    bullet.style.position = "absolute";
    bullet.style.left = "-15px"; // Bring the bullet closer to the text
    bullet.style.top = "50%"; // Center the bullet vertically
    bullet.style.transform = "translateY(-50%)"; // Center the bullet exactly
    bullet.style.width = "12px"; // Outer ring size
    bullet.style.height = "12px";
    bullet.style.border = `4px solid ${bulletColor || "#dcdfe1"}`; // Outer ring color and border size
    bullet.style.borderRadius = "50%"; // Make it a ring (circle with border)
    bullet.style.display = "inline-block";
  
    // Create the inner circle (smaller circle inside the outer ring)
    const innerBullet = document.createElement("span");
    innerBullet.style.position = "absolute";
    innerBullet.style.left = "50%";
    innerBullet.style.top = "50%";
    innerBullet.style.transform = "translate(-50%, -50%)"; // Centering the inner circle
    innerBullet.style.width = "2px"; // Inner circle size
    innerBullet.style.height = "2px";
    innerBullet.style.borderRadius = "50%"; // Inner circle rounded
    innerBullet.style.display = "inline-block";
  
    // Append the inner circle to the outer circle (bullet)
    bullet.appendChild(innerBullet);
  
    // Split the text into words
    const words = text.split(" ");
    
    // Extract specific words
    const firstWord = words.shift(); // Remove first word
    const secondWord = words.shift(); // Remove second word
    const lastFourWords = words.splice(-4).join(" "); // Get last four words
    const remainingText = words.join(" "); // Remaining words (excluding first, second, and last four)
  
    // Construct the innerHTML with the second word in black and the last four words in highlight color
    listItem.innerHTML = `
      <span>${firstWord}</span> 
      <span style="color: black; font-weight: 500;">${secondWord}</span> 
      ${remainingText} 
      <span style="color: ${highlightColor}; font-weight: 500;">${lastFourWords}</span>
    `;
  
    // Append the custom double circular bullet to the list item
    listItem.insertBefore(bullet, listItem.firstChild);
  
    return listItem;
  };
  

  
  if (Number(automation_type_id) === 3){
    const eventBullet = createCustomBullet1(
      "When Ticket is is checked every hour", // Text content
      "#2c5cc5", // Bullet color
      "#00a886" // Highlight color for the last word
    );
    eventDetail.appendChild(eventBullet);
    
    // Append the heading and the event detail to the container
    eventText.appendChild(eventLabel);
    eventText.appendChild(eventDetail);
  
    }
  // Create the conditions heading
  const conditionText = document.createElement("div");
  conditionText.textContent = "Condition";
  conditionText.style.marginBottom = "8px";
  conditionText.style.fontWeight = "bold";
  conditionText.style.color = "#e86f25"; // Green color for conditions heading
  conditionText.style.fontSize = "16px";
  
  // Create a container for the conditions list
  const conditionsList = document.createElement("ul");
  conditionsList.style.margin = "0 0 12px";
  conditionsList.style.padding = "8px";
  conditionsList.style.border = "1px solid #ddd";
  conditionsList.style.borderRadius = "4px";
  conditionsList.style.backgroundColor = "#fff";
  conditionsList.style.listStyleType = "none"; // Remove default bullet style
  conditionsList.style.fontSize = "14px";
  
 // Extract condition sets and operator
const conditionsArray1 = Array.isArray(content.conditions.condition_set_1)
? content.conditions.condition_set_1
: [];
const conditionsArray2 = Array.isArray(content.conditions.condition_set_2)
? content.conditions.condition_set_2
: [];
const operator = content.conditions.operator || "";




// Function to create a styled bullet point for conditions/actions
const createConditionBullet = (condition, bulletColor = "#dcdfe1") => {
  


  const listItem = document.createElement("li");
  listItem.style.position = "relative";
  listItem.style.paddingLeft = "30px"; // Space for bullet
  listItem.style.display = "flex"; // Prevents breaking lines
  listItem.style.alignItems = "center"; // Keeps elements aligned

  // Create custom bullet
  const bullet = document.createElement("span");
  bullet.style.position = "absolute";
  bullet.style.left = "0";
  bullet.style.top = "50%";
  bullet.style.transform = "translateY(-50%)";
  bullet.style.width = "12px";
  bullet.style.height = "12px";
  bullet.style.border = `4px solid ${bulletColor || "#dcdfe1"}`;
  bullet.style.borderRadius = "50%";

  // Inner circle of bullet
  const innerBullet = document.createElement("span");
  innerBullet.style.position = "absolute";
  innerBullet.style.left = "50%";
  innerBullet.style.top = "50%";
  innerBullet.style.transform = "translate(-50%, -50%)";
  innerBullet.style.width = "8px";
  innerBullet.style.height = "8px";
  innerBullet.style.borderRadius = "50%";

  bullet.appendChild(innerBullet);

  // **Formatting Condition with Colors**
  let formattedCondition = condition
    .replace(/<div/g, ' <div') // Add space before <div> tags if missing
    .replace(/<div\s+class\s*=\s*["']?SummaryKey["']?\s*>(.*?)<\/div>/gi, ' <span style="color: black; font-weight: 500;">$1</span> ') 
    .replace(/<div\s+class\s*=\s*["']?SummaryValue["']?\s*>(.*?)<\/div>/gi, ' <span style="color: #00a886; font-weight: 500;">$1</span> ') 
    .replace(/<div\s+class\s*=\s*["']?SummaryOperator["']?\s*>(.*?)<\/div>/gi, ' <span> $1 </span> ') // Ensure space around operators
    .replace(/>\s+</g, '> <')  // Ensures space between inline elements
    .replace(/\s+/g, ' ')      // Remove multiple spaces
    .trim();                   // Trim any leading/trailing spaces

 

  // // Set bullet first, then append formatted text
  listItem.appendChild(bullet);
  
  // Create a span for the condition text (for proper spacing)
  const textSpan = document.createElement("span");
  textSpan.innerHTML = formattedCondition;
  textSpan.style.marginLeft = "-5px"; // Ensure space between bullet and text
  listItem.appendChild(textSpan);

  console.log("✅ Final List Item InnerHTML:", listItem.innerHTML); // Log final output

  return listItem;
};


// Add conditions from condition_set_1
conditionsArray1.forEach((condition) => {
if (condition === "AND" || condition === "OR") {
  // Add operator as a separate text element
  const operatorItem = document.createElement("div");
  operatorItem.textContent = condition;
  operatorItem.style.color = "#6c757d";
  operatorItem.style.margin = "8px 0 5px 29px";
  conditionsList.appendChild(operatorItem);
} else {
  conditionsList.appendChild(createConditionBullet(condition, "#2c5cc5")); // Blue bullet
}
});

// Add operator between conditions (if available)
if (operator) {
const operatorItem = document.createElement("div");
operatorItem.textContent = operator;
operatorItem.style.color = "#000000";
operatorItem.style.margin = "8px 0";
operatorItem.style.fontSize = "14px";
operatorItem.style.fontweight="bold"
conditionsList.appendChild(operatorItem);
}

// Add conditions from condition_set_2
conditionsArray2.forEach((condition) => {
if (condition === "AND" || condition === "OR") {
  const operatorItem = document.createElement("div");
  operatorItem.textContent = condition;
  operatorItem.style.color = "#6c757d";
  operatorItem.style.margin = "8px 0 5px 29px";
  conditionsList.appendChild(operatorItem);
} else {
  conditionsList.appendChild(createConditionBullet(condition, "#2c5cc5")); // Blue bullet
}
});

// Create actions heading
const actionText = document.createElement("div");
actionText.textContent = "Action";
actionText.style.marginBottom = "8px";
actionText.style.fontWeight = "bold";
actionText.style.color = "#2c5cc5";
actionText.style.fontSize = "16px";

// Create actions content
const actionContent = document.createElement("ul");
actionContent.style.margin = "0";
actionContent.style.padding = "8px";
actionContent.style.border = "1px solid #ddd";
actionContent.style.borderRadius = "4px";
actionContent.style.backgroundColor = "#fff";
actionContent.style.listStyleType = "none";
actionContent.style.fontSize = "14px";

const actionsArray = Array.isArray(content.actions) ? content.actions : [];

// Add actions with custom bullets
actionsArray.forEach((action) => {
if (action === "AND" || action === "OR") {
  const operatorItem = document.createElement("div");
  operatorItem.textContent = action;
  operatorItem.style.color = "#6c757d";
  operatorItem.style.margin = "8px 0 5px 29px";
  actionContent.appendChild(operatorItem);
} else {
  actionContent.appendChild(createConditionBullet(action, "#2c5cc5")); // Blue bullet for actions
}
});
  
  // Append the label and line to the content box
  contentBox.appendChild(previewLabel);
  contentBox.appendChild(lineBelowLabel);
  
  scrollableContent.appendChild(eventText);
  scrollableContent.appendChild(conditionText);
  scrollableContent.appendChild(conditionsList);
  scrollableContent.appendChild(actionText);
  scrollableContent.appendChild(actionContent);
  
  // Append content to the scrollable wrapper
  
  contentBox.appendChild(scrollableContent);
  
  // Create fw-button element with "primary" color
  const closeButton = document.createElement("fw-button");
  closeButton.setAttribute("color", "primary");
  closeButton.textContent = "Close";
  closeButton.style.position = "absolute";
  closeButton.style.bottom = "16px"; // Distance from the bottom
  closeButton.style.right = "16px"; // Distance from the right
  closeButton.style.padding = "8px 16px"; // Padding for the button
  closeButton.style.borderRadius = "4px"; // Rounded corners
  closeButton.style.cursor = "pointer";
  
  // Close popup and remove overlay when the button is clicked
  closeButton.addEventListener("click", () => {
    document.body.removeChild(popupContainer);
    document.body.removeChild(overlay);
  });
  
  popupContainer.appendChild(popupHeader); // Fixed title
  popupContainer.appendChild(contentBox);
  
  popupContainer.appendChild(closeButton); // Close button
  
  // Append elements to the document
  document.body.appendChild(overlay);
  document.body.appendChild(popupContainer);
  
  }





let currentPage = 1;
const itemsPerPage = 5;

function normalizeText2(text) {
  return text
    .toLowerCase()
    .replace(/[.,\/#!$%\^&\*;:{}=\-_`~()]/g, "") // Remove punctuation
    .split(/\s+/) // Split words
    .sort() // Sort for consistency
    .join(" "); // Rejoin sorted words
}

function normalizeList(text) {
  return text
    ? text
        .split(",") // Convert to array
        .map((item) => item.trim().toLowerCase()) // Trim & lowercase
        .sort() // Sort to ensure same order
        .join(",") // Join back to a string
    : "";
}
function stripHTML2(htmlString) {
  // Create a temporary div to parse the HTML
  const div = document.createElement("div");
  div.innerHTML = htmlString;

  // Remove all elements except <img>
  [...div.querySelectorAll("*")].forEach(el => {
      if (el.tagName.toLowerCase() !== "img") {
          el.replaceWith(...el.childNodes);
      }
  });

  return div.innerHTML.trim(); // Return cleaned HTML
}
function removeImgTags(htmlString) {
return htmlString.replace(/<img\b[^>]*>/g, "").trim();
}

function displayGroupedRules(records, containerId) {
  const container = document.getElementById(containerId);
  if (!container) {
    console.error(`Container with ID "${containerId}" not found.`);
    return;
  }

  container.innerHTML = ""; // Clear container
  if (records.length === 0) {
    container.innerHTML = `
        <div style="
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            width: 100%;
            font-size: 24px;
            font-weight: bold;
            color: #333;
            margin-left: 400px; 
            text-align: center;
        ">
            No duplicate rules found.
        </div>`;
    return;
  }

  const groupedRules = new Map();

  records.forEach((record) => {
    const { data, display_id } = record;
    const { name, summary, position, updated_at, last_updated_by, affected_tickets_count, rule_id, automation_type_id, conditions, actions,agentName
    } = data;
  
    if (summary) {
      // console.log(`🔍 Original Summary: ${summary}`);
  
      // **Remove all HTML except <img> for display, but remove <img> for grouping**
      const cleanSummary = stripHTML2(summary);
  
      // **Ensure `actions` is a string before removing <img> tags**
      const actionsText = Array.isArray(actions) ? actions.join(" ") : String(actions || ""); 
      const cleanedActions = removeImgTags(actionsText); // Remove <img> from actions
  
      // console.log(`✅ Cleaned Summary: ${cleanSummary}`);
      // console.log(`🖼️ Actions without <img>: ${cleanedActions}`); // Log cleaned actions
  
      const normalizedSummary = normalizeText2(cleanSummary);
      const normalizedConditions = normalizeList(conditions);
      const normalizedActions = normalizeList(cleanedActions); // Use cleaned actions
  
      // **Generate Group Key (WITHOUT <img> tags)**
      const groupKey = `${normalizedSummary}|${normalizedConditions}|${normalizedActions}`;
  
      // console.log(`📌 Group Key: ${groupKey}`);
  
      if (!groupedRules.has(groupKey)) {
        groupedRules.set(groupKey, { originalSummary: cleanSummary, rules: [] });
      }
  
      groupedRules.get(groupKey).rules.push({
        name,
        position,
        summary,
        updated_at,
        last_updated_by,
        affected_tickets_count,
        rule_id,
        automation_type_id,
        display_id,
        agentName
      });
    }
  });    
  
  const groupedRulesArray = Array.from(groupedRules.values());
  const totalgroup = groupedRulesArray.length;
  console.log(totalgroup, "*********************");

  const totalPages = Math.ceil(totalgroup / itemsPerPage);
  currentPage = Math.max(1, Math.min(currentPage, totalPages)); // Ensure valid page number

  console.log("Total Pages:", totalPages, "Current Page:", currentPage);

  const startIdx = (currentPage - 1) * itemsPerPage;
  const paginatedRules = groupedRulesArray.slice(startIdx, startIdx + itemsPerPage);

  console.log("Displaying Records:", paginatedRules);

  let arrayLength = paginatedRules.length;
  console.log("Records Length:", arrayLength);

  // Display paginated rules
  paginatedRules.forEach((group) => {
    const rulesCount = group.rules.length;

    
    if (rulesCount === 1) {
        console.log(`Skipping group with only 1 rule: ${group.originalSummary}`);
        return; 
    }

    const groupContainer = document.createElement("div");
    groupContainer.style.border = "1px solid #ccc";
    groupContainer.style.padding = "16px";
    groupContainer.style.margin = "16px";
    groupContainer.style.borderRadius = "8px";
    groupContainer.style.backgroundColor = "#f5f7f9";
    groupContainer.style.width = "1200px";

    

    // ✅ Correctly loop through the rules array inside the group object
    group.rules.forEach(({ name, position, summary, updated_at, affected_tickets_count, display_id, rule_id, automation_type_id,agentName }, index) => {
      const card = document.createElement("div");
    card.style.border = "1px solid #ccc";
    card.style.padding = "16px";
    card.style.margin = "8px 0"
    card.style.fontFamily =
      "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif";
    card.style.borderRadius = "8px";
    card.style.backgroundColor = index === 0 ? "#fff" : "#e5f2fd";
    card.style.marginBottom = "10px";
    card.style.paddingBottom = "0";
   
   
      const cardHeader = document.createElement("div");
      cardHeader.style.display = "flex";
      cardHeader.style.justifyContent = "space-between";
      cardHeader.style.alignItems = "center";
      
      // Create a wrapper for the title
const cardTitle = document.createElement("h4");
cardTitle.style.margin = "0";
cardTitle.style.cursor = "pointer";
cardTitle.style.fontSize = "14px";
cardTitle.style.fontFamily = "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif";
cardTitle.style.color = "#183247";
cardTitle.style.transition = "color 0.2s ease";
cardTitle.style.fontWeight = "600"; 

// Create the serial number (position)
if (position) {
    const serialNumber = document.createElement("span");
    serialNumber.textContent = position + ". ";
    serialNumber.style.color = "#183247"; // Keep serial number color fixed
    cardTitle.appendChild(serialNumber);
}

// Create the actual name (clickable part)
const titleText = document.createElement("span");
titleText.textContent = name;
titleText.style.color = "#183247"; 
titleText.style.transition = "color 0.2s ease";

// Add hover effect for only the name
titleText.addEventListener("mouseover", () => {
    titleText.style.color = "#007bff"; // Change only name color on hover
});
titleText.addEventListener("mouseout", () => {
    titleText.style.color = "#183247"; // Reset name color when not hovering
});
titleText.addEventListener("click", () => {
    titleText.style.color = "#ff5733"; // Change title color on click
   

    
    // let ruleid=rule_id;
    console.log("ruleid",rule_id);
    // let automationid= automation_type_id;
    console.log("automationtypeid",automation_type_id);
    GetRules();
    async function GetRules() {
      //  console.log('GetRules called');
       try {
           const GetRulesResponse = await client.request.invokeTemplate("getid", {
               context: 
               { 
                ruleid: rule_id ,
                automationid:automation_type_id
               },
           });
   
           const responses = GetRulesResponse.response;
           const rulesData = JSON.parse(responses);
           console.log("Rules", rulesData);
           console.log("Rules", rulesData.summary.conditions);
           console.log("Rules", rulesData.summary.actions);
           if(automation_type_id === 1||automation_type_id === 3)
        {
           showPopupCard(rulesData.name, { conditions: rulesData.summary.conditions, actions:rulesData.summary.actions },automation_type_id);
      }else{
        showPopupCard1(rulesData.name, {performer:rulesData.summary.performer,events:rulesData.summary.events, conditions: rulesData.summary.conditions, actions:rulesData.summary.actions });
      }
    }
      catch (error) {
        console.error("Error in getting rules",error);
         
         }
    }
   

});

// Append name to title
cardTitle.appendChild(titleText);




      // Append title and actions to the cardHeader
      cardHeader.appendChild(cardTitle);
      // Create a container for the horizontal line and the gap
const cardContainer = document.createElement("div");

// Style the container to have a background color in the gap
cardContainer.style.backgroundColor = "#f0f0f0";  // Set the background color for the gap (change to desired color)
cardContainer.style.paddingBottom = "20px";  
cardContainer.style.marginLeft="-15px";
cardContainer.style.borderRadius = "4px";
cardContainer.style.width="102.7%";

// Create a horizontal line after the cardBody
const horizontalLine = document.createElement("div");
horizontalLine.style.height = "1px"; // Set the height to 1px for a thin line
horizontalLine.style.backgroundColor = "#ccc"; // Set the color of the horizontal line
horizontalLine.style.marginTop = "16px"; // Add space above the line (adjust as needed)
horizontalLine.style.width = "100%"; // Ensure the line stretches the full width of the container
horizontalLine.style.marginLeft="-3px";
      

      function truncateContent(content, maxLength, lines) {
        // Truncate the content to the desired number of characters
        let truncated = content;
      
        // Adjust for the desired line count and maximum length
        if (content.length > maxLength) {
          truncated = content.slice(0, maxLength) + "...";
        }
      
        // Break content into lines manually for multi-line truncation
        const words = truncated.split(" ");
        const result = [];
        let line = "";
        let currentLine = 1;
      
        for (let i = 0; i < words.length; i++) {
          if (line.length + words[i].length + 1 <= maxLength / lines) {
            line += (line ? " " : "") + words[i];
          } else {
            result.push(line);
            line = words[i];
            currentLine++;
            if (currentLine > lines) break; // Stop adding more lines if max lines are reached
          }
        }
      
        if (currentLine <= lines && line) {
          result.push(line);
        }
      
        return result.join(" ") + (currentLine > lines ? "..." : "");
      }
      function calculateLastModified(updated_at) {
        const updatedDate = new Date(updated_at);
        const currentDate = new Date();
    
        const diffInMilliseconds = currentDate - updatedDate;
        const seconds = Math.floor(diffInMilliseconds / 1000);
        const minutes = Math.floor(seconds / 60);
        const hours = Math.floor(minutes / 60);
        const days = Math.floor(hours / 24);
        const months = Math.floor(days / 30);  // Approximate months
        const years = Math.floor(days / 365);  // Approximate years
    
        if (years > 0) {
            return years === 1 ? "a year ago" : `${years} years ago`;
        } else if (months > 0) {
            return months === 1 ? "a month ago" : `${months} months ago`;
        } else if (days > 0) {
            return `${days} day${days > 1 ? "s" : ""} ago`;
        } else if (hours > 0) {
            return `${hours} hour${hours > 1 ? "s" : ""} ago`;
        } else if (minutes > 0) {
            return `${minutes} minute${minutes > 1 ? "s" : ""} ago`;
        } else {
            return "Just now";
        }
    }
    
    
      
      
      // console.log("updated at",calculateLastModified(updated_at));
      
 // Create a row for "Last Modified"
 const lastModifiedRow = document.createElement("div");
 lastModifiedRow.style.display = "grid";
 lastModifiedRow.style.gridTemplateColumns = "150px 150px 2px 150px 150px 2px 150px 150px"; // Consistent width for each section
 lastModifiedRow.style.alignItems = "center";
 lastModifiedRow.style.marginTop = "10px";
 lastModifiedRow.style.fontSize = "12px";
 lastModifiedRow.style.gap = "20px";
 lastModifiedRow.style.width = "100%"; // Ensures full width alignment
 
 const lastModifiedLabel = document.createElement("span");
 lastModifiedLabel.textContent = "Last Modified :";
 lastModifiedLabel.style.color = "#183247";
 lastModifiedLabel.style.fontSize = "12px";
 lastModifiedLabel.style.display = "inline-flex";
lastModifiedLabel.style.fontFamily =" -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif"
lastModifiedLabel.style.marginLeft = "40px"

 const lastModifiedValue = document.createElement("span");
 const lastModifiedText = calculateLastModified(updated_at);
 lastModifiedValue.textContent = lastModifiedText;
 lastModifiedValue.style.color = "#183247";
 lastModifiedValue.style.fontWeight = "600";
 lastModifiedValue.style.display = "inline-flex";
 lastModifiedValue.style.fontSize = "12px";
 lastModifiedValue.style.marginLeft = "-50px"
 lastModifiedValue.style.justifySelf = "start";
 lastModifiedValue.style.fontFamily =" -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif"

 const verticalLine = document.createElement("div");
 verticalLine.style.height = "20px";
 verticalLine.style.borderLeft = "2px solid #ccc";
 verticalLine.style.alignSelf = "stretch";
 
 lastModifiedRow.appendChild(lastModifiedLabel);
 lastModifiedRow.appendChild(lastModifiedValue);
 lastModifiedRow.appendChild(verticalLine);
 
//  const agentsid = last_updated_by;
//  console.log("agentsid", agentsid);
//  GetAgents();
 
//  async function GetAgents() {
//     //  console.log('GetAgents called');
//      try {
//          const GetAgentsResponse = await client.request.invokeTemplate('getAgents', {
//              context: { id: agentsid },
//          });
 
//          const responses = GetAgentsResponse.response;
//          const agentData = JSON.parse(responses);
        //  console.log("Name:", agentData.contact.name);
 
         const agentNameLabel = document.createElement("span");
         agentNameLabel.textContent = "By :";
         agentNameLabel.style.fontSize = "12px";
         agentNameLabel.style.color = "#183247";
         agentNameLabel.style.whiteSpace = "nowrap";
         agentNameLabel.style.marginLeft="149px"
         agentNameLabel.style.fontFamily =" -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif"

         const agentNameValue = document.createElement("span");
         agentNameValue.textContent = agentName;
         agentNameValue.style.color = "#183247";
         agentNameValue.style.fontWeight = "600";
         agentNameValue.style.whiteSpace = "nowrap";
         agentNameValue.style.fontFamily =" -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif"
         const verticalLine2 = document.createElement("div");
         verticalLine2.style.height = "20px";
         verticalLine2.style.borderLeft = "2px solid #ccc";
         verticalLine2.style.alignSelf = "stretch";
         verticalLine2.style.marginLeft = "100px";  // Increase for more right shift

 
         lastModifiedRow.appendChild(agentNameLabel);
         lastModifiedRow.appendChild(agentNameValue);
         lastModifiedRow.appendChild(verticalLine2);
 
         const affectedTicketsLabel = document.createElement("span");
         affectedTicketsLabel.textContent = "Impacted tickets (Last 7 days) : ";
         affectedTicketsLabel.style.fontSize = "12px";
         affectedTicketsLabel.style.color = "#183247";
         affectedTicketsLabel.style.marginLeft="140px";
         affectedTicketsLabel.style.whiteSpace = "nowrap";
         affectedTicketsLabel.style.fontFamily =" -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif"

         const affectedTicketsValue = document.createElement("span");
         affectedTicketsValue.textContent = affected_tickets_count === 0 ? "--" : affected_tickets_count;
         affectedTicketsValue.style.color = "#183247";
         affectedTicketsValue.style.fontWeight = "600";
         affectedTicketsValue.style.marginLeft ="134px"
         affectedTicketsValue.style.whiteSpace = "nowrap";
         affectedTicketsValue.style.fontFamily =" -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif"

         lastModifiedRow.appendChild(affectedTicketsLabel);
         lastModifiedRow.appendChild(affectedTicketsValue);
    // }
    
//     catch (error) {
//       console.error("Agents error",error);
//       if (error.status === 429) {
//         console.warn("⚠️API limit exceeded. App will reload 1 minute after");
//         document.getElementById("Automation-page").style.display = "none";
//         document.getElementById("Workflow-Automation-page").style.display = "none";
        
//         document.getElementById("no_user1").style.display = "block";
//       //   setTimeout(() => {
//       //     window.location.reload();
//       // }, 30000);
// }
// else if(error.status === 401){
//   document.getElementById("Automation-page").style.display = "none";
//   document.getElementById("Workflow-Automation-page").style.display = "none";
  
//   document.getElementById("no_user2").style.display = "block";

// } 
       
//        }
//   }







 
      const cardBody = document.createElement("div"); // Create a container for card content and actions
      cardBody.style.display = "flex"; // Flexbox to align items horizontally
      cardBody.style.justifyContent = "space-between"; // Ensure there's space between content and actions
      cardBody.style.alignItems = "flex-start"; // Align items to the top (optional, depending on your needs)
               

const truncatedContent = truncateContent(summary, 200, 2);

const cardContent = document.createElement("pre");
cardContent.textContent = truncatedContent;

// Style the card content
cardContent.style.marginTop = "8px";
cardContent.style.padding = "8px";
cardContent.style.color="#183247";
cardContent.style.fontweight="600";
cardContent.style.fontFamily= "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif";
cardContent.style.whiteSpace = "pre-wrap"; // Ensure text wraps
cardContent.style.overflow = "hidden"; // Hide overflow content
cardContent.style.textOverflow = "ellipsis"; // Add ellipsis for overflow
cardContent.style.maxWidth = "75%"; // Limit the card width to half the container's width
cardContent.style.fontSize="12px";
cardContent.style.marginLeft="15px";


     // Create the container for card actions
const cardActionsContainer = document.createElement("div");
cardActionsContainer.style.display = "flex"; // Display actions horizontally
cardActionsContainer.style.justifyContent = "flex-end"; // Align to the right
cardActionsContainer.style.marginTop = "10px"; // Add some spacing above the actions
cardActionsContainer.style.gap = "8px"; // Set space between the toggle and the delete icon



//       // Add fw-toggle
//       const fwToggle = document.createElement("fw-toggle");
//       fwToggle.setAttribute("size", "medium");
//       fwToggle.setAttribute("checked", "");
//       // Add event listener to handle state change
// fwToggle.addEventListener("fwChange", (event) => {
//   fwToggle.checked = event.detail.checked; // Keep the state as per user selection
//   console.log("Toggle state changed:", fwToggle.checked);
// });
// const fwToggle = document.createElement("fw-toggle");
// fwToggle.setAttribute("size", "medium");

// // Unique key for storing toggle state (Assuming each card has a unique rule ID)
// const ruleId = rule_id; // Ensure rule_id is unique per rule
// const storedState = localStorage.getItem(`toggleState_${ruleId}`);

// if (storedState !== null) {
//   fwToggle.checked = storedState === "true"; // Convert string to boolean
// } else {
//   fwToggle.setAttribute("checked", ""); // Default state
// }

// // Event listener to update localStorage on state change
// fwToggle.addEventListener("fwChange", (event) => {
//   const isChecked = event.detail.checked;
//   localStorage.setItem(`toggleState_${ruleId}`, isChecked);
//   fwToggle.checked = isChecked; // Ensure UI reflects stored state
//   console.log(`Toggle state changed for ${ruleId}:`, isChecked);
// });


        // Add fw-icon
        const fwIcon = document.createElement("fw-icon");
        fwIcon.setAttribute("name", "delete");
        fwIcon.setAttribute("size", "18");
        fwIcon.style.cursor = "pointer";
        fwIcon.style.color = "red"; // Set the color to red
        // Add a pointer cursor for interactivity
        fwIcon.title = "Delete";
        fwIcon.addEventListener("click", () => {
          console.log("ruleid inside entity deletion", rule_id);
         
      
          showDeletePopup(display_id); 
      
          function showDeletePopup(display_id) {
              currentRuleId = display_id; // Store the rule ID for deletion
              document.getElementById("deleteConfirmationPopup").style.display = "flex";
          }
      
          function hideDeletePopup() {
              document.getElementById("deleteConfirmationPopup").style.display = "none";
          }
      
          function removeDeletedRuleFromUI(display_id) {
              let ruleCard = document.querySelector(`[data-rule-id="${display_id}"]`);
              if (ruleCard) {
                  ruleCard.remove();
              }
          }
      
          
          async function confirmDeletion1(rule_id, automation_type_id) {
              console.log("📢 confirmDeletion1 function triggered with rule_id:", rule_id, "and automation_type_id:", automation_type_id);
      
              if (!rule_id || !automation_type_id) {
                  console.warn("⚠️ Missing rule_id or automation_type_id, aborting function.");
                  return;
              }
      
              try {
                  console.log("🚀 Sending request to delete rule...");
      
                  let getdeleteruleResponse1 = await client.request.invokeTemplate("deleterule", {
                      context: {
                          automationid: automation_type_id,
                          ruleid: rule_id,
                      },
                  });
      
                  console.log("✅ getdeleteruleResponse:", getdeleteruleResponse1);
      
                  if (getdeleteruleResponse1.status === 204) {
                      console.log("✅ Rule deleted successfully!");
                      hideDeletePopup();
                  } else {
                      console.warn("⚠️ Unexpected response:", getdeleteruleResponse1);
                  }
      
              } catch (error) {
                  console.error("❌ Error in confirmDeletion1:", error);
              }
          }
      
          async function entityconfirmDeletion() {
              if (!currentRuleId) return; // Ensure rule ID is available
      
              try {
                  console.log("Deleting rule with ID:", currentRuleId);
                  await newRulePloadDB5.delete(currentRuleId);
  
  
                  
              } catch (error) {
                  console.warn(` Error deleting record with Display ID ${currentRuleId}, but continuing...`);
                  const ruleIndex = records.findIndex(record => record.display_id === currentRuleId);
                if (ruleIndex !== -1) {
              records.splice(ruleIndex, 1);
               console.log(`✅ Rule ${currentRuleId} removed from records array.`);
                } else {
                 console.warn(`⚠️ Rule with display_id ${currentRuleId} not found in records array.`);
                 }
  
                  displayGroupedRules(records, containerId)
                   let toast = document.getElementById('type_toast');
                   toast.setAttribute('content', 'Rule deleted successfully');
                   toast.setAttribute('type', 'success');
                   toast.setAttribute('open', true);
       
                  
                   removeDeletedRuleFromUI(currentRuleId);
                   hideDeletePopup();
       
                   
                 
              }
          }
      
          // Attach event listeners
          document.getElementById("confirmDeleteBtn").addEventListener("click", async () => {
              try {
                  await confirmDeletion1(rule_id, automation_type_id); 
                  await entityconfirmDeletion(); 
      
              } catch (error) {
                  console.error("❌ Error in deletion process:", error);
              }
          });
      
          document.getElementById("cancelDeleteBtn").addEventListener("click", hideDeletePopup);
      });
      
  //   
      // Append fw-toggle and fw-icon to cardActions
      // cardActionsContainer.appendChild(fwToggle);

      cardActionsContainer.appendChild(fwIcon);
      card.appendChild(cardHeader);
      cardBody.appendChild(cardContent);
      cardBody.appendChild(cardActionsContainer);
      card.appendChild(cardBody);
      cardContainer.appendChild(horizontalLine);
      // card.appendChild(horizontalLine);
     
      cardContainer.appendChild(lastModifiedRow);
      card.appendChild(cardContainer)
      groupContainer.appendChild(card);
    });

    container.appendChild(groupContainer);
  });
  
  // Add pagination component
  addFwPagination(containerId,  records, totalgroup);
}


function addFwPagination(containerId, records, totalgroup) {
  console.log('Adding pagination to container:', containerId);

  let container = document.getElementById(containerId);

  if (!container) {
    console.warn(`Container with ID "${containerId}" not found.`);
    return;
  }

  if (totalgroup <= itemsPerPage) {
    console.log("Total records are less than or equal to items per page, skipping pagination.");
    return;
  }

  let existingPagination= container.querySelector("#fw-pagination-4");
  if (existingPagination) {
    existingPagination.remove(); // Remove old pagination if it exists
  }

  const pagination = document.createElement("fw-pagination");
  pagination.id = "fw-pagination-4";

  pagination.setAttribute("total", totalgroup);
  // pagination1.setAttribute("total", totalPages4 * arrayLength);

  // console.log("totalpages",totalPages4 * arrayLength)
  pagination.setAttribute("per-page", itemsPerPage);
  pagination.setAttribute("page", currentPage);

  console.log("Pagination Element:", pagination);

  const paginationWrapper = document.createElement("div");
  paginationWrapper.style.display = "flex";
  paginationWrapper.style.justifyContent = "flex-start";
  paginationWrapper.style.alignItems = "center";
  paginationWrapper.style.width = "100%";
  paginationWrapper.style.marginLeft = "70%";

  paginationWrapper.appendChild(pagination);
  container.appendChild(paginationWrapper);

  pagination.addEventListener("fwChange", (event) => {
    console.log("fwChange Event Triggered", event);
    currentPage = event.detail.page;
    console.log("Updated Page:", currentPage);

   // Update the displayed rules for the current container
   displayGroupedRules(records, containerId);


  });
}

 
function showPopupCard1(title, content) {
  console.log("logPopup" ,content);
  const overlay = document.createElement("div");
  overlay.style.position = "fixed";
  overlay.style.top = "0";
  overlay.style.left = "0";
  overlay.style.width = "100%";
  overlay.style.height = "100%";
  overlay.style.backgroundColor = "rgba(0, 0, 0, 0.3)"; // Semi-transparent dark background
  overlay.style.backdropFilter = "blur(5px)"; // Apply blur effect
  overlay.style.zIndex = "999"; // Ensure it appears above everything else
  
  // Create popup container
  const popupContainer = document.createElement("div");
  popupContainer.style.position = "fixed";
  popupContainer.style.top = "50%";
  popupContainer.style.left = "50%";
  popupContainer.style.transform = "translate(-50%, -50%)";
  popupContainer.style.width = "1000px"; // Increased default width
  popupContainer.style.maxWidth = "95%"; // Ensure it fits on smaller screens
  popupContainer.style.height = "60vh"; // Use viewport height to limit size
  popupContainer.style.backgroundColor = "#fff";
  popupContainer.style.border = "1px solid #ccc";
  popupContainer.style.boxShadow = "0 4px 8px rgba(0, 0, 0, 0.2)";
  popupContainer.style.borderRadius = "12px"; // Increased border radius for a smoother look
  popupContainer.style.overflow = "hidden"; // Prevent content overflow
  popupContainer.style.fontFamily =
    "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif"; // Apply a system font
  popupContainer.style.zIndex = "1000";
  popupContainer.style.display = "flex";
  popupContainer.style.flexDirection = "column";
  
  
  // Create header for title (fixed position)
  const popupHeader = document.createElement("div");
  popupHeader.style.padding = "16px 24px";
  popupHeader.style.borderBottom = "1px solid #ddd"; // Separate the title visually
  popupHeader.style.backgroundColor = "#fff";
  popupHeader.style.zIndex = "10"; // Ensure it appears above the scrollable content
  
  // Popup title
  const popupTitle = document.createElement("h2");
  popupTitle.textContent = title;
  popupTitle.style.paddingLeft = "15px"; // Move the title slightly to the right
  popupTitle.style.fontSize = "20px";
  popupTitle.style.color = "#333";
  popupTitle.style.textAlign = "left";
  popupHeader.appendChild(popupTitle);
  
  
  
  // Content wrapper (flex layout)
  const contentWrapper = document.createElement("div");
  contentWrapper.style.display = "flex";
  contentWrapper.style.flexDirection = "column";
  contentWrapper.style.flex = "1"; // Automatically take up available space
  contentWrapper.style.overflow = "hidden"; // Prevent content overflow
  
  // Content box (with fixed preview label)
  const contentBox = document.createElement("div");
  contentBox.style.flex = "1";
  contentBox.style.border = "1px solid #ddd";
  contentBox.style.borderRadius = "8px";
  contentBox.style.backgroundColor = "#f9f9f9";
  contentBox.style.padding = "16px";
  contentBox.style.margin = "16px 16px"; // Add vertical spacing
  contentBox.style.overflow = "hidden"; // Prevent outer scrolling
  contentBox.style.marginBottom = "75px"; // Add enough space for the close button
  
  
  // Preview label and line (sticky inside content box)
  const previewLabelContainer = document.createElement("div");
  previewLabelContainer.style.position = "sticky"; // Fix inside the content box
  previewLabelContainer.style.top = "0"; // Stick to the top
  previewLabelContainer.style.backgroundColor = "#f9f9f9"; // Match the content box background
  previewLabelContainer.style.zIndex = "1";
  previewLabelContainer.style.padding = "8px 0";
  
  const previewLabel = document.createElement("p");
  previewLabel.textContent = "Preview"; // Label text
  previewLabel.style.fontSize = "16px";
  previewLabel.style.fontWeight = "500";
  previewLabel.style.color = "#92a2b1";
  previewLabel.style.margin = "0";
  
  const lineBelowLabel = document.createElement("hr");
  lineBelowLabel.style.border = "none";
  lineBelowLabel.style.borderTop = "1px solid #ddd";
  lineBelowLabel.style.margin = "8px 0";
  
  previewLabelContainer.appendChild(previewLabel);
  previewLabelContainer.appendChild(lineBelowLabel);
  
  // Scrollable content area
  const scrollableContent = document.createElement("div");
  scrollableContent.style.overflowY = "auto"; // Enable vertical scrolling
  scrollableContent.style.height = "calc(100% - 40px)"; // Adjust to fit within the content box
  
  
  
    const eventText = document.createElement("div");
    eventText.style.marginBottom = "12px";
    
    const createCustomBullet = (text, bulletColor, highlightColor) => {
      const listItem = document.createElement("li");
      listItem.style.position = "relative"; // For positioning the custom bullet
      listItem.style.paddingLeft = "10px"; // Space for custom bullet
    
      // Create the custom double circular bullet using a span element
      const bullet = document.createElement("span");
      bullet.style.position = "absolute";
      bullet.style.left = "-15px"; // Bring the bullet closer to the text (adjust this value)
      bullet.style.top = "50%"; // Center the bullet vertically
      bullet.style.transform = "translateY(-50%)"; // Center the bullet exactly
      bullet.style.width = "12px"; // Outer ring size
      bullet.style.height = "12px";
      bullet.style.border = `4px solid ${bulletColor || "#dcdfe1"}`; // Outer ring color and border size
      bullet.style.borderRadius = "50%"; // Make it a ring (circle with border)
      bullet.style.display = "inline-block";
    
      // Create the inner circle (smaller circle inside the outer ring)
      const innerBullet = document.createElement("span");
      innerBullet.style.position = "absolute";
      innerBullet.style.left = "50%";
      innerBullet.style.top = "50%";
      innerBullet.style.transform = "translate(-50%, -50%)"; // Centering the inner circle
      innerBullet.style.width = "2px"; // Inner circle size
      innerBullet.style.height = "2px";
      // innerBullet.style.backgroundColor = bulletColor || "#dcdfe1"; // Inner circle color
      innerBullet.style.borderRadius = "50%"; // Inner circle rounded
      innerBullet.style.display = "inline-block";
    
      // Append the inner circle to the outer circle (bullet)
      bullet.appendChild(innerBullet);
   // Split the text into words
   const words = text.split(" ");
      
   // Extract specific words
   const firstWord = words.shift(); // Remove first word
   const secondWord = words.shift(); // Remove second word
   const lastWord = words.pop(); // Extract last word
   const remainingText = words.join(" "); // Remaining words (excluding first, second, and last)
 
   // Construct the innerHTML with the second word in black and the last word in highlight color
   listItem.innerHTML = `
     <span>${firstWord}</span> 
     <span style="color: black; font-weight: 500;">${secondWord}</span> 
     ${remainingText} 
     <span style="color: ${highlightColor}; font-weight: 500;">${lastWord}</span>
   `;
 
   // Append the custom double circular bullet to the list item
   listItem.insertBefore(bullet, listItem.firstChild);
 
   return listItem;
  
    };
    
    // Function to remove HTML tags while preserving spaces
// const stripHTMLWithSpacing = (htmlString) => {
//   const tempElement = document.createElement("div");
//   tempElement.innerHTML = htmlString;
//   return tempElement.textContent.replace(/\s+/g, ' ').trim(); // Ensure proper spacing
// };

   // Function to create a styled bullet point for conditions/actions
const createConditionBullet = (condition, bulletColor = "#dcdfe1") => {
  // console.log("🔹 Original Condition:", condition); // Log initial condition


  const listItem = document.createElement("li");
  listItem.style.position = "relative";
  listItem.style.paddingLeft = "30px"; // Space for bullet
  listItem.style.display = "flex"; // Prevents breaking lines
  listItem.style.alignItems = "center"; // Keeps elements aligned

  // Create custom bullet
  const bullet = document.createElement("span");
  bullet.style.position = "absolute";
  bullet.style.left = "0";
  bullet.style.top = "50%";
  bullet.style.transform = "translateY(-50%)";
  bullet.style.width = "12px";
  bullet.style.height = "12px";
  bullet.style.border = `4px solid ${bulletColor || "#dcdfe1"}`;
  bullet.style.borderRadius = "50%";

  // Inner circle of bullet
  const innerBullet = document.createElement("span");
  innerBullet.style.position = "absolute";
  innerBullet.style.left = "50%";
  innerBullet.style.top = "50%";
  innerBullet.style.transform = "translate(-50%, -50%)";
  innerBullet.style.width = "8px";
  innerBullet.style.height = "8px";
  innerBullet.style.borderRadius = "50%";

  bullet.appendChild(innerBullet);

  // **Formatting Condition with Colors**
  let formattedCondition = condition
    .replace(/<div/g, ' <div') // Add space before <div> tags if missing
    .replace(/<div\s+class\s*=\s*["']?SummaryKey["']?\s*>(.*?)<\/div>/gi, ' <span style="color: black; font-weight: 500;">$1</span> ') 
    .replace(/<div\s+class\s*=\s*["']?SummaryValue["']?\s*>(.*?)<\/div>/gi, ' <span style="color: #00a886; font-weight: 500;">$1</span> ') 
    .replace(/<div\s+class\s*=\s*["']?SummaryOperator["']?\s*>(.*?)<\/div>/gi, ' <span> $1 </span> ') // Ensure space around operators
    .replace(/>\s+</g, '> <')  // Ensures space between inline elements
    .replace(/\s+/g, ' ')      // Remove multiple spaces
    .trim();                   // Trim any leading/trailing spaces

  // console.log("🟢 Formatted Condition (With Colors):", formattedCondition);

  // **Convert to Plain Text with Spaces**
  // const plainTextCondition = stripHTMLWithSpacing(formattedCondition);
  // console.log("🔹 Plain Text Condition (With Spaces):", plainTextCondition);

  // // Set bullet first, then append formatted text
  listItem.appendChild(bullet);
  
  // Create a span for the condition text (for proper spacing)
  const textSpan = document.createElement("span");
  textSpan.innerHTML = formattedCondition;
  textSpan.style.marginLeft = "-5px"; // Ensure space between bullet and text
  listItem.appendChild(textSpan);

  console.log("✅ Final List Item InnerHTML:", listItem.innerHTML); // Log final output

  return listItem;
};
 // Create the heading "Event:"
    const eventLabel = document.createElement("p");
    eventLabel.textContent = "Event";
    eventLabel.style.margin = "0";
    eventLabel.style.color = "#00a886"; // Blue color for heading
    eventLabel.style.fontWeight = "bold";
    eventLabel.style.fontSize = "16px";
  
    // Create the unordered list for the event details
    const eventDetail = document.createElement("ul");
    eventDetail.style.margin = "8px 0 0 -15px"; // Add margin and indentation
    eventDetail.style.color = "#333"; // Normal color for text
    eventDetail.style.listStyleType = "none"; // Remove default bullets
    eventDetail.style.fontSize = "14px";
    // Add event detail with the custom bullet
    const eventBullet = createCustomBullet(
      "When Ticket is Updated", // Text content
      "#2c5cc5", // Bullet color
      "#00a886" // Highlight color for the last word
    );
    eventDetail.appendChild(eventBullet);
    
    // Append the heading and the event detail to the container
    eventText.appendChild(eventLabel);
    eventText.appendChild(eventDetail);
    // Extract performer text (assuming it's a single string)
      const performerText = typeof content.performer === "string" ? stripHTML(content.performer) : "";
      
      // Add the performer to the content if it exists
      if (performerText) {
        console.log("performerText",performerText)
        const performerItem = createConditionBullet(content.performer, "#2c5cc5"); // Green bullet for performer
        performerItem.style.marginBottom = "10px";
        performerItem.style.marginTop = "10px"; // Add space after performer text
        performerItem.style.marginLeft = "10px"; 
        performerItem.style.fontSize ="14px";
        eventText.appendChild(performerItem);
      }
  // Add Event data to Event content
const eventArray = (Array.isArray(content.events) && content.events.length) 
    ? content.events 
    : (Array.isArray(content.eventText) && content.eventText.length) 
        ? content.eventText 
        : (content.events ? [content.events] : (content.eventText ? [content.eventText] : []));

eventArray.forEach(event => {
    if (event) {
        const eventItem = createConditionBullet(event,  "#2c5cc5");
        eventItem.style.marginBottom = "10px";
        eventItem.style.marginTop = "10px"; // Add space after performer text
        eventItem.style.marginLeft = "10px"; 
        eventItem.style.fontSize ="14px";
        eventText.appendChild(eventItem);

    }
});
     
    
  // Create the conditions heading
  const conditionText = document.createElement("div");
  conditionText.textContent = "Condition";
  conditionText.style.marginBottom = "8px";
  conditionText.style.fontWeight = "bold";
  conditionText.style.color = "#e86f25"; // Green color for conditions heading
  conditionText.style.fontSize = "16px";
  
  // Create a container for the conditions list
  const conditionsList = document.createElement("ul");
  conditionsList.style.margin = "0 0 12px";
  conditionsList.style.padding = "8px";
  conditionsList.style.border = "1px solid #ddd";
  conditionsList.style.borderRadius = "4px";
  conditionsList.style.backgroundColor = "#fff";
  conditionsList.style.listStyleType = "none"; // Remove default bullet style
  conditionsList.style.fontSize = "14px";
  
 // Extract condition sets and operator
const conditionsArray1 = Array.isArray(content.conditions.condition_set_1)
? content.conditions.condition_set_1
: [];
const conditionsArray2 = Array.isArray(content.conditions.condition_set_2)
? content.conditions.condition_set_2
: [];
const operator = content.conditions.operator || "";
console.log("conditions array 1",conditionsArray1);




// // Create condition list container
// const conditionsList = document.createElement("ul");
// conditionsList.style.listStyleType = "none";
// conditionsList.style.padding = "0";

// Add conditions from condition_set_1
conditionsArray1.forEach((condition) => {
if (condition === "AND" || condition === "OR") {
  // Add operator as a separate text element
  const operatorItem = document.createElement("div");
  operatorItem.textContent = condition;
  operatorItem.style.color = "#6c757d";
  operatorItem.style.margin = "8px 0 5px 29px";
  conditionsList.appendChild(operatorItem);
} else {
  conditionsList.appendChild(createConditionBullet(condition, "#2c5cc5")); // Blue bullet
}
});

// Add operator between conditions (if available)
if (operator) {
const operatorItem = document.createElement("div");
operatorItem.textContent = operator;
operatorItem.style.color = "#000000";
operatorItem.style.margin = "8px 0";
operatorItem.style.fontSize = "14px";
operatorItem.style.fontweight = "500";
conditionsList.appendChild(operatorItem);
}

// Add conditions from condition_set_2
conditionsArray2.forEach((condition) => {
if (condition === "AND" || condition === "OR") {
  const operatorItem = document.createElement("div");
  operatorItem.textContent = condition;
  operatorItem.style.color = "#6c757d";
  operatorItem.style.margin = "8px 0 5px 29px";
  conditionsList.appendChild(operatorItem);
} else {
  conditionsList.appendChild(createConditionBullet(condition, "#2c5cc5")); // Blue bullet
}
});

// Create actions heading
const actionText = document.createElement("div");
actionText.textContent = "Action";
actionText.style.marginBottom = "8px";
actionText.style.fontWeight = "bold";
actionText.style.color = "#2c5cc5";
actionText.style.fontSize = "16px";

// Create actions content
const actionContent = document.createElement("ul");
actionContent.style.margin = "0";
actionContent.style.padding = "8px";
actionContent.style.border = "1px solid #ddd";
actionContent.style.borderRadius = "4px";
actionContent.style.backgroundColor = "#fff";
actionContent.style.listStyleType = "none";
actionContent.style.fontSize = "14px";

const actionsArray = Array.isArray(content.actions) ? content.actions : [];

// Add actions with custom bullets
actionsArray.forEach((action) => {
if (action === "AND" || action === "OR") {
  const operatorItem = document.createElement("div");
  operatorItem.textContent = action;
  operatorItem.style.color = "#6c757d";
  operatorItem.style.margin = "8px 0 5px 29px";
  actionContent.appendChild(operatorItem);
} else {
  actionContent.appendChild(createConditionBullet(action, "#2c5cc5")); // Blue bullet for actions
}
});
  
  // Append the label and line to the content box
  contentBox.appendChild(previewLabel);
  contentBox.appendChild(lineBelowLabel);
  
  scrollableContent.appendChild(eventText);
  scrollableContent.appendChild(conditionText);
  scrollableContent.appendChild(conditionsList);
  scrollableContent.appendChild(actionText);
  scrollableContent.appendChild(actionContent);
  
  // Append content to the scrollable wrapper
  
  contentBox.appendChild(scrollableContent);
  
  // Create fw-button element with "primary" color
  const closeButton = document.createElement("fw-button");
  closeButton.setAttribute("color", "primary");
  closeButton.textContent = "Close";
  closeButton.style.position = "absolute";
  closeButton.style.bottom = "16px"; // Distance from the bottom
  closeButton.style.right = "16px"; // Distance from the right
  closeButton.style.padding = "8px 16px"; // Padding for the button
  closeButton.style.borderRadius = "4px"; // Rounded corners
  closeButton.style.cursor = "pointer";
  
  // Close popup and remove overlay when the button is clicked
  closeButton.addEventListener("click", () => {
    document.body.removeChild(popupContainer);
    document.body.removeChild(overlay);
  });
  
  popupContainer.appendChild(popupHeader); // Fixed title
  popupContainer.appendChild(contentBox);
  // popupContainer.appendChild(headerContainer); // Fixed preview label and line
  // popupContainer.appendChild(wrapper); // Scrollable content
  popupContainer.appendChild(closeButton); // Close button
  
  // Append elements to the document
  document.body.appendChild(overlay);
  document.body.appendChild(popupContainer);
  
  }

  const normalizeText5 = (text) => {
    return text
        ? text
            .toLowerCase() // Convert everything to lowercase
            .split(/\s+/) // Split by spaces
            .filter(word => word.trim() !== "") // Remove empty words
            .sort() // Sort words alphabetically
            .join(" ") // Join words back into a string
        : "";
  };
  
  // Function to normalize, sort, and format list-based values (Case-Insensitive)
  const normalizeList5 = (value, label) => {
    if (!value) return "";
  
    const list = value
        .toLowerCase() // Convert everything to lowercase
        .split(/\s*[,|]\s*/) // Split by commas or pipes (remove spaces)
        .map((v) => normalizeText5(v)) // Normalize each item in the list
        .sort(); // Sort alphabetically
  
    console.log(`🔹 Normalized ${label}:`, list);
    return list.join(",");
  };
  
  // Function to find duplicate rules (Case-Insensitive)
  function findDuplicateRulestype4(records) { 
    console.log("function called");
  
    const seenRules = new Map(); // Store unique rules with their first occurrence
    const duplicateRecords = []; // Store all duplicate records
  
    // Function to remove all <img> tags from HTML content
    const stripImageTags = (html) => html ? html.replace(/<img[^>]*>/gi, "") : "";
  
    records.forEach((record) => {
        const { summary, conditions, actions, operator, events, performer, active } = record.data;
  
        if (!active) return; // Skip inactive records
  
        console.log("✅ Active Record:", record);
  
        // Normalize and sort fields (Ensure **case-insensitive** processing)
        const normalizedSummary = normalizeText5(summary);
        const normalizedConditions = normalizeList5(conditions, "Conditions");
        const normalizedActions = normalizeList5(stripImageTags(actions), "Actions");
        const normalizedEvents = normalizeList5(events, "Events");
        const normalizedPerformer = normalizeList5(performer, "Performer");
        const normalizedOperator = operator ? operator.trim().toLowerCase() : null; // Ensure lowercase
  
        console.log("🔹 Normalized Summary:", normalizedSummary);
        console.log("🔹 Normalized Conditions:", normalizedConditions);
        console.log("🔹 Normalized Actions:", normalizedActions);
        console.log("🔹 Normalized Events:", normalizedEvents);
        console.log("🔹 Normalized Performer:", normalizedPerformer);
        console.log("🔹 Normalized Operator:", normalizedOperator);
  
        // Create a unique key to compare records (All in lowercase now)
        const recordKey = `${normalizedSummary}|${normalizedConditions}|${normalizedActions}|${normalizedOperator}|${normalizedEvents}|${normalizedPerformer}`;
  
        console.log("🔍 Generated Record Key:", recordKey);
  
        if (seenRules.has(recordKey)) {
            console.log("⚠️ Duplicate Found:", record.display_id);
            
            if (!duplicateRecords.includes(seenRules.get(recordKey))) {
                duplicateRecords.push(seenRules.get(recordKey)); // Add original rule
            }
            duplicateRecords.push(record); // Add duplicate rule
        } else {
            seenRules.set(recordKey, record);
        }
    });
  
    return duplicateRecords;
  }
  
  



  
async function handleDuplicateRulestype4() {
  if (isFetchingType4 || type4 > 0) return; // Stop if already fetching or has run before

  isFetchingType4 = true; // Set flag to true before execution starts
  console.log("handleDuplicateRulestype4 called");

  try {
    const duplicatesType4 = await Filterrecords(4); // Get duplicate records
    console.log("🔄 Final duplicate records:", duplicatesType4);

    displayGroupedRules(duplicatesType4, "TicketUpdates"); // Display grouped rules

    type4++; // ✅ Increment count to prevent multiple calls
  } catch (error) {
    console.error("Error handling duplicate rules for type 4:", error);
  } finally {
    isFetchingType4 = false; // ✅ Reset flag after execution completes
  }
}



async function handleDuplicateRulestype3() {
  if (isFetchingType3 || type3 > 0) return; // Stop if already fetching or has run before

  isFetchingType3 = true; // Set flag to true before execution starts
  console.log("handleDuplicateRulestype3 called");

  try {
    const duplicatesType3 = await Filterrecords(3); // Get duplicate records
    console.log("🔄 Final duplicate records for hourly triggers:", duplicatesType3);

    displayGroupedRules(duplicatesType3, "HourlyTriggers"); // Display grouped rules

    type3++; // ✅ Increment count to prevent multiple calls
  } catch (error) {
    console.error("Error handling duplicate rules for type 3:", error);
  } finally {
    isFetchingType3 = false; // ✅ Reset flag after execution completes
  }
}

  


how these program works in order of working explain
ASSISTANT
Certainly! Here's a detailed walkthrough explaining **how the provided program works step-by-step, in order**, from initialization to UI rendering and duplicate detection:

---

## Overview

This program is for managing and displaying rule automations (Ticket Creation, Updates, Hourly triggers) with features including:

- Role-based access control.
- Fetching and caching agents and rules via API/pagination.
- Detecting duplicates among rules.
- Pagination and dynamic UI rendering.
- Rule deletion with confirmation and real-time UI update.
- Persistent tab state on page reload.
- Loading indicators and banners.

---

## Step-by-Step Flow

### 1. **Initialization on Page Load**

- When the page is loaded (`DOMContentLoaded` event):
  - `setupTabListener("Automation-page", "LastVisitedTab")` runs:
    - This function waits until `client` is initialized.
    - Then, it fetches the last selected tab from IndexedDB (`TabDB`) and restores the UI to that tab.
    - Attaches an event listener on tabs to store the currently selected tab for persistence.
  - A progress bar element is initialized in the UI for visual feedback.

### 2. **App Initialization (`init()` function)**

- `init()` is called immediately (after declarations).
- It awaits `app.initialized()` which gets the `client` context reference.
- It attaches an event handler for the app activation event (`client.events.on("app.activated")`) that triggers `RoleAccess()`.

---

### 3. **Role-Based Access Control (`RoleAccess()`)**

- Fetches installation parameters (`iparams`) which contain:
  - `accessvalue`: array of allowed agents, roles, or groups.
  - `fd_fields`: type of access control ('agent', 'role', or 'group').
- Fetches current logged-in user data (`loggedInUser`) to get their agent ID, group IDs, and role IDs.
- Checks if the user belongs to allowed access under the specified type.
- If **access is granted**:
  - Displays the main automation content.
  - Hides the "no access" page.
  - Calls `checkAndSetButtonState()` and `initializeDatabase()` for further data fetching and UI setup.
- If **access is denied**:
  - Displays the "no access" message/page.
  - Hides the automation content.

---

### 4. **Button State and Loading Banner (`checkAndSetButtonState()`)**

- Checks a persistent stored value in `"RulesDB"` to see if the button should be enabled.
- If button should be disabled (no rules loaded/stored yet):
  - Disables the button.
  - Shows a loading banner that tells the user to wait.
  - Keeps checking every 60 seconds using an interval until the button can be enabled.
- Once the button is enabled:
  - Hides and removes the loading banner.
  - Stops the periodic check.

---

### 5. **Database Initialization (`initializeDatabase()`)**

- Uses `client.db.entity()` to get a reference to entity storage (local DB abstraction).
- The entity `newRulePloadDB5` is stored globally for further fetched rule data management.
- Fetches the schema of the entity to understand its structure (mostly logging).

---

### 6. **Fetching Agents Data (`GetAgents()`)**

- Uses recursive paginated `invokeTemplate('recentagents', { page })` API call wrapper.
- Accumulates agents into an array, recursively fetching until no more pages.
- Stores the fetched agents into global `globalAgents` variable.
- Handles unauthorized (401) or rate limit (429) errors gracefully by showing "no access" pages.

---

### 7. **Fetching Different Types of Rules**

- Functions `listrules()`, `listupdaterules()`, and `listhourlyrules()` recursively fetch paginated rules for:
  - Ticket Creation (type ID 1).
  - Ticket Updates (type ID 4).
  - Hourly triggers (type ID 3).
- Stored rules are filtered by `active` status and accumulated globally.
- Errors (401 unauthorized, 429 rate limit) are handled and appropriate "no access" UI is shown.

---

### 8. **Detecting Duplicate Rules**

- `findDuplicatesWithinType()` and similar specialized `findDuplicateRulestype1and3()`, `findDuplicateRulestype4()` compare fetched rules to find duplicates.
- Deduplication criteria:
  - Deep comparison of rule summary, conditions, and actions.
  - Conditions and actions are normalized by:
    - Stripping HTML.
    - Sorting arrays for consistent comparison.
    - Lowercasing strings.
- Duplicate sets are stored separately per automation type (`duplicatesType1`, `duplicatesType3`, `duplicatesType4`).
- This logic ensures visually or logically duplicate rules are detected even if formatted differently.

---

### 9. **Displaying Rules and Duplicates (`displayGroupedRules()`, `displayGroupedRules4()`, `processAndDisplayDuplicates()`)**

- Duplicate groups are rendered in the UI with pagination support.
- Rules in a group share the same normalized conditions+actions.
- UI cards:
  - Show rule name.
  - Show truncated description/content preview.
  - Show detailed info on clicking rule title (popup).
  - Show last modified and agent info.
  - Include delete icon to remove rule.
- Pagination uses `<fw-pagination>` web component with event handlers to switch pages and update visible groups.
- Handling for different automation types and containers (`"Ticketcreation1"`, `"TicketUpdates1"`, `"HourlyTriggers1"`).
- Styles and layout are dynamically created for user-friendly presentation.

---

### 10. **Rule Detail Popups**

- Clicking a rule title opens a popup card that:
  - Shows event details, conditions, and actions with formatted bullets and colors.
  - Has a close button.
- Structure adapts for different automation types.
- Popups have backdrop blur to isolate focus.

---

### 11. **Deleting Rules**

- Clicking the delete icon shows a confirmation popup.
- On confirmation:
  - Calls the deletion API via `invokeTemplate("deleterule")` with automation and rule IDs.
  - Deletes the rule record from both remote API and local entity storage.
  - Removes deleted rule from the duplicates array.
  - Updates the displayed UI by re-rendering duplicate groups without the deleted rule.
  - Shows success or error toast messages using an app-provided toast element.
- Loading progress bar shows progress for deletion operations.

---

### 12. **Utility and Helper Functions**

- HTML stripping and normalization helpers (`stripHTML4`, etc.) clean and compare textual fields.
- Deep comparison of objects considering HTML content and array order.
- Pagination state management.
- Text truncation for clean UI previews.
- Date calculation to show "Last modified" in human-friendly form ("3 days ago").
- Display agents' names based on stored agent data.
- Recursive database fetch with pagination (using `marker`) to collect all records.
- Persistent state via IndexedDB (`client.db`).

---

## Overall Program Flow Summary

1. **On page load:** Setup tab persistence and progress bar.
2. **Initialize app:** Get app client and register activate event.
3. **On activate:** Check user role/group/agent access.
4. **If authorized:** Show main content, setup button state, initialize local DB entity.
5. **Fetch user agents and rules (paginated).**
6. **Detect duplicate rules based on normalized content.**
7. **Render grouped duplicates with pagination & details.**
8. **Allow deleting rules with confirmation, API update, and UI re-render.**
9. **Offer popups for rule full detail previews.**
10. **Handle loading states, error states, and UI feedback throughout.**

---

If you want, I can also provide a flowchart or sequence diagram, or further clarify any specific function or flow behavior!

turns-00069.parquet:31542

85ce498a943fd5fd6313c468
turn 1/1gpt-4.1-mini-2025-04-14FrenchUnited Kingdom407 words
degenerate_repetitionAbsentFinal dense release
USER
     Goal
    Traduire toutes les valeurs textuelles présentes dans une liste d’objets d’une recette de cuisine de en (ISO 639) vers pt (ISO 639), en respectant le contexte culinaire.

    Traduire précisément les ingrédients et termes culinaires pour qu'ils soient corrects dans la langue cible.
    Maintenir la structure JSON intacte, en ne modifiant que les valeurs.
    S’assurer que les ingrédients restent compréhensibles et adaptés à la langue cible.

    Return Format
    Tu dois renvoyer une liste d’objets sous la forme reçu.
    - Chaque valeur doit être correctement traduite en pt.
    - Les ingrédients doivent être adaptés à la langue cible.
    - Aucune clé ne doit être modifiée.

    Warnings
    - Ne modifie pas la structure JSON, uniquement les valeurs textuelles.
    - Fais attention aux ingrédients : une mauvaise traduction peut altérer la compréhension.
    - Ne laisse aucune valeur non traduite.
    - Ne renvoie que le JSON, sans explication.

    Context Dump
    Langue source : en (ISO 639)
    Langue cible : pt (ISO 639)
    Données à traduire :

    [
  {
    "recipeCode": "57b6eaedbde040a3ab93c6b1f847a7e2",
    "updated": "2025-04-21T13:38:59.247Z",
    "title": "Seven-Grain Bread",
    "subtitle": "A multigrain bread made with white flour. Seven-grain cereal is typically available in most supermarkets.",
    "description": "This recipe provides a simple method for creating a multigrain bread using a bread machine.",
    "ingredients": [
      {
        "section": "For the recipe",
        "ingredients": [
          "(315 ml) water",
          "(21 g) unsalted butter",
          "(248 g) bread flour",
          "(26 g) sugar",
          "(60 g) cup seven-grain cereal",
          "(12 g) nonfat dry milk powder",
          "yeast"
        ]
      }
    ],
    "instructions": [
      "Place the ingredients into the bread machine pan according to your manufacturer's recommended order.",
      "Choose the basic/white bread cycle and set the crust color to medium/normal."
    ],
    "notes_ingredients": "",
    "notes_instructions": ""
  }
]

    
ASSISTANT
[
  {
    "recipeCode": "57b6eaedbde040a3ab93c6b1f847a7e2",
    "updated": "2025-04-21T13:38:59.247Z",
    "title": "Pão de Sete Grãos",
    "subtitle": "Um pão multigrãos feito com farinha de trigo branca. Cereal de sete grãos geralmente está disponível na maioria dos supermercados.",
    "description": "Esta receita oferece um método simples para criar um pão multigrãos usando uma máquina de fazer pão.",
    "ingredients": [
      {
        "section": "Para a receita",
        "ingredients": [
          "(315 ml) água",
          "(21 g) manteiga sem sal",
          "(248 g) farinha de trigo para pão",
          "(26 g) açúcar",
          "(60 g) cereal de sete grãos",
          "(12 g) leite em pó desnatado",
          "fermento biológico"
        ]
      }
    ],
    "instructions": [
      "Coloque os ingredientes na forma da máquina de pão seguindo a ordem recomendada pelo fabricante.",
      "Escolha o ciclo básico/pão branco e ajuste a cor da crosta para médio/normal."
    ],
    "notes_ingredients": "",
    "notes_instructions": ""
  }
]

turns-00069.parquet:31543

fc89c5c3e53a5768ea65a918
turn 1/1gpt-4.1-mini-2025-04-14FrenchUnited States324 words
degenerate_repetitionAbsentFinal dense release
USER
     Goal
    Traduire toutes les valeurs textuelles présentes dans une liste d’objets d’une recette de cuisine de en (ISO 639) vers zh (ISO 639), en respectant le contexte culinaire.

    Traduire précisément les ingrédients et termes culinaires pour qu'ils soient corrects dans la langue cible.
    Maintenir la structure JSON intacte, en ne modifiant que les valeurs.
    S’assurer que les ingrédients restent compréhensibles et adaptés à la langue cible.

    Return Format
    Tu dois renvoyer une liste d’objets sous la forme reçu.
    - Chaque valeur doit être correctement traduite en zh.
    - Les ingrédients doivent être adaptés à la langue cible.
    - Aucune clé ne doit être modifiée.

    Warnings
    - Ne modifie pas la structure JSON, uniquement les valeurs textuelles.
    - Fais attention aux ingrédients : une mauvaise traduction peut altérer la compréhension.
    - Ne laisse aucune valeur non traduite.
    - Ne renvoie que le JSON, sans explication.

    Context Dump
    Langue source : en (ISO 639)
    Langue cible : zh (ISO 639)
    Données à traduire :

    [
  {
    "recipeCode": "57b6eaedbde040a3ab93c6b1f847a7e2",
    "updated": "2025-04-21T13:38:59.247Z",
    "title": "Seven-Grain Bread",
    "subtitle": "A multigrain bread made with white flour. Seven-grain cereal is typically available in most supermarkets.",
    "description": "This recipe provides a simple method for creating a multigrain bread using a bread machine.",
    "ingredients": [
      {
        "section": "For the recipe",
        "ingredients": [
          "(315 ml) water",
          "(21 g) unsalted butter",
          "(248 g) bread flour",
          "(26 g) sugar",
          "(60 g) cup seven-grain cereal",
          "(12 g) nonfat dry milk powder",
          "yeast"
        ]
      }
    ],
    "instructions": [
      "Place the ingredients into the bread machine pan according to your manufacturer's recommended order.",
      "Choose the basic/white bread cycle and set the crust color to medium/normal."
    ],
    "notes_ingredients": "",
    "notes_instructions": ""
  }
]

    
ASSISTANT
```json
[
  {
    "recipeCode": "57b6eaedbde040a3ab93c6b1f847a7e2",
    "updated": "2025-04-21T13:38:59.247Z",
    "title": "七谷面包",
    "subtitle": "一种使用白面粉制作的多谷物面包。七谷麦片通常在大多数超市有售。",
    "description": "本食谱提供了一种使用面包机制作多谷物面包的简易方法。",
    "ingredients": [
      {
        "section": "配方用料",
        "ingredients": [
          "(315 毫升)水",
          "(21 克)无盐黄油",
          "(248 克)高筋面粉",
          "(26 克)白糖",
          "(60 克)七谷麦片",
          "(12 克)脱脂奶粉",
          "酵母"
        ]
      }
    ],
    "instructions": [
      "按照制造商推荐的顺序将食材放入面包机内锅中。",
      "选择基础/白面包程序,设置面包皮颜色为中等/正常。"
    ],
    "notes_ingredients": "",
    "notes_instructions": ""
  }
]
```

turns-00069.parquet:31544

9540aa03e08dbbec8a378b5d
turn 1/1gpt-4.1-mini-2025-04-14FrenchBelarus406 words
degenerate_repetitionAbsentFinal dense release
USER
     Goal
    Traduire toutes les valeurs textuelles présentes dans une liste d’objets d’une recette de cuisine de en (ISO 639) vers es (ISO 639), en respectant le contexte culinaire.

    Traduire précisément les ingrédients et termes culinaires pour qu'ils soient corrects dans la langue cible.
    Maintenir la structure JSON intacte, en ne modifiant que les valeurs.
    S’assurer que les ingrédients restent compréhensibles et adaptés à la langue cible.

    Return Format
    Tu dois renvoyer une liste d’objets sous la forme reçu.
    - Chaque valeur doit être correctement traduite en es.
    - Les ingrédients doivent être adaptés à la langue cible.
    - Aucune clé ne doit être modifiée.

    Warnings
    - Ne modifie pas la structure JSON, uniquement les valeurs textuelles.
    - Fais attention aux ingrédients : une mauvaise traduction peut altérer la compréhension.
    - Ne laisse aucune valeur non traduite.
    - Ne renvoie que le JSON, sans explication.

    Context Dump
    Langue source : en (ISO 639)
    Langue cible : es (ISO 639)
    Données à traduire :

    [
  {
    "recipeCode": "57b6eaedbde040a3ab93c6b1f847a7e2",
    "updated": "2025-04-21T13:38:59.247Z",
    "title": "Seven-Grain Bread",
    "subtitle": "A multigrain bread made with white flour. Seven-grain cereal is typically available in most supermarkets.",
    "description": "This recipe provides a simple method for creating a multigrain bread using a bread machine.",
    "ingredients": [
      {
        "section": "For the recipe",
        "ingredients": [
          "(315 ml) water",
          "(21 g) unsalted butter",
          "(248 g) bread flour",
          "(26 g) sugar",
          "(60 g) cup seven-grain cereal",
          "(12 g) nonfat dry milk powder",
          "yeast"
        ]
      }
    ],
    "instructions": [
      "Place the ingredients into the bread machine pan according to your manufacturer's recommended order.",
      "Choose the basic/white bread cycle and set the crust color to medium/normal."
    ],
    "notes_ingredients": "",
    "notes_instructions": ""
  }
]

    
ASSISTANT
[
  {
    "recipeCode": "57b6eaedbde040a3ab93c6b1f847a7e2",
    "updated": "2025-04-21T13:38:59.247Z",
    "title": "Pan de Siete Cereales",
    "subtitle": "Un pan multigrano hecho con harina blanca. El cereal de siete cereales suele estar disponible en la mayoría de supermercados.",
    "description": "Esta receta proporciona un método simple para crear un pan multigrano usando una panificadora.",
    "ingredients": [
      {
        "section": "Para la receta",
        "ingredients": [
          "(315 ml) agua",
          "(21 g) mantequilla sin sal",
          "(248 g) harina de pan",
          "(26 g) azúcar",
          "(60 g) taza de cereal de siete cereales",
          "(12 g) leche en polvo desnatada",
          "levadura"
        ]
      }
    ],
    "instructions": [
      "Coloque los ingredientes en la cubeta de la panificadora según el orden recomendado por el fabricante.",
      "Seleccione el ciclo básico/de pan blanco y ajuste el color de la corteza a medio/normal."
    ],
    "notes_ingredients": "",
    "notes_instructions": ""
  }
]