// import React, { useEffect, useState, useRef } from "react";
// import { FwSpinner } from "@freshworks/crayons/react";
// import { Pie, Doughnut } from "react-chartjs-2";
// import { Chart as ChartJS, ArcElement, Tooltip, Legend } from "chart.js";

// ChartJS.register(ArcElement, Tooltip, Legend);

// // 🥧 Top 10 High Impact Chart (Pie)
// const ImpactPieChart = ({ rules, title }) => {
//   if (!rules || rules.length === 0) return null;

//   const labels = rules.map((r) => r.name || r.id || `Rule ${r.rule_id}`);
//   const dataValues = rules.map((r) => r.impact);

//   const data = {
//     labels,
//     datasets: [
//       {
//         label: "Impact Score",
//         data: dataValues,
//         backgroundColor: [
//           "#FF6384", "#36A2EB", "#FFCE56", "#4BC0C0", "#9966FF",
//           "#FF9F40", "#C9CBCF", "#A3CB38", "#FDA7DC", "#C4E538"
//         ],
//         borderColor: "#fff",
//         borderWidth: 1,
//       },
//     ],
//   };

//   return (
//     <div style={{ maxWidth: "600px", marginTop: 20 }}>
//       <h4>🎯 {title} ➤ Top 10 High Impact (Pie)</h4>
//       <Pie data={data} />
//     </div>
//   );
// };

// // 🍩 Top 10 Low Impact Chart (Doughnut)
// const LowImpactDoughnutChart = ({ rules, title }) => {
//   if (!rules || rules.length === 0) return null;

//   const labels = rules.map((r) => r.name || r.id || `Rule ${r.rule_id}`);
//   const dataValues = rules.map((r) => r.impact);

//   const data = {
//     labels,
//     datasets: [
//       {
//         label: "Low Impact Score",
//         data: dataValues,
//         backgroundColor: [
//           "#FF6384", "#36A2EB", "#FFCE56", "#4BC0C0", "#9966FF",
//           "#FF9F40", "#C9CBCF", "#A3CB38", "#FDA7DC", "#C4E538"
//         ],
//         borderColor: "#fff",
//         borderWidth: 1,
//       },
//     ],
//   };

//   return (
//     <div style={{ maxWidth: "600px", marginTop: 20 }}>
//       <h4>🍩 {title} ➤ Top 10 Low Impact (Doughnut)</h4>
//       <Doughnut data={data} />
//     </div>
//   );
// };

// // 🔁 Top 10 Duplicates Chart (Pie)
// const DuplicatePieChart = ({ duplicates }) => {
//   if (!duplicates || duplicates.length === 0) return null;

//   const labels = duplicates.map((d) => d.name);
//   const counts = duplicates.map((d) => d.count);

//   const data = {
//     labels,
//     datasets: [
//       {
//         label: "Duplicate Count",
//         data: counts,
//         backgroundColor: [
//           "#FF6384", "#36A2EB", "#FFCE56", "#4BC0C0", "#9966FF",
//           "#FF9F40", "#C9CBCF", "#A3CB38", "#FDA7DC", "#C4E538"
//         ],
//         borderColor: "#fff",
//         borderWidth: 1,
//       },
//     ],
//   };

//   return (
//     <div style={{ maxWidth: "600px", marginTop: 20 }}>
//       <h4>📊 Create ➤ Top 10 Duplicate Rule Names</h4>
//       <Pie data={data} />
//     </div>
//   );
// };

// const Workflow_dashboard = ({ client }) => {
//   const [timerSeconds, setTimerSeconds] = useState(null);
//   const [processingDone, setProcessingDone] = useState(false);
//   const [storedvalue1, setStoredvalue1] = useState(null);
//   const intervalRef = useRef(null);
//   const newRulePloadDB6 = useRef(null);
//   const [impactStats, setImpactStats] = useState({});

//   const ticketCreate = 1;
//   const ticketUpdate = 4;
//   const hourlyTriggers = 3;

//   const parseImpact = (impactString) => {
//     let totalCommaChar_ = (impactString.match(/,/g) || []).length;
//     if (totalCommaChar_ > 35) {
//       let d = new Date();
//       d.setMonth(d.getMonth() - 1);
//       let lastDate = d.toLocaleDateString();
//       impactString = impactString.split(`${lastDate}`);
//       impactString = impactString[1] || impactString[0];
//     }
//     const arrStr = impactString.split(/[:,]/).filter((el, i) => i % 2);
//     const total = arrStr.reduce((sum, val) => sum + (parseInt(val) || 0), 0);
//     return total;
//   };

//   const analyzeRules = (records, typeLabel) => {
//     const activeRules = records.filter((r) => r.active === "true");

//     const rulesWithImpact = activeRules.map((r) => {
//       const impact = parseImpact(r.impactDiffWithDate || "0:0");
//       return { ...r, impact };
//     });

//     // Duplicate counting
//     const nameCountMap = {};
//     for (const rule of rulesWithImpact) {
//       const name = rule.name || rule.rule_id || "Unnamed";
//       nameCountMap[name] = (nameCountMap[name] || 0) + 1;
//     }

//     const duplicateArray = Object.entries(nameCountMap)
//       .filter(([_, count]) => count > 1)
//       .sort((a, b) => b[1] - a[1])
//       .slice(0, 10)
//       .map(([name, count]) => ({ name, count }));

//     const noImpactRules = rulesWithImpact.filter((r) => r.impact === 0);
//     const sortedByImpact = [...rulesWithImpact].sort((a, b) => b.impact - a.impact);
//     const top10High = sortedByImpact.slice(0, 10);
//     const top10Low = sortedByImpact.filter((r) => r.impact > 0).slice(-10);


//     console.log(`🔹 ${typeLabel} ➤ Top 10 Highest Impact Rules (${top10High.length}):`);
// console.log(top10High.map(r => `${r.name} (${r.impact})`));

// console.log(`🔹 ${typeLabel} ➤ Top 10 Lowest Impact Rules (${top10Low.length}):`);
// console.log(top10Low.map(r => `${r.name} (${r.impact})`));

// console.log(`🔹 ${typeLabel} ➤ No Impact Rules (${noImpactRules.length})`);
// console.log(noImpactRules);

//     return {
//       noImpactCount: noImpactRules.length,
//       topHigh: top10High,
//       topLow: top10Low,
//       topDuplicates: duplicateArray,
//     };
//   };

//   const Filterrecords = async (automationTypeId, dbInstance, typeLabel) => {
//     let allRecords = [];
//     let nextMarker = null;

//     try {
//       do {
//         const queryObj = { query: { automation_type_id: automationTypeId } };
//         if (nextMarker) queryObj.next = { marker: nextMarker };
//         const response = await dbInstance.getAll(queryObj);
//         if (!response.records || !Array.isArray(response.records)) break;

//         const filtered = response.records.map((record) => ({
//           ...record.data,
//           display_id: record.display_id,
//           rule_id: record.data.rule_id,
//           automation_type_id: record.data.automation_type_id,
//           id: record.data.rule_id || record.data.id,
//         }));

//         allRecords = allRecords.concat(filtered);
//         nextMarker = response.links?.next?.marker || null;
//       } while (nextMarker);

//       allRecords.sort((a, b) => {
//         const posA = typeof a.position === "number" ? a.position : Number.MAX_SAFE_INTEGER;
//         const posB = typeof b.position === "number" ? b.position : Number.MAX_SAFE_INTEGER;
//         return posA - posB;
//       });

//       return analyzeRules(allRecords, typeLabel);
//     } catch (error) {
//       console.error("❌ Error fetching filtered records:", error);
//       return { noImpactCount: 0, topHigh: [], topLow: [], topDuplicates: [] };
//     }
//   };

//   const handleFilterRecords = async () => {
//     const dbInstance = newRulePloadDB6.current;
//     if (!dbInstance) return;

//     const creationStats = await Filterrecords(ticketCreate, dbInstance, "Create");
//     const updateStats = await Filterrecords(ticketUpdate, dbInstance, "Update");
//     const hourlyStats = await Filterrecords(hourlyTriggers, dbInstance, "Hourly");

//     setImpactStats({ create: creationStats, update: updateStats, hourly: hourlyStats });
//   };

//   useEffect(() => {
//     const initDB = async () => {
//       try {
//         const entity = await client.db.entity({ version: "v1" });
//         newRulePloadDB6.current = entity.get("newRulePloadDB6");
//       } catch (error) {
//         console.error("❌ Failed to init DB:", error);
//       }
//     };
//     initDB();
//   }, [client]);

//   useEffect(() => {
//     const fetchStored = async () => {
//       try {
//         const val = await client.db.get("RulesDB");
//         setStoredvalue1(val);
//       } catch (err) {
//         console.error("❌ Error fetching RulesDB:", err);
//         setStoredvalue1(null);
//       }
//     };
//     fetchStored();
//     const interval = setInterval(fetchStored, 60000);
//     return () => clearInterval(interval);
//   }, [client]);

//   useEffect(() => {
//     if (!storedvalue1) return;
//     const itemsPerPage = 100;
//     const secondsPerPage = 60;
//     const fixedOverhead = 60;

//     const getTime = (count) =>
//       count > 0 ? Math.ceil(count / itemsPerPage) * secondsPerPage + fixedOverhead : 0;

//     const creationTime = getTime(storedvalue1.creationTotal || 0);
//     const hourlyTime = getTime(storedvalue1.hourlyTotal || 0);
//     const updateTime = getTime(storedvalue1.updateTotal || 0);
//     const totalTime = creationTime + hourlyTime + updateTime;

//     if (totalTime <= 0) {
//       setTimerSeconds(null);
//       setProcessingDone(true);
//       return;
//     }

//     setTimerSeconds(totalTime);
//     setProcessingDone(false);
//     let remaining = totalTime;

//     if (intervalRef.current) clearInterval(intervalRef.current);

//     intervalRef.current = setInterval(() => {
//       remaining -= 1;
//       setTimerSeconds(remaining);
//       if (remaining <= 0) {
//         clearInterval(intervalRef.current);
//         intervalRef.current = null;
//         setTimerSeconds(0);
//         setProcessingDone(true);
//       }
//     }, 1000);

//     return () => clearInterval(intervalRef.current);
//   }, [storedvalue1]);

//   useEffect(() => {
//     if (processingDone && newRulePloadDB6.current) {
//       handleFilterRecords();
//     }
//   }, [processingDone, newRulePloadDB6.current]);

//   return (
//     <div>
//       {!processingDone ? (
//         <div
//           style={{
//             backgroundColor: "#f0f0f0",
//             height: "100vh",
//             display: "flex",
//             alignItems: "center",
//             justifyContent: "center",
//           }}
//         >
//           <div
//             style={{
//               display: "flex",
//               alignItems: "center",
//               backgroundColor: "white",
//               padding: "20px 30px",
//               borderRadius: 8,
//               fontSize: 18,
//               userSelect: "none",
//             }}
//           >
//             <FwSpinner size="small" color="green" style={{ marginRight: 8 }} />
//             <div>
//               Processing data. Please revisit in (<strong>{timerSeconds}</strong>) seconds.
//             </div>
//           </div>
//         </div>
//       ) : (
//         <div style={{ padding: 20, backgroundColor: "#fff", minHeight: "100vh" }}>
//           <h1>🎉 Dashboard Ready</h1>

//           {["create", "update", "hourly"].map((key) => (
//             <div key={key}>
//               <h2>🧠 {key.toUpperCase()} Rules</h2>
//               <ImpactPieChart rules={impactStats[key]?.topHigh} title={key} />
//               <LowImpactDoughnutChart rules={impactStats[key]?.topLow} title={key} />
//               {key === "create" && (
//                 <DuplicatePieChart duplicates={impactStats[key]?.topDuplicates} />
//               )}
//             </div>
//           ))}
//         </div>
//       )}
//     </div>
//   );
// };

// export default Workflow_dashboard;


import React, { useEffect, useState, useRef } from "react";
import { FwSpinner } from "@freshworks/crayons/react";
import { Pie, Doughnut } from "react-chartjs-2";
import { Chart as ChartJS, ArcElement, Tooltip, Legend } from "chart.js";

ChartJS.register(ArcElement, Tooltip, Legend);

// Pie Chart for High Impact
const ImpactPieChart = ({ rules }) => {
  if (!rules || rules.length === 0) return null;

  const labels = rules.map((r) => r.name || r.id || `Rule ${r.rule_id}`);
  const dataValues = rules.map((r) => r.impact);

  const data = {
    labels,
    datasets: [
      {
        label: "Impact Score",
        data: dataValues,
        backgroundColor: [
          "#FF6384", "#36A2EB", "#FFCE56", "#4BC0C0", "#9966FF",
          "#FF9F40", "#C9CBCF", "#A3CB38", "#FDA7DC", "#C4E538"
        ],
        borderColor: "#fff",
        borderWidth: 1,
      },
    ],
  };

  return (
    <div style={{ maxWidth: "300px" }}>
      <Pie data={data} />
    </div>
  );
};

// Doughnut Chart for Low Impact
const LowImpactDoughnutChart = ({ rules }) => {
  if (!rules || rules.length === 0) return null;

  const labels = rules.map((r) => r.name || r.id || `Rule ${r.rule_id}`);
  const dataValues = rules.map((r) => r.impact);

  const data = {
    labels,
    datasets: [
      {
        label: "Low Impact Score",
        data: dataValues,
        backgroundColor: [
          "#FF6384", "#36A2EB", "#FFCE56", "#4BC0C0", "#9966FF",
          "#FF9F40", "#C9CBCF", "#A3CB38", "#FDA7DC", "#C4E538"
        ],
        borderColor: "#fff",
        borderWidth: 1,
      },
    ],
  };

  return (
    <div style={{ maxWidth: "300px" }}>
      <Doughnut data={data} />
    </div>
  );
};

const Workflow_dashboard = ({ client }) => {
  const [timerSeconds, setTimerSeconds] = useState(null);
  const [processingDone, setProcessingDone] = useState(false);
  const [storedvalue1, setStoredvalue1] = useState(null);
  const intervalRef = useRef(null);
  const newRulePloadDB6 = useRef(null);
  const [impactStats, setImpactStats] = useState({});

  const ticketCreate = 1;
  const ticketUpdate = 4;
  const hourlyTriggers = 3;

  const parseImpact = (impactString) => {
    let totalCommaChar_ = (impactString.match(/,/g) || []).length;
    if (totalCommaChar_ > 35) {
      let d = new Date();
      d.setMonth(d.getMonth() - 1);
      let lastDate = d.toLocaleDateString();
      impactString = impactString.split(`${lastDate}`);
      impactString = impactString[1] || impactString[0];
    }
    const arrStr = impactString.split(/[:,]/).filter((el, i) => i % 2);
    const total = arrStr.reduce((sum, val) => sum + (parseInt(val) || 0), 0);
    return total;
  };

  const analyzeRules = (records, typeLabel) => {
    const activeRules = records.filter((r) => r.active === "true");

    const rulesWithImpact = activeRules.map((r) => {
      const impact = parseImpact(r.impactDiffWithDate || "0:0");
      return { ...r, impact };
    });

    const noImpactRules = rulesWithImpact.filter((r) => r.impact === 0);
    const sortedByImpact = [...rulesWithImpact].sort((a, b) => b.impact - a.impact);
    const top10High = sortedByImpact.slice(0, 10);
    const top10Low = sortedByImpact.filter((r) => r.impact > 0).slice(-10);

    return {
      noImpactCount: noImpactRules.length,
      topHigh: top10High,
      topLow: top10Low,
    };
  };

  const Filterrecords = async (automationTypeId, dbInstance, typeLabel) => {
    let allRecords = [];
    let nextMarker = null;

    try {
      do {
        const queryObj = { query: { automation_type_id: automationTypeId } };
        if (nextMarker) queryObj.next = { marker: nextMarker };
        const response = await dbInstance.getAll(queryObj);
        if (!response.records || !Array.isArray(response.records)) break;

        const filtered = response.records.map((record) => ({
          ...record.data,
          display_id: record.display_id,
          rule_id: record.data.rule_id,
          automation_type_id: record.data.automation_type_id,
          id: record.data.rule_id || record.data.id,
        }));

        allRecords = allRecords.concat(filtered);
        nextMarker = response.links?.next?.marker || null;
      } while (nextMarker);

      allRecords.sort((a, b) => {
        const posA = typeof a.position === "number" ? a.position : Number.MAX_SAFE_INTEGER;
        const posB = typeof b.position === "number" ? b.position : Number.MAX_SAFE_INTEGER;
        return posA - posB;
      });

      return analyzeRules(allRecords, typeLabel);
    } catch (error) {
      console.error("Error fetching filtered records:", error);
      return { noImpactCount: 0, topHigh: [], topLow: [] };
    }
  };

  const handleFilterRecords = async () => {
    const dbInstance = newRulePloadDB6.current;
    if (!dbInstance) return;

    const creationStats = await Filterrecords(ticketCreate, dbInstance, "Create");
    const updateStats = await Filterrecords(ticketUpdate, dbInstance, "Update");
    const hourlyStats = await Filterrecords(hourlyTriggers, dbInstance, "Hourly");

    setImpactStats({ create: creationStats, update: updateStats, hourly: hourlyStats });
  };

  useEffect(() => {
    const initDB = async () => {
      try {
        const entity = await client.db.entity({ version: "v1" });
        newRulePloadDB6.current = entity.get("newRulePloadDB6");
      } catch (error) {
        console.error("Failed to init DB:", error);
      }
    };
    initDB();
  }, [client]);

  useEffect(() => {
    const fetchStored = async () => {
      try {
        const val = await client.db.get("RulesDB");
        setStoredvalue1(val);
      } catch (err) {
        console.error("Error fetching RulesDB:", err);
        setStoredvalue1(null);
      }
    };
    fetchStored();
    const interval = setInterval(fetchStored, 60000);
    return () => clearInterval(interval);
  }, [client]);

  useEffect(() => {
    if (!storedvalue1) return;
    const itemsPerPage = 100;
    const secondsPerPage = 60;
    const fixedOverhead = 60;

    const getTime = (count) =>
      count > 0 ? Math.ceil(count / itemsPerPage) * secondsPerPage + fixedOverhead : 0;

    const creationTime = getTime(storedvalue1.creationTotal || 0);
    const hourlyTime = getTime(storedvalue1.hourlyTotal || 0);
    const updateTime = getTime(storedvalue1.updateTotal || 0);
    const totalTime = creationTime + hourlyTime + updateTime;

    if (totalTime <= 0) {
      setTimerSeconds(null);
      setProcessingDone(true);
      return;
    }

    setTimerSeconds(totalTime);
    setProcessingDone(false);
    let remaining = totalTime;

    if (intervalRef.current) clearInterval(intervalRef.current);

    intervalRef.current = setInterval(() => {
      remaining -= 1;
      setTimerSeconds(remaining);
      if (remaining <= 0) {
        clearInterval(intervalRef.current);
        intervalRef.current = null;
        setTimerSeconds(0);
        setProcessingDone(true);
      }
    }, 1000);

    return () => clearInterval(intervalRef.current);
  }, [storedvalue1]);

  useEffect(() => {
    if (processingDone && newRulePloadDB6.current) {
      handleFilterRecords();
    }
  }, [processingDone, newRulePloadDB6.current]);

  return (
    <div>
      {!processingDone ? (
        <div
          style={{
            backgroundColor: "#f0f0f0",
            height: "100vh",
            display: "flex",
            alignItems: "center",
            justifyContent: "center",
          }}
        >
          <div
            style={{
              display: "flex",
              alignItems: "center",
              backgroundColor: "white",
              padding: "20px 30px",
              borderRadius: 8,
              fontSize: 18,
              userSelect: "none",
            }}
          >
            <FwSpinner size="small" color="green" style={{ marginRight: 8 }} />
            <div>
              Processing data. Please revisit in (<strong>{timerSeconds}</strong>) seconds.
            </div>
          </div>
        </div>
      ) : (
        <div style={{ padding: 20, backgroundColor: "#fff", minHeight: "100vh" }}>
          <h1>🎉 Dashboard Ready</h1>

          {["create", "update", "hourly"].map((key) => (
            <div key={key} style={{ marginBottom: "40px" }}>
              <h2>🧠 {key.toUpperCase()} Rules</h2>
              <div style={{ display: "flex", justifyContent: "space-between", gap: 20, flexWrap: "wrap" }}>
                <div style={{ flex: "1", maxWidth: 300 }}>
                  <h4>🎯 Top 10 High Impact</h4>
                  <ImpactPieChart rules={impactStats[key]?.topHigh} />
                </div>
                <div style={{ flex: "1", maxWidth: 300 }}>
                  <h4>🍩 Top 10 Low Impact</h4>
                  <LowImpactDoughnutChart rules={impactStats[key]?.topLow} />
                </div>
                <div style={{ flex: "1", maxWidth: 300 }}>
                  <h4>🚫 No Impact</h4>
                  <div
                    style={{
                      height: 220,
                      display: "flex",
                      alignItems: "center",
                      justifyContent: "center",
                      border: "1px solid #ccc",
                      borderRadius: 8,
                      backgroundColor: "#f9f9f9",
                      fontWeight: "bold",
                      fontSize: 20,
                    }}
                  >
                    {impactStats[key]?.noImpactCount ?? 0}
                  </div>
                </div>
              </div>
            </div>
          ))}
        </div>
      )}
    </div>
  );
};

export default Workflow_dashboard;


Explain this code