<script lang="ts">
  import notifySound from "$lib/audio/options-flow-reader.mp3";
  import {
    numberOfUnreadNotification,
    getCache,
    setCache,
    isOpen,
  } from "$lib/store";

  import { cn } from "$lib/utils";
  import { onMount, onDestroy } from "svelte";
  import toast from "svelte-french-toast";
  import { DateFormatter, type DateValue } from "@internationalized/date";
  import * as DropdownMenu from "$lib/components/shadcn/dropdown-menu/index.js";
  import * as Popover from "$lib/components/shadcn/popover/index.js";
  import { Button } from "$lib/components/shadcn/button/index.js";
  import { Calendar } from "$lib/components/shadcn/calendar/index.js";
  import CalendarIcon from "lucide-svelte/icons/calendar";

  import { page } from "$app/stores";

  import OptionsFlowTable from "$lib/components/Table/OptionsFlowTable.svelte";
  import { writable } from "svelte/store";

  export let data;
  let shouldLoadWorker = writable(false);

  let optionsWatchlist = data?.getOptionsWatchlist;

  let ruleOfList = data?.getPredefinedCookieRuleOfList || [];

  let displayRules = [];
  let filteredData = [];
  let filterQuery = $page.url.searchParams.get("query") || "";

  let socket: WebSocket | null = null; // Initialize socket as null

  let syncWorker: Worker | undefined;
  let ruleName = "";
  let searchTerm = "";
  let showFilters = true;
  let filteredRows = [];
  const df = new DateFormatter("en-US", {
    day: "2-digit",
    month: "short",
    year: "numeric",
  });
  let selectedDate: DateValue | undefined = undefined;
  let infoText = {};
  let tooltipTitle;

  const allRules = {
    size: {
      label: "Size",
      step: ["50K", "20K", "10K", "5K", "2K", "1K", "100", "0"],
      defaultCondition: "over",
      defaultValue: "any",
    },
    volume: {
      label: "Volume",
      step: ["100K", "50K", "20K", "10K", "5K", "2K", "1K", "100", "0"],
      defaultCondition: "over",
      defaultValue: "any",
    },
    open_interest: {
      label: "Open Interest",
      step: ["100K", "10K", "1K"],
      defaultCondition: "over",
      defaultValue: "any",
    },
    volumeOIRatio: {
      label: "Volume / Open Interest",
      step: ["100%", "80%", "60%", "50%", "30%", "15%", "10%", "5%"],
      defaultCondition: "over",
      defaultValue: "any",
    },
    sizeOIRatio: {
      label: "Size / Open Interest",
      step: ["100%", "80%", "60%", "50%", "30%", "15%", "10%", "5%"],
      defaultCondition: "over",
      defaultValue: "any",
    },
    cost_basis: {
      label: "Premium",
      step: [
        "10M",
        "5M",
        "1M",
        "500K",
        "400K",
        "300K",
        "200K",
        "100K",
        "50K",
        "10K",
        "5K",
      ],
      defaultCondition: "over",
      defaultValue: "any",
    },
    moneyness: {
      label: "Moneyness",
      step: ["ITM", "OTM"],
      defaultValue: "any",
    },
    flowType: {
      label: "Flow Type",
      step: ["Repeated Flow"],
      defaultValue: "any",
    },
    put_call: {
      label: "Contract Type",
      step: ["Calls", "Puts"],
      defaultValue: "any",
    },
    sentiment: {
      label: "Sentiment",
      step: ["Bullish", "Neutral", "Bearish"],
      defaultValue: "any",
    },
    execution_estimate: {
      label: "Execution",
      step: ["Above Ask", "Below Bid", "At Ask", "At Bid", "At Midpoint"],
      defaultValue: "any",
    },
    option_activity_type: {
      label: "Option Type",
      step: ["Sweep", "Trade"],
      defaultValue: "any",
    },
    date_expiration: {
      label: "Date Expiration",
      step: ["250", "180", "100", "80", "60", "50", "30", "20", "10", "5", "0"],
      defaultCondition: "over",
      defaultValue: "any",
    },
    underlying_type: {
      label: "Asset Type",
      step: ["Stock", "ETF"],
      defaultValue: "any",
    },
  };

  const categoricalRules = [
    "moneyness",
    "flowType",
    "put_call",
    "sentiment",
    "execution_estimate",
    "option_activity_type",
    "underlying_type",
  ];

  // Generate allRows from allRules
  $: allRows = Object?.entries(allRules)
    ?.sort(([, a], [, b]) => a.label.localeCompare(b.label)) // Sort by label
    ?.map(([ruleName, ruleProps]) => ({
      rule: ruleName,
      ...ruleProps,
    }));

  let ruleCondition = {};
  let valueMappings = {};

  Object.keys(allRules).forEach((ruleName) => {
    ruleCondition[ruleName] = allRules[ruleName].defaultCondition;

    // Check if the default condition is "between"
    if (allRules[ruleName].defaultCondition === "between") {
      valueMappings[ruleName] = allRules[ruleName].defaultValue || [null, null];
    } else {
      valueMappings[ruleName] = allRules[ruleName].defaultValue;
    }
  });

  // Update ruleCondition and valueMappings based on existing rules
  ruleOfList.forEach((rule) => {
    ruleCondition[rule.name] =
      rule.condition || allRules[rule.name].defaultCondition;
    valueMappings[rule.name] = rule.value || allRules[rule.name].defaultValue;
  });

  async function handleDeleteRule(state) {
    for (let i = 0; i < ruleOfList.length; i++) {
      if (ruleOfList[i].name === state) {
        ruleOfList.splice(i, 1); // Remove the element at index i from the ruleOfList
        ruleOfList = [...ruleOfList];
        break; // Exit the loop after deleting the element
      }
    }

    if (ruleOfList?.length === 0) {
      ruleName = "";
    } else if (state === ruleName) {
      ruleName = "";
    }

    displayRules = allRows?.filter((row) =>
      ruleOfList.some((rule) => rule.name === row.rule),
    );
    shouldLoadWorker.set(true);
    await saveCookieRuleOfList();
  }

  async function handleResetAll() {
    ruleOfList = [];
    filteredData = [];
    ruleOfList = [...ruleOfList];
    ruleName = "";
    filterQuery = "";
    checkedItems = new Set();
    Object.keys(allRules).forEach((ruleName) => {
      ruleCondition[ruleName] = allRules[ruleName].defaultCondition;
      valueMappings[ruleName] = allRules[ruleName].defaultValue;
    });
    displayRules = allRows?.filter((row) =>
      ruleOfList.some((rule) => rule.name === row.rule),
    );
    displayedData = rawData;
    await saveCookieRuleOfList();
  }

  function changeRule(state: string) {
    searchTerm = "";
    ruleName = state;
    handleAddRule();

    //const closePopup = document.getElementById("ruleModal");
    //closePopup?.dispatchEvent(new MouseEvent('click'))
  }

  function handleAddRule() {
    if (ruleName === "") {
      toast.error("Please select a rule", {
        style: "border-radius: 200px; background: #333; color: #fff;",
      });
      return;
    }

    let newRule;

    switch (ruleName) {
      case "moneyness":
      case "flowType":
      case "put_call":
      case "sentiment":
      case "execution_estimate":
      case "option_activity_type":
      case "underlying_type":
        newRule = {
          name: ruleName,
          value: Array.isArray(valueMappings[ruleName])
            ? valueMappings[ruleName]
            : [valueMappings[ruleName]],
        }; // Ensure value is an array
        break;
      default:
        newRule = {
          name: ruleName,
          condition: ruleCondition[ruleName],
          value: valueMappings[ruleName],
        };
        break;
    }
    handleRule(newRule);
  }

  async function handleRule(newRule) {
    const existingRuleIndex = ruleOfList.findIndex(
      (rule) => rule.name === newRule.name,
    );

    if (existingRuleIndex !== -1) {
      const existingRule = ruleOfList[existingRuleIndex];
      if (existingRule.name === newRule.name) {
        // Remove the rule instead of showing an error
        ruleOfList.splice(existingRuleIndex, 1);
        ruleOfList = [...ruleOfList]; // Trigger reactivity
        Object.keys(allRules).forEach((ruleName) => {
          ruleCondition[ruleName] = allRules[ruleName].defaultCondition;
          valueMappings[ruleName] = allRules[ruleName].defaultValue;
        });
        displayRules = allRows?.filter((row) =>
          ruleOfList.some((rule) => rule.name === row.rule),
        );
      } else {
        ruleOfList[existingRuleIndex] = newRule;
        ruleOfList = [...ruleOfList]; // Trigger reactivity
      }
    } else {
      ruleOfList = [...ruleOfList, newRule];
      /*
    toast.success('Rule added', {
      style: 'border-radius: 200px; background: #333; color: #fff;'
    });
    */

      shouldLoadWorker.set(true);
    }
  }

  const loadWorker = async () => {
    syncWorker.postMessage({ rawData, ruleOfList, filterQuery });
  };

  const handleMessage = (event) => {
    displayRules = allRows?.filter((row) =>
      ruleOfList.some((rule) => rule.name === row.rule),
    );
    filteredData = event.data?.filteredData ?? [];
    displayedData = filteredData;
    console.log("handle Message");
    calculateStats(displayedData);

    //console.log(displayedData)
  };

  async function changeRuleCondition(name: string, state: string) {
    ruleName = name;
    if (
      ruleCondition[ruleName] === "between" &&
      ["over", "under"]?.includes(state?.toLowerCase())
    ) {
      valueMappings[ruleName] = "";
    }
    ruleCondition[ruleName] = state?.toLowerCase();

    await handleChangeValue(valueMappings[ruleName]);
  }

  let checkedItems = new Set(ruleOfList.flatMap((rule) => rule.value));

  function isChecked(item) {
    return checkedItems.has(item);
  }

  async function getInfoText(parameter, title) {
    tooltipTitle = title;
    const cachedData = getCache(parameter, "getInfoText");
    if (cachedData) {
      infoText = cachedData;
    } else {
      const postData = { parameter };
      const response = await fetch("/api/info-text", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify(postData),
      });

      infoText = await response.json();
      setCache(parameter, infoText, "getInfoText");
    }
  }

  function parseValue(val) {
    if (typeof val === "string") {
      // Handle percentage values
      if (val.endsWith("%")) {
        return parseFloat(val);
      }
      // Handle values with suffixes like K (thousand), M (million), B (billion)
      const suffixMap = {
        K: 1e3,
        M: 1e6,
        B: 1e9,
      };
      const suffix = val.slice(-1).toUpperCase();
      const numberPart = parseFloat(val);
      if (suffix in suffixMap) {
        return numberPart * suffixMap[suffix];
      }
    }
    return parseFloat(val);
  }

  // Custom sorting function
  function customSort(a, b) {
    return parseValue(a) - parseValue(b);
  }

  async function handleChangeValue(value, { shouldSort = true } = {}) {
    // Toggle checkedItems logic
    if (checkedItems.has(value)) {
      checkedItems.delete(value);
    } else {
      checkedItems.add(value);
    }

    // Specific rule handling for options-related rules
    if (categoricalRules?.includes(ruleName)) {
      // Ensure valueMappings[ruleName] is initialized as an array
      if (!Array.isArray(valueMappings[ruleName])) {
        valueMappings[ruleName] = [];
      }

      // Similar logic to the original function for adding/removing values
      const index = valueMappings[ruleName].indexOf(value);
      if (index === -1) {
        valueMappings[ruleName].push(value);

        // Sort the array when a new value is added, respecting shouldSort parameter
        if (shouldSort) {
          valueMappings[ruleName] = valueMappings[ruleName].sort(customSort);
        }
      } else {
        valueMappings[ruleName].splice(index, 1);
      }

      // Set to "any" if no values are selected
      if (valueMappings[ruleName].length === 0) {
        valueMappings[ruleName] = "any";
      }
    } else if (ruleName in valueMappings) {
      // For rules that require sorting (like range or numeric values)
      if (ruleCondition[ruleName] === "between" && Array.isArray(value)) {
        // Sort the array for between conditions, respecting shouldSort parameter
        valueMappings[ruleName] = shouldSort ? value.sort(customSort) : value;
      } else {
        // Handle non-specific rules as single values
        valueMappings[ruleName] = value;
      }
    } else {
      console.warn(`Unhandled rule: ${ruleName}`);
    }

    // Update ruleOfList (if applicable)
    const ruleToUpdate = ruleOfList?.find((rule) => rule.name === ruleName);
    if (ruleToUpdate) {
      ruleToUpdate.value = valueMappings[ruleToUpdate.name];
      ruleToUpdate.condition = ruleCondition[ruleToUpdate.name];
      ruleOfList = [...ruleOfList];
    }

    // Trigger worker load and save cookie
    shouldLoadWorker.set(true);
    await saveCookieRuleOfList();
  }

  async function stepSizeValue(value, condition) {
    const match = value.toString().match(/^(-?[\d.]+)([KMB%]?)$/);
    if (!match) return value;

    let [_, number, suffix] = match;
    number = parseFloat(number);

    let step = 1;

    number += condition === "add" ? step : -step;

    // Round to 2 decimal places for consistency
    number = parseFloat(number?.toFixed(2));
    const newValue = suffix ? `${number}${suffix}` : Math?.round(number);
    await handleChangeValue(newValue);
  }

  async function handleValueInput(event, ruleName, index = null) {
    const newValue = event.target.value;

    if (ruleCondition[ruleName] === "between") {
      const currentValues = [...(valueMappings[ruleName] || ["", ""])];
      currentValues[index] = newValue;
      await handleChangeValue(currentValues, { shouldSort: false });
    } else {
      await handleChangeValue(newValue);
    }
  }

  const nyseDate = new Date(
    data?.getOptionsFlowFeed?.at(0)?.date ?? null,
  )?.toLocaleString("en-US", {
    month: "short",
    day: "numeric",
    year: "numeric",
    timeZone: "Europe/Berlin",
  });

  let rawData = data?.getOptionsFlowFeed?.filter((item) =>
    Object?.values(item)?.every(
      (value) =>
        value !== null &&
        value !== undefined &&
        (typeof value !== "object" ||
          Object?.values(value)?.every(
            (subValue) => subValue !== null && subValue !== undefined,
          )),
    ),
  );
  rawData?.forEach((item) => {
    item.dte = daysLeft(item?.date_expiration);
  });

  let displayedData = [];

  let flowSentiment;
  let putCallRatio;
  let displayCallVolume;
  let displayPutVolume;
  let callPercentage;
  let putPercentage;

  let audio;
  let muted = false;
  let newData = [];
  let previousVolume = 0; //This is needed to play the sound only if it changes.
  let notFound = false;
  let isLoaded = false;
  $: mode = $isOpen === true ? true : false;

  function toggleMode() {
    if ($isOpen) {
      mode = !mode;
      if (mode === true && selectedDate !== undefined) {
        selectedDate = undefined;
        rawData = data?.getOptionsFlowFeed;
        displayedData = [...rawData];
        shouldLoadWorker.set(true);
      }
    } else {
      toast.error(`Market is closed`, {
        style: "border-radius: 200px; background: #333; color: #fff;",
      });
    }
  }

  async function websocketRealtimeData() {
    newData = [];
    try {
      socket = new WebSocket(data?.wsURL + "/options-flow-reader");
      /*
    socket.addEventListener("open", () => {
      const ids = rawData.map(item => item.id);
      sendMessage(JSON.stringify({ ids }));
    });
    */

      socket.addEventListener("message", (event) => {
        const totalVolume = displayCallVolume + displayPutVolume;
        if (mode === true) {
          try {
            newData = JSON?.parse(event.data) ?? [];
            console.log(newData?.length);
            if (newData?.length > 0) {
              newData?.forEach((item) => {
                item.dte = daysLeft(item?.date_expiration);
              });

              //calculateStats(newData);
              //console.log(previousVolume);
              if (
                newData?.length > rawData?.length &&
                previousVolume !== totalVolume
              ) {
                //console.log(previousVolume,totalVolume,);
                rawData = newData;
                displayedData = rawData;

                if (!muted) {
                  audio?.play();
                }
              }
            }

            /*
          if (previousCallVolume !== displayCallVolume && !muted && audio) {
            audio?.play();
          }
          */
          } catch (e) {
            console.error("Error processing WebSocket message:", e);
          }
          newData = [];
          previousVolume = totalVolume;
        }
      });

      socket.addEventListener("close", (event) => {
        console.log("WebSocket connection closed:", event.reason);

        // Explicitly nullify the socket and remove all event listeners
        if (socket) {
          socket.onmessage = null;
          socket.onopen = null;
          socket.onclose = null;
          socket.onerror = null;
          socket = null;
        }
      });

      socket.addEventListener("error", (error) => {
        console.error("WebSocket error:", error);
        // Handle WebSocket errors here
      });
    } catch (error) {
      console.error("WebSocket connection error:", error);
      // Handle connection errors here
      setTimeout(() => websocketRealtimeData(), 400);
    }
  }

  function daysLeft(targetDate) {
    const targetTime = new Date(targetDate).getTime();
    const currentTime = new Date().getTime();
    const difference = targetTime - currentTime;

    const millisecondsPerDay = 1000 * 60 * 60 * 24;
    const daysLeft = Math?.ceil(difference / millisecondsPerDay);

    return daysLeft;
  }

  async function saveCookieRuleOfList() {
    const postData = {
      ruleOfList: ruleOfList,
    };

    const response = await fetch("/api/options-flow-filter-cookie", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify(postData),
    }); // make a POST request to the server with the FormData object
  }

  $: if ($isOpen) {
    websocketRealtimeData();
  }

  onMount(async () => {
    if (filterQuery?.length > 0) {
      shouldLoadWorker.set(true);
    }
    if (ruleOfList?.length !== 0) {
      shouldLoadWorker.set(true);
      console.log("initial filter");
    }

    displayRules = allRows?.filter((row) =>
      ruleOfList?.some((rule) => rule?.name === row?.rule),
    );

    audio = new Audio(notifySound);
    displayedData = rawData;
    calculateStats(rawData);

    if (!syncWorker) {
      const SyncWorker = await import("./workers/filterWorker?worker");
      syncWorker = new SyncWorker.default();
      syncWorker.onmessage = handleMessage;
    }

    shouldLoadWorker.subscribe(async (value) => {
      if (value) {
        isLoaded = false;
        await loadWorker();
        shouldLoadWorker.set(false); // Reset after worker is loaded
        isLoaded = true;
      }
    });

    isLoaded = true;
  });

  onDestroy(async () => {
    if (socket && socket.readyState === WebSocket.OPEN) {
      socket.close();
      console.log("WebSocket connection closed safely.");
    }
    if (audio) {
      audio?.pause();
      audio = null;
    }
  });

  function calculateStats(data) {
    const {
      callVolumeSum,
      putVolumeSum,
      bullishCount,
      bearishCount,
      neutralCount,
    } = data?.reduce(
      (acc, item) => {
        const volume = parseInt(item?.volume);

        if (item?.put_call === "Calls") {
          acc.callVolumeSum += volume;
        } else if (item?.put_call === "Puts") {
          acc.putVolumeSum += volume;
        }

        if (item?.sentiment === "Bullish") {
          acc.bullishCount += 1;
        } else if (item?.sentiment === "Bearish") {
          acc.bearishCount += 1;
        } else if (item?.sentiment === "Neutral") {
          acc.neutralCount += 1;
        }

        return acc;
      },
      {
        callVolumeSum: 0,
        putVolumeSum: 0,
        bullishCount: 0,
        bearishCount: 0,
        neutralCount: 0,
      },
    );

    if (bullishCount > bearishCount) {
      flowSentiment = "Bullish";
    } else if (bullishCount < bearishCount) {
      flowSentiment = "Bearish";
    } else if (neutralCount > bearishCount && neutralCount > bullishCount) {
      flowSentiment = "Neutral";
    } else {
      flowSentiment = "-";
    }

    putCallRatio = callVolumeSum !== 0 ? putVolumeSum / callVolumeSum : 0;

    callPercentage =
      callVolumeSum + putVolumeSum !== 0
        ? Math.floor((callVolumeSum / (callVolumeSum + putVolumeSum)) * 100)
        : 0;
    putPercentage =
      callVolumeSum + putVolumeSum !== 0 ? 100 - callPercentage : 0;

    displayCallVolume = callVolumeSum;
    displayPutVolume = putVolumeSum;
  }

  const getHistoricalFlow = async () => {
    // Create a delay using setTimeout wrapped in a Promise
    if (data?.user?.tier === "Pro") {
      mode = false;
      isLoaded = false;

      displayRules = allRows?.filter((row) =>
        ruleOfList.some((rule) => rule.name === row.rule),
      );
      displayedData = [];
      calculateStats(displayedData);

      await new Promise((resolve) => setTimeout(resolve, 300));

      // Make the POST request after the delay
      const convertDate = new Date(df.format(selectedDate?.toDate()));
      const year = convertDate?.getFullYear();
      const month = String(convertDate?.getMonth() + 1).padStart(2, "0");
      const day = String(convertDate?.getDate()).padStart(2, "0");

      const postData = { selectedDate: `${year}-${month}-${day}` };

      try {
        const response = await fetch("/api/options-historical-flow", {
          method: "POST",
          headers: {
            "Content-Type": "application/json",
          },
          body: JSON.stringify(postData),
        });

        rawData = await response?.json();
        if (rawData?.length !== 0) {
          rawData?.forEach((item) => {
            item.dte = daysLeft(item?.date_expiration);
          });
          shouldLoadWorker.set(true);
        }
      } catch (error) {
        console.error("Error fetching historical flow:", error);
        rawData = [];
      } finally {
        isLoaded = true;
      }
    } else {
      toast.error("Only for Pro Members", {
        style: "border-radius: 200px; background: #333; color: #fff;",
      });
    }
  };

  function handleInput(event) {
    filterQuery = event.target.value;

    setTimeout(() => {
      shouldLoadWorker.set(true);
    }, 0);
  }

  function debounce(fn, delay) {
    let timeoutId;
    return function (...args) {
      clearTimeout(timeoutId);
      timeoutId = setTimeout(() => {
        fn.apply(this, args);
      }, delay);
    };
  }

  const debouncedHandleInput = debounce(handleInput, 300);

  $: {
    if (searchTerm) {
      filteredRows = allRows?.filter((row) =>
        row?.label?.toLowerCase()?.includes(searchTerm?.toLowerCase()),
      );
    }
  }

  $: {
    if (ruleOfList) {
      const ruleToUpdate = ruleOfList?.find((rule) => rule?.name === ruleName);
      if (ruleToUpdate) {
        ruleToUpdate.value = valueMappings[ruleToUpdate.name];
        ruleToUpdate.condition = ruleCondition[ruleToUpdate.name];
        ruleOfList = [...ruleOfList];
        //shouldLoadWorker.set(true);
      }
    }
  }
</script>

<svelte:head>
  <meta charset="utf-8" />
  <meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0" />

  <title>
    {$numberOfUnreadNotification > 0 ? `(${$numberOfUnreadNotification})` : ""} Options
    Flow Feed · Stocknear
  </title>
  <meta
    name="description"
    content={`Explore unusual options from big institutional traders and hedge funds.`}
  />

  <!-- Other meta tags -->
  <meta property="og:title" content={`Options Flow Feed · Stocknear`} />
  <meta
    property="og:description"
    content={`Explore unusual options from big institutional traders and hedge funds.`}
  />
  <meta property="og:type" content="website" />
  <!-- Add more Open Graph meta tags as needed -->

  <!-- Twitter specific meta tags -->
  <meta name="twitter:card" content="summary_large_image" />
  <meta name="twitter:title" content={`Options Flow Feed · Stocknear`} />
  <meta
    name="twitter:description"
    content={`Explore unusual options from big institutional traders and hedge funds.`}
  />
  <!-- Add more Twitter meta tags as needed -->
</svelte:head>

<body class="overflow-y-auto">
  <section
    class="w-full max-w-screen sm:max-w-7xl xl:max-w-7xl flex justify-center items-center bg-[#09090B] pb-20"
  >
    <div class="w-full m-auto px-3 min-h-screen">
      <!--
        <div class="text-sm sm:text-[1rem] breadcrumbs mb-5">
          <ul>
            <li><a href="/" class="text-gray-300">Home</a></li>
            <li class="text-gray-300">Options Flow</li>
          </ul>
        </div>
        -->

      {#if !$isOpen}
        <div
          class="text-white text-sm sm:text-[1rem] italic text-center sm:text-start w-full ml-2 mb-3"
        >
          Live flow of {data?.user?.tier === "Pro" && selectedDate
            ? df.format(selectedDate?.toDate())
            : nyseDate} (NYSE Time)
        </div>
      {/if}

      <div class="rounded-md border border-gray-700 bg-[#1E222D] p-2">
        <div
          class="flex flex-col sm:flex-row items-center pt-3 sm:pt-1 pb-3 sm:border-b sm:border-gray-600"
        >
          <div
            class="flex flex-row items-center justify-center sm:justify-start"
          >
            <label
              data-tip="Audio Preference"
              on:click={() => (muted = !muted)}
              class="xl:tooltip xl:tooltip-bottom flex flex-col items-center mr-3 cursor-pointer"
            >
              <div
                class="rounded-full w-10 h-10 relative bg-[#000] flex items-center justify-center"
              >
                {#if !muted}
                  <svg
                    class="w-4 h-4"
                    xmlns="http://www.w3.org/2000/svg"
                    viewBox="0 0 16 16"
                    ><path
                      fill="#fff"
                      d="M9 2.5a.5.5 0 0 0-.849-.358l-2.927 2.85H3.5a1.5 1.5 0 0 0-1.5 1.5v2.99a1.5 1.5 0 0 0 1.5 1.5h1.723l2.927 2.875A.5.5 0 0 0 9 13.5zm1.111 2.689a.5.5 0 0 1 .703-.08l.002.001l.002.002l.005.004l.015.013l.046.04c.036.034.085.08.142.142c.113.123.26.302.405.54c.291.48.573 1.193.573 2.148c0 .954-.282 1.668-.573 2.148a3.394 3.394 0 0 1-.405.541a2.495 2.495 0 0 1-.202.196l-.008.007h-.001s-.447.243-.703-.078a.5.5 0 0 1 .075-.7l.002-.002l-.001.001l.002-.001h-.001l.018-.016c.018-.017.048-.045.085-.085a2.4 2.4 0 0 0 .284-.382c.21-.345.428-.882.428-1.63c0-.747-.218-1.283-.428-1.627a2.382 2.382 0 0 0-.368-.465a.5.5 0 0 1-.096-.717m1.702-2.08a.5.5 0 1 0-.623.782l.011.01l.052.045c.047.042.116.107.201.195c.17.177.4.443.63.794c.46.701.92 1.733.92 3.069a5.522 5.522 0 0 1-.92 3.065c-.23.35-.46.614-.63.79a3.922 3.922 0 0 1-.252.24l-.011.01h-.001a.5.5 0 0 0 .623.782l.033-.027l.075-.065c.063-.057.15-.138.253-.245a6.44 6.44 0 0 0 .746-.936a6.522 6.522 0 0 0 1.083-3.614a6.542 6.542 0 0 0-1.083-3.618a6.517 6.517 0 0 0-.745-.938a4.935 4.935 0 0 0-.328-.311l-.023-.019l-.007-.006l-.002-.002zM10.19 5.89l-.002-.001Z"
                    /></svg
                  >
                {:else}
                  <svg
                    class="w-4 h-4"
                    xmlns="http://www.w3.org/2000/svg"
                    viewBox="0 0 24 24"
                    ><path
                      fill="#fff"
                      d="M3.28 2.22a.75.75 0 1 0-1.06 1.06L6.438 7.5H4.25A2.25 2.25 0 0 0 2 9.749v4.497a2.25 2.25 0 0 0 2.25 2.25h3.68a.75.75 0 0 1 .498.19l4.491 3.994c.806.716 2.081.144 2.081-.934V16.06l5.72 5.72a.75.75 0 0 0 1.06-1.061zm13.861 11.74l1.138 1.137A6.974 6.974 0 0 0 19 12a6.973 6.973 0 0 0-.84-3.328a.75.75 0 0 0-1.32.714c.42.777.66 1.666.66 2.614c0 .691-.127 1.351-.359 1.96m2.247 2.246l1.093 1.094A9.956 9.956 0 0 0 22 12a9.959 9.959 0 0 0-1.96-5.946a.75.75 0 0 0-1.205.892A8.459 8.459 0 0 1 20.5 12a8.458 8.458 0 0 1-1.112 4.206M9.52 6.338l5.48 5.48V4.25c0-1.079-1.274-1.65-2.08-.934z"
                    /></svg
                  >
                {/if}
              </div>
            </label>

            <span
              class="text-xs sm:text-sm sm:text-lg {!mode
                ? 'text-white'
                : 'text-gray-400'} mr-3"
            >
              {$isOpen ? "Paused" : "Market Closed"}
            </span>

            <label
              class="inline-flex items-center cursor-pointer focus-none focus:outline-none"
            >
              <input
                on:click={toggleMode}
                type="checkbox"
                checked={mode}
                value={mode}
                disabled={!$isOpen}
                class="sr-only peer"
              />

              <div
                class="relative w-11 h-6 bg-gray-600 focus:outline-none peer-focus:outline-none peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full rtl:peer-checked:after:-translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:start-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-[#00A96E]"
              ></div>
            </label>

            <div class="ml-3 flex flex-col items-start">
              <span
                class="text-xs sm:text-sm sm:text-lg {mode
                  ? 'text-white'
                  : 'text-gray-400'}"
              >
                Live Flow
              </span>
            </div>
          </div>

          <div class="sm:ml-auto w-full sm:w-fit pt-5">
            <div class="relative flex flex-col sm:flex-row items-center">
              <div
                class="relative w-full sm:w-fit pl-3 sm:mr-5 mb-4 sm:mb-0 flex-auto text-center bg-[#2A2E39] rounded-md border border-gray-600"
              >
                <label class="flex flex-row items-center">
                  <input
                    id="modal-search"
                    type="search"
                    class="text-white sm:ml-2 text-[1rem] placeholder-gray-300 border-transparent focus:border-transparent focus:ring-0 flex items-center justify-center w-full px-0 py-1.5 bg-inherit"
                    placeholder="Search AAPL, SPY,..."
                    bind:value={filterQuery}
                    on:input={debouncedHandleInput}
                    autocomplete="off"
                  />
                  <svg
                    class="ml-auto h-7 w-7 sm:h-8 sm:w-8 inline-block mr-5"
                    xmlns="http://www.w3.org/2000/svg"
                    viewBox="0 0 24 24"
                    ><path
                      fill="#fff"
                      d="m19.485 20.154l-6.262-6.262q-.75.639-1.725.989t-1.96.35q-2.402 0-4.066-1.663T3.808 9.503T5.47 5.436t4.064-1.667t4.068 1.664T15.268 9.5q0 1.042-.369 2.017t-.97 1.668l6.262 6.261zM9.539 14.23q1.99 0 3.36-1.37t1.37-3.361t-1.37-3.36t-3.36-1.37t-3.361 1.37t-1.37 3.36t1.37 3.36t3.36 1.37"
                    /></svg
                  >
                </label>
                {#if notFound === true}
                  <span
                    class="absolute left-1 -bottom-6 label-text text-error text-[0.65rem] mt-2"
                  >
                    No Results Found
                  </span>
                {/if}
              </div>

              <Popover.Root>
                <Popover.Trigger asChild let:builder>
                  <Button
                    class={cn(
                      "w-full sm:w-[160px] truncate sm:mr-3 py-3 bg-[#000] sm:hover:bg-[#000] sm:hover:text-white text-white justify-center sm:justify-start text-center sm:text-left font-normal border-none rounded-md",
                      !selectedDate && "text-gray-300",
                    )}
                    builders={[builder]}
                  >
                    <CalendarIcon class="mr-2 h-4 w-4" />
                    {selectedDate
                      ? df.format(selectedDate?.toDate())
                      : "Pick a date"}
                  </Button>
                </Popover.Trigger>
                <Popover.Content class="w-auto p-0 border-gray-500">
                  <Calendar
                    class="bg-[#09090B] text-white"
                    bind:value={selectedDate}
                    initialFocus
                    onValueChange={getHistoricalFlow}
                  />
                </Popover.Content>
              </Popover.Root>
            </div>
          </div>
        </div>

        <div
          class="mr-1 flex items-center justify-between lg:mr-2 pb-1.5 border-b border-gray-600 mt-1.5"
        >
          <button
            on:click={() => (showFilters = !showFilters)}
            class="flex cursor-pointer items-center text-lg sm:text-xl font-semibold text-white"
            title="Hide Filter Area"
          >
            <svg
              class="-mb-0.5 h-6 w-6 {showFilters ? '' : '-rotate-90'} "
              viewBox="0 0 20 20"
              fill="currentColor"
              style="max-width:40px"
            >
              <path
                fill-rule="evenodd"
                d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
                clip-rule="evenodd"
              ></path>
            </svg>
            {ruleOfList?.length} Filters
          </button>
        </div>

        {#if showFilters}
          <div
            class="sm:mt-3 flex flex-col gap-y-2.5 sm:flex-row lg:gap-y-2 pb-1"
          >
            <label
              for="ruleModal"
              class="inline-flex cursor-pointer items-center justify-center space-x-1 whitespace-nowrap rounded-md border border-transparent bg-blue-brand_light py-2 pl-3 pr-4 text-base font-semibold text-white shadow-sm bg-[#000] sm:hover:bg-[#09090B]/60 ease-out focus:outline-none focus:ring-2 focus:ring-blue-500 sm:text-smaller"
            >
              <svg
                class="h-5 w-5"
                viewBox="0 0 20 20"
                fill="currentColor"
                style="max-width:40px"
                aria-hidden="true"
              >
                <path
                  fill-rule="evenodd"
                  d="M10 3a1 1 0 011 1v5h5a1 1 0 110 2h-5v5a1 1 0 11-2 0v-5H4a1 1 0 110-2h5V4a1 1 0 011-1z"
                  clip-rule="evenodd"
                ></path>
              </svg>
              <div>Add Filters</div>
            </label>

            {#if ruleOfList?.length !== 0}
              <label
                on:click={handleResetAll}
                class="sm:ml-3 cursor-pointer inline-flex items-center justify-center space-x-1 whitespace-nowrap rounded-md border border-transparent bg-blue-brand_light py-2 pl-3 pr-4 text-base font-semibold text-white shadow-sm bg-[#000] sm:hover:text-red-500 ease-out focus:outline-none focus:ring-2 focus:ring-blue-500 sm:text-smaller"
              >
                <svg
                  class="h-4 w-4"
                  xmlns="http://www.w3.org/2000/svg"
                  viewBox="0 0 21 21"
                  ><g
                    fill="none"
                    fill-rule="evenodd"
                    stroke="currentColor"
                    stroke-linecap="round"
                    stroke-linejoin="round"
                    ><path d="M3.578 6.487A8 8 0 1 1 2.5 10.5" /><path
                      d="M7.5 6.5h-4v-4"
                    /></g
                  ></svg
                >
                <div>Reset All</div>
              </label>
            {/if}
          </div>

          <div
            class="sm:grid sm:gap-x-2.5 md:grid-cols-2 lg:grid-cols-3 w-full mt-3 border-t border-b border-gray-600"
          >
            {#each displayRules as row (row?.rule)}
              <!--Start Added Rules-->
              <div
                class="flex items-center justify-between space-x-2 px-1 py-1.5 text-smaller leading-tight text-default"
              >
                <div class="hide-scroll text-white">
                  {row?.label?.length > 20
                    ? row?.label?.slice(0, 20)?.replace("[%]", "") + "..."
                    : row?.label?.replace("[%]", "")}
                  <span class="relative" role="tooltip"
                    ><label
                      for="mobileTooltip"
                      on:click={() =>
                        getInfoText(row?.rule, row?.label?.replace("[%]", ""))}
                      class="relative"
                      role="tooltip"
                    >
                      <span
                        class="absolute -right-[15px] -top-[3px] cursor-pointer p-1 text-gray-300 sm:hover:text-white"
                      >
                        <svg
                          class="h-[10.5px] w-[10.5px]"
                          viewBox="0 0 4 16"
                          fill="currentColor"
                          style="max-width:20px"
                          ><path
                            d="M0 6h4v10h-4v-10zm2-6c1.1 0 2 .9 2 2s-.9 2-2 2-2-.9-2-2 .9-2 2-2z"
                          ></path></svg
                        >
                      </span>
                    </label></span
                  >
                </div>

                <div class="flex items-center">
                  <button
                    on:click={() => handleDeleteRule(row?.rule)}
                    class="mr-1.5 cursor-pointer text-gray-300 sm:hover:text-red-500 focus:outline-none"
                    title="Remove filter"
                  >
                    <svg
                      class="w-6 h-6"
                      fill="none"
                      viewBox="0 0 24 24"
                      stroke="CurrentColor"
                      style="max-width:40px"
                    >
                      <path
                        stroke-linecap="round"
                        stroke-linejoin="round"
                        stroke-width="2"
                        d="M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z"
                      ></path>
                    </svg>
                  </button>
                  <div class="relative inline-block text-left">
                    <div on:click={() => (ruleName = row?.rule)}>
                      <DropdownMenu.Root>
                        <DropdownMenu.Trigger asChild let:builder>
                          <Button
                            builders={[builder]}
                            class="bg-[#000] h-[40px] flex flex-row justify-between items-center w-[150px] xs:w-[140px] sm:w-[150px] px-3 text-white rounded-md truncate"
                          >
                            <span class="truncate ml-2 text-sm sm:text-[1rem]">
                              {#if valueMappings[row?.rule] === "any"}
                                Any
                              {:else if ruleCondition[row?.rule] === "between"}
                                {Array.isArray(valueMappings[row?.rule])
                                  ? `${valueMappings[row?.rule][0]}-${valueMappings[row?.rule][1] ?? "Any"}`
                                  : "Any"}
                              {:else}
                                {ruleCondition[row?.rule]
                                  ?.replace("under", "Under")
                                  ?.replace("over", "Over") ?? ""}
                                {valueMappings[row?.rule]}
                              {/if}
                            </span>
                            <svg
                              class=" ml-1 h-6 w-6 xs:ml-2 inline-block"
                              viewBox="0 0 20 20"
                              fill="currentColor"
                              style="max-width:40px"
                              aria-hidden="true"
                            >
                              <path
                                fill-rule="evenodd"
                                d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
                                clip-rule="evenodd"
                              ></path>
                            </svg>
                          </Button>
                        </DropdownMenu.Trigger>
                        <DropdownMenu.Content
                          class="w-64 min-h-auto max-h-72 overflow-y-auto scroller"
                        >
                          {#if !categoricalRules?.includes(row?.rule)}
                            <DropdownMenu.Label
                              class="absolute mt-2 h-11 border-gray-800 border-b -top-1 z-20 fixed sticky bg-[#09090B]"
                            >
                              <div
                                class="flex items-center justify-start gap-x-1"
                              >
                                <!--Start Dropdown for Condition-->
                                <div
                                  class="-ml-2 relative inline-block text-left"
                                >
                                  <DropdownMenu.Root>
                                    <DropdownMenu.Trigger asChild let:builder
                                      ><Button
                                        builders={[builder]}
                                        class="w-fit -mt-1 -ml-2 bg-[#09090B] flex flex-row justify-between items-center text-white"
                                      >
                                        <span
                                          class="truncate ml-2 text-sm sm:text-[1rem]"
                                        >
                                          {ruleCondition[ruleName]
                                            ?.replace("under", "Under")
                                            ?.replace("over", "Over")
                                            ?.replace("between", "Between")}
                                        </span>
                                        <svg
                                          class="mt-1 -mr-1 ml-1 h-5 w-5 xs:ml-2 !ml-0 sm:ml-0 inline-block"
                                          viewBox="0 0 20 20"
                                          fill="currentColor"
                                          style="max-width:40px"
                                          aria-hidden="true"
                                          ><path
                                            fill-rule="evenodd"
                                            d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
                                            clip-rule="evenodd"
                                          ></path></svg
                                        >
                                      </Button>
                                    </DropdownMenu.Trigger>
                                    <DropdownMenu.Content>
                                      <DropdownMenu.Group>
                                        {#each ["Over", "Under", "Between"] as item}
                                          <DropdownMenu.Item
                                            on:click={() =>
                                              changeRuleCondition(
                                                row?.rule,
                                                item,
                                              )}
                                            class="cursor-pointer text-[1rem] font-normal"
                                            >{item}</DropdownMenu.Item
                                          >
                                        {/each}
                                      </DropdownMenu.Group>
                                    </DropdownMenu.Content>
                                  </DropdownMenu.Root>
                                </div>

                                {#if ruleCondition[row?.rule] === "between"}
                                  <div class="flex gap-x-1 -ml-2 z-10 -mt-1">
                                    <input
                                      type="text"
                                      placeholder="Min"
                                      value={Array.isArray(
                                        valueMappings[row?.rule],
                                      )
                                        ? (valueMappings[row?.rule][0] ?? "")
                                        : ""}
                                      on:input={(e) =>
                                        handleValueInput(e, row?.rule, 0)}
                                      class="ios-zoom-fix block max-w-[3.5rem] rounded-sm placeholder:text-gray-200 font-normal p-1 text-sm shadow-sm focus:border-blue-500 focus:ring-blue-500 bg-secondary"
                                    />
                                    <span
                                      class="text-white text-[1rem] font-normal mt-1"
                                    >
                                      &
                                    </span>
                                    <input
                                      type="text"
                                      placeholder="Max"
                                      value={Array.isArray(
                                        valueMappings[row?.rule],
                                      )
                                        ? (valueMappings[row?.rule][1] ?? "")
                                        : ""}
                                      on:input={(e) =>
                                        handleValueInput(e, row?.rule, 1)}
                                      class="ios-zoom-fix block max-w-[3.5rem] rounded-sm placeholder:text-gray-200 font-normal p-1 text-sm shadow-sm focus:border-blue-500 focus:ring-blue-500 bg-secondary"
                                    />
                                  </div>
                                {:else}
                                  <input
                                    type="text"
                                    placeholder="Value"
                                    value={valueMappings[row?.rule] === "any"
                                      ? ""
                                      : valueMappings[row?.rule]}
                                    on:input={(e) =>
                                      handleValueInput(e, row?.rule)}
                                    class="ios-zoom-fix block max-w-[4.8rem] rounded-sm placeholder:text-gray-200 font-normal p-1 text-sm shadow-sm focus:border-blue-500 focus:ring-blue-500 bg-secondary"
                                  />
                                {/if}

                                {#if ["over", "under"]?.includes(ruleCondition[ruleName]?.toLowerCase())}
                                  <div
                                    class="ml-2 flex touch-manipulation flex-row items-center gap-x-1.5"
                                  >
                                    <button
                                      on:click={() =>
                                        stepSizeValue(
                                          valueMappings[row?.rule],
                                          "add",
                                        )}
                                      ><svg
                                        class="size-6 cursor-pointer text-white"
                                        fill="none"
                                        viewBox="0 0 24 24"
                                        stroke="currentColor"
                                        style="max-width:40px"
                                        ><path
                                          stroke-linecap="round"
                                          stroke-linejoin="round"
                                          stroke-width="2"
                                          d="M12 9v6m3-3H9m12 0a9 9 0 11-18 0 9 9 0 0118 0z"
                                        ></path></svg
                                      ></button
                                    >
                                    <button
                                      on:click={() =>
                                        stepSizeValue(
                                          valueMappings[row?.rule],
                                          "minus",
                                        )}
                                      ><svg
                                        class="size-6 cursor-pointer text-white"
                                        fill="none"
                                        viewBox="0 0 24 24"
                                        stroke="currentColor"
                                        style="max-width:40px"
                                        ><path
                                          stroke-linecap="round"
                                          stroke-linejoin="round"
                                          stroke-width="2"
                                          d="M15 12H9m12 0a9 9 0 11-18 0 9 9 0 0118 0z"
                                        ></path></svg
                                      ></button
                                    >
                                  </div>
                                {/if}
                                <!--End Dropdown for Condition-->
                              </div>
                            </DropdownMenu.Label>
                          {:else}
                            <div
                              class="relative sticky z-40 focus:outline-none -top-1"
                              tabindex="0"
                              role="menu"
                              style=""
                            ></div>
                          {/if}
                          <DropdownMenu.Group class="min-h-10 mt-2">
                            {#if !categoricalRules?.includes(row?.rule)}
                              {#each row?.step as newValue, index}
                                {#if ruleCondition[row?.rule] === "between"}
                                  {#if newValue && row?.step[index + 1]}
                                    <DropdownMenu.Item
                                      class="sm:hover:bg-primary"
                                    >
                                      <button
                                        on:click={() => {
                                          handleChangeValue([
                                            row?.step[index],
                                            row?.step[index + 1],
                                          ]);
                                        }}
                                        class="block w-full border-b border-gray-600 px-4 py-1.5 text-left text-sm sm:text-[1rem] rounded text-white last:border-0 sm:hover:bg-primary focus:bg-blue-100 focus:text-gray-900 focus:outline-none"
                                      >
                                        {ruleCondition[row?.rule]?.replace(
                                          "between",
                                          "Between",
                                        )}
                                        {row?.step[index + 1]} - {row?.step[
                                          index
                                        ]}
                                      </button>
                                    </DropdownMenu.Item>
                                  {/if}
                                {:else}
                                  <DropdownMenu.Item
                                    class="sm:hover:bg-primary"
                                  >
                                    <button
                                      on:click={() => {
                                        handleChangeValue(newValue);
                                      }}
                                      class="block w-full border-b border-gray-600 px-4 py-1.5 text-left text-sm sm:text-[1rem] rounded text-white last:border-0 sm:hover:bg-primary focus:bg-blue-100 focus:text-gray-900 focus:outline-none"
                                    >
                                      {ruleCondition[row?.rule]
                                        ?.replace("under", "Under")
                                        ?.replace("over", "Over")}
                                      {newValue}
                                    </button>
                                  </DropdownMenu.Item>
                                {/if}
                              {/each}
                            {:else if categoricalRules?.includes(row?.rule)}
                              {#each row?.step as item}
                                <DropdownMenu.Item
                                  class="sm:hover:bg-[#2A2E39]"
                                >
                                  <div
                                    class="flex items-center"
                                    on:click|capture={(event) =>
                                      event.preventDefault()}
                                  >
                                    <label
                                      on:click={() => {
                                        handleChangeValue(item);
                                      }}
                                      class="cursor-pointer text-white"
                                      for={item}
                                    >
                                      <input
                                        type="checkbox"
                                        class="rounded"
                                        checked={isChecked(item)}
                                      />
                                      <span class="ml-2">{item}</span>
                                    </label>
                                  </div>
                                </DropdownMenu.Item>
                              {/each}
                            {/if}
                          </DropdownMenu.Group>
                        </DropdownMenu.Content>
                      </DropdownMenu.Root>
                    </div>
                  </div>
                </div>
              </div>
              <!--End Added Rules-->
            {/each}
          </div>
        {/if}
      </div>

      {#if isLoaded}
        <div class="w-full mt-5 m-auto flex justify-center items-center">
          <div class="w-full grid grid-cols-1 lg:grid-cols-4 gap-y-3 gap-x-3">
            <!--Start Flow Sentiment-->
            <div
              class="flex flex-row items-center flex-wrap w-full px-5 bg-[#1E222D] shadow-lg rounded-md h-20"
            >
              <div class="flex flex-col items-start">
                <span class="font-semibold text-gray-200 text-sm sm:text-[1rem]"
                  >Flow Sentiment</span
                >
                <span
                  class="text-start text-[1rem] font-semibold {flowSentiment ===
                  'Bullish'
                    ? 'text-[#00FC50]'
                    : flowSentiment === 'Bearish'
                      ? 'text-[#FF2F1F]'
                      : flowSentiment === 'Neutral'
                        ? 'text-[#fff]'
                        : 'text-white'}">{flowSentiment}</span
                >
              </div>
            </div>
            <!--End Flow Sentiment-->
            <!--Start Put/Call-->
            <div
              class="flex flex-row items-center flex-wrap w-full px-5 bg-[#1E222D] shadow-lg rounded-md h-20"
            >
              <div class="flex flex-col items-start">
                <span class="font-semibold text-gray-200 text-sm sm:text-[1rem]"
                  >Put/Call</span
                >
                <span class="text-start text-[1rem] font-semibold text-white">
                  {putCallRatio?.toFixed(3)}
                </span>
              </div>
              <!-- Circular Progress -->
              <div class="relative size-14 ml-auto">
                <svg
                  class="size-full w-14 h-14"
                  viewBox="0 0 36 36"
                  xmlns="http://www.w3.org/2000/svg"
                >
                  <!-- Background Circle -->
                  <circle
                    cx="18"
                    cy="18"
                    r="16"
                    fill="none"
                    class="stroke-current text-[#3E3E3E]"
                    stroke-width="3"
                  ></circle>
                  <!-- Progress Circle inside a group with rotation -->
                  <g class="origin-center -rotate-90 transform">
                    <circle
                      cx="18"
                      cy="18"
                      r="16"
                      fill="none"
                      class="stroke-current text-blue-500"
                      stroke-width="3"
                      stroke-dasharray="100"
                      stroke-dashoffset={putCallRatio >= 1
                        ? 0
                        : 100 - (putCallRatio * 100)?.toFixed(2)}
                    ></circle>
                  </g>
                </svg>
                <!-- Percentage Text -->
                <div
                  class="absolute top-1/2 start-1/2 transform -translate-y-1/2 -translate-x-1/2"
                >
                  <span class="text-center text-white text-sm"
                    >{putCallRatio?.toFixed(2)}</span
                  >
                </div>
              </div>
              <!-- End Circular Progress -->
            </div>
            <!--End Put/Call-->
            <!--Start Call Flow-->
            <div
              class="flex flex-row items-center flex-wrap w-full px-5 bg-[#1E222D] shadow-lg rounded-md h-20"
            >
              <div class="flex flex-col items-start">
                <span class="font-semibold text-gray-200 text-sm sm:text-[1rem]"
                  >Call Flow</span
                >
                <span class="text-start text-[1rem] font-semibold text-white">
                  {new Intl.NumberFormat("en", {
                    minimumFractionDigits: 0,
                    maximumFractionDigits: 0,
                  }).format(displayCallVolume)}
                </span>
              </div>
              <!-- Circular Progress -->
              <div class="relative size-14 ml-auto">
                <svg
                  class="size-full w-14 h-14"
                  viewBox="0 0 36 36"
                  xmlns="http://www.w3.org/2000/svg"
                >
                  <!-- Background Circle -->
                  <circle
                    cx="18"
                    cy="18"
                    r="16"
                    fill="none"
                    class="stroke-current text-[#3E3E3E]"
                    stroke-width="3"
                  ></circle>
                  <!-- Progress Circle inside a group with rotation -->
                  <g class="origin-center -rotate-90 transform">
                    <circle
                      cx="18"
                      cy="18"
                      r="16"
                      fill="none"
                      class="stroke-current text-[#00FC50]"
                      stroke-width="3"
                      stroke-dasharray="100"
                      stroke-dashoffset={100 - callPercentage?.toFixed(2)}
                    ></circle>
                  </g>
                </svg>
                <!-- Percentage Text -->
                <div
                  class="absolute top-1/2 start-1/2 transform -translate-y-1/2 -translate-x-1/2"
                >
                  <span class="text-center text-white text-sm"
                    >{callPercentage}%</span
                  >
                </div>
              </div>
              <!-- End Circular Progress -->
            </div>
            <!--End Call Flow-->
            <!--Start Put Flow-->
            <div
              class="flex flex-row items-center flex-wrap w-full px-5 bg-[#1E222D] shadow-lg rounded-md h-20"
            >
              <div class="flex flex-col items-start">
                <span class="font-semibold text-gray-200 text-sm sm:text-[1rem]"
                  >Put Flow</span
                >
                <span class="text-start text-[1rem] font-semibold text-white">
                  {new Intl.NumberFormat("en", {
                    minimumFractionDigits: 0,
                    maximumFractionDigits: 0,
                  }).format(displayPutVolume)}
                </span>
              </div>
              <!-- Circular Progress -->
              <div class="relative size-14 ml-auto">
                <svg
                  class="size-full w-14 h-14"
                  viewBox="0 0 36 36"
                  xmlns="http://www.w3.org/2000/svg"
                >
                  <!-- Background Circle -->
                  <circle
                    cx="18"
                    cy="18"
                    r="16"
                    fill="none"
                    class="stroke-current text-[#3E3E3E]"
                    stroke-width="3"
                  ></circle>
                  <!-- Progress Circle inside a group with rotation -->
                  <g class="origin-center -rotate-90 transform">
                    <circle
                      cx="18"
                      cy="18"
                      r="16"
                      fill="none"
                      class="stroke-current text-[#EE5365]"
                      stroke-width="3"
                      stroke-dasharray="100"
                      stroke-dashoffset={100 - putPercentage?.toFixed(2)}
                    ></circle>
                  </g>
                </svg>
                <!-- Percentage Text -->
                <div
                  class="absolute top-1/2 start-1/2 transform -translate-y-1/2 -translate-x-1/2"
                >
                  <span class="text-center text-white text-sm"
                    >{putPercentage}%</span
                  >
                </div>
              </div>
              <!-- End Circular Progress -->
            </div>
          </div>
        </div>

        <!-- Page wrapper -->
        <div class="flex w-full m-auto h-full overflow-hidden">
          {#if displayedData?.length !== 0}
            <div class="mt-8 w-full overflow-x-auto h-[850px] overflow-hidden">
              <OptionsFlowTable
                {data}
                {optionsWatchlist}
                {displayedData}
                {filteredData}
                {rawData}
              />
            </div>
          {:else}
            <div
              class="text-white text-center p-3 sm:p-5 mb-10 mt-5 rounded-md sm:flex sm:flex-row sm:items-center border border-gray-600 text-sm sm:text-[1rem]"
            >
              <svg
                class="w-6 h-6 flex-shrink-0 inline-block sm:mr-2"
                xmlns="http://www.w3.org/2000/svg"
                viewBox="0 0 256 256"
                ><path
                  fill="#fff"
                  d="M128 24a104 104 0 1 0 104 104A104.11 104.11 0 0 0 128 24m-4 48a12 12 0 1 1-12 12a12 12 0 0 1 12-12m12 112a16 16 0 0 1-16-16v-40a8 8 0 0 1 0-16a16 16 0 0 1 16 16v40a8 8 0 0 1 0 16"
                /></svg
              >
              Looks like your taste is one-of-a-kind! No matches found... yet!
            </div>
          {/if}
        </div>

        <!--
          <div class="relative bottom-[400px] w-fit m-auto flex justify-center items-center">
            <UpgradeToPro data={data} title="Get the recent Options Flow Data from Hedge Funds and major institutional traders to never miss out"/>
          </div>
          -->
      {:else}
        <div class="flex justify-center items-center h-80">
          <div class="relative">
            <label
              class="bg-[#09090B] rounded-xl h-14 w-14 flex justify-center items-center absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2"
            >
              <span class="loading loading-spinner loading-md text-gray-400"
              ></span>
            </label>
          </div>
        </div>
      {/if}
    </div>
  </section>
</body>

<!--Start Choose Rule Modal-->
<input type="checkbox" id="ruleModal" class="modal-toggle" />

<dialog id="ruleModal" class="modal p-2 sm:p-0">
  <label
    id="ruleModal"
    for="ruleModal"
    on:click={() => (searchTerm = "")}
    class="cursor-pointer modal-backdrop bg-[#000] bg-opacity-[0.8]"
  ></label>

  <div
    class="modal-box relative bg-primary z-20 mx-2 min-h-[30vh] h-[800px] rounded bg-default opacity-100 border border-gray-600 bp:mx-3 sm:mx-4 w-full max-w-6xl overflow-y-auto"
  >
    <div class="relative flex flex-col w-full">
      <!-- Sticky Header -->

      <div
        class="fixed w-full h-fit sticky -top-6 z-40 bg-primary shadow-sm opacity-100 pb-6 pt-5 border-gray-600 border-b"
      >
        <div class="flex flex-row items-center justify-between mb-2">
          <h2 class="text-white text-[1rem] sm:text-xl font-semibold">
            Select screener filters ({allRows?.length} total)
          </h2>
          <label
            for="ruleModal"
            class="inline-block cursor-pointer absolute right-0 top-3 text-[1.3rem] sm:text-[1.8rem] text-white"
          >
            <svg
              class="w-6 h-6 sm:w-8 sm:h-8"
              xmlns="http://www.w3.org/2000/svg"
              viewBox="0 0 24 24"
              ><path
                fill="white"
                d="m6.4 18.308l-.708-.708l5.6-5.6l-5.6-5.6l.708-.708l5.6 5.6l5.6-5.6l.708.708l-5.6 5.6l5.6 5.6l-.708.708l-5.6-5.6z"
              /></svg
            >
          </label>
        </div>

        <!-- Start Search bar -->
        <form
          class="w-full h-8"
          on:keydown={(e) => (e?.key === "Enter" ? e.preventDefault() : "")}
        >
          <label for="search" class="text-sm font-medium text-gray-200 sr-only"
            >Search</label
          >
          <div class="relative w-full max-w-sm">
            <div
              class="absolute inset-y-0 start-0 flex items-center ps-3 pointer-events-none"
            >
              <svg
                class="w-4 h-4 text-gray-200"
                aria-hidden="true"
                xmlns="http://www.w3.org/2000/svg"
                fill="none"
                viewBox="0 0 20 20"
              >
                <path
                  stroke="currentColor"
                  stroke-linecap="round"
                  stroke-linejoin="round"
                  stroke-width="2"
                  d="m19 19-4-4m0-7A7 7 0 1 1 1 8a7 7 0 0 1 14 0Z"
                />
              </svg>
            </div>

            <div
              class="absolute inset-y-0 right-0 flex items-center pr-2 {searchTerm?.length >
              0
                ? ''
                : 'hidden'}"
            >
              <button
                on:click={() => (searchTerm = "")}
                class="cursor-pointer text-gray-200 sm:hover:text-white"
                tabindex="0"
                ><svg
                  class="w-5 h-5"
                  fill="none"
                  viewBox="0 0 24 24"
                  stroke="currentColor"
                  style="max-width:40px"
                  ><path
                    stroke-linecap="round"
                    stroke-linejoin="round"
                    stroke-width="2"
                    d="M6 18L18 6M6 6l12 12"
                  ></path></svg
                ></button
              >
            </div>

            <input
              autocomplete="off"
              type="search"
              id="search"
              class="placeholder-gray-300 block w-full p-2 ps-10 text-sm text-gray-200 border border-gray-600 rounded-md bg-secondary border border-blue-500"
              placeholder="Search"
              bind:value={searchTerm}
            />
          </div>
        </form>
        <!-- End Search bar -->
      </div>

      <!-- Content -->
      <div class="text-white mt-5">
        <div class="flex flex-wrap">
          {#each searchTerm?.length !== 0 ? filteredRows : allRows as row}
            <div
              class="flex w-full items-center space-x-1.5 py-1.5 md:w-1/2 lg:w-1/3 lg:py-1"
            >
              {#if row?.rule === "score" && data?.user?.tier !== "Pro"}
                <label id={row?.rule} on:click={() => changeRule(row?.rule)}>
                  <svg
                    class="w-4 h-4 mb-1 inline-block text-[#A3A3A3] sm:hover:text-white cursor-pointer"
                    xmlns="http://www.w3.org/2000/svg"
                    viewBox="0 0 24 24"
                    ><path
                      fill="currentColor"
                      d="M17 9V7c0-2.8-2.2-5-5-5S7 4.2 7 7v2c-1.7 0-3 1.3-3 3v7c0 1.7 1.3 3 3 3h10c1.7 0 3-1.3 3-3v-7c0-1.7-1.3-3-3-3M9 7c0-1.7 1.3-3 3-3s3 1.3 3 3v2H9z"
                    /></svg
                  >
                </label>
              {:else}
                <input
                  on:click={() => changeRule(row?.rule)}
                  id={row?.rule}
                  type="checkbox"
                  checked={ruleOfList?.find((rule) => rule?.name === row?.rule)}
                  class="h-[18px] w-[18px] rounded-sm ring-offset-0 lg:h-4 lg:w-4"
                />
              {/if}
              <div class="-mt-0.5">
                <label for={row?.rule} class="cursor-pointer text-[1rem]"
                  >{row?.label}</label
                >
              </div>
            </div>
          {/each}
        </div>

        {#if searchTerm?.length > 0 && filteredRows?.length === 0}
          <div class="text-white mt-5 font-semibold text-[1rem] sm:text-lg">
            Nothing found
          </div>
        {/if}
      </div>
    </div>
  </div>
</dialog>
<!--End Choose Rule Modal-->

<!--Start Options Detail Desktop Modal-->

<input type="checkbox" id="mobileTooltip" class="modal-toggle" />

<dialog id="mobileTooltip" class="modal p-3">
  <label
    for="mobileTooltip"
    class="cursor-pointer modal-backdrop bg-[#000] bg-opacity-[0.8]"
  ></label>

  <!-- Desktop modal content -->
  <div
    class="modal-box rounded-md border border-gray-600 w-full bg-secondary flex flex-col items-center"
  >
    <div class="text-white mb-5 text-center">
      <h3 class="font-bold text-2xl mb-5">{tooltipTitle}</h3>
      <span class="text-white text-[1rem] font-normal"
        >{infoText?.text ?? "n/a"}</span
      >
      {#if infoText?.equation !== undefined}
        <div class="w-5/6 m-auto mt-5"></div>
        <div class="text-[1rem] w-full pt-3 pb-3 m-auto text-white">
          {infoText?.equation}
        </div>
      {/if}
    </div>

    <div class="border-t border-gray-600 mt-2 w-full">
      <label
        for="mobileTooltip"
        class="mt-4 font-semibold text-white text-xl m-auto flex justify-center"
      >
        Close
      </label>
    </div>
  </div>
</dialog>
