let isTestDeviceStatus = false;
let allHardwareDevices = [];
let allHardwareSettingsTableData = {};
let allDoors = [];
let isLoadingTest = false;
let isLoadingAddNewRowInTable = false;
let allSchedules = [];
let signalWireCredentials = null;
let allSignalWireNumbers = [];
let backendUrl=null;
let isHardwareCardView = false;

const options = {
  web_Relay: [
    {
      value: "Original Web Relay 1 I/O Model X-WR-1R12-1I-I",
      label: "Original Web Relay 1 I/O Model X-WR-1R12-1I-I",
    },
    {
      value: "X-401 Web Relay 2 I/O Model X-401-I",
      label: "X-401 Web Relay 2 I/O Model X-401-I",
    },
    {
      value: "X-412 Web Relay 4 I/O Model X-412-I",
      label: "X-412 Web Relay 4 I/O Model X-412-I",
    },
    {
      value: "X-432 Web Relay 16 I/O Model X-432-I",
      label: "X-432 Web Relay 16 I/O Model X-432-I",
    },
  ],
  SMSIO: [
    { value: "UC1414", label: "UC1414" },
    { value: "UC300", label: "UC300" },
  ],
  Mobotix: [{ value: "_generic", label: "_generic" }],
};

const UC1414Options = [
  { key: "Output 1", value: "output 1" },
  { key: "Output 2", value: "output 2" },
];

const UC1414InputOptions = [
  { key: "Input 1", value: "Input 1" },
  { key: "Input 2", value: "Input 2" },
];

const UC300Options = [
  { key: "Output 1", value: "1" },
  { key: "Output 2", value: "2" },
];

const UC300InputOptions = [
  { key: "Input 1", value: "Input 1" },
  { key: "Input 2", value: "Input 2" },
];

$(document).ready(async function () {
  window.scrollTo({
    top: 0,
    behavior: "smooth",
  });

  const sessionPreferences = sessionStorage.getItem("preferences");
  if(sessionPreferences){
    const preferencesData = await parseJSONData(sessionPreferences);
    preferencesData?.is_card_view==1? isHardwareCardView = true:isHardwareCardView = false;
  }else {
    const preferences = await asyncGetPreferencesRequestForView({
      get_preferences_for_property_user: true,
      property_id: sessionStorage.getItem("propertyId"),
    });
    if(preferences?.length>0) sessionStorage.setItem("preferences",JSON.stringify(preferences[0])); 
    if(preferences?.length>0 && preferences[0]?.is_card_view==1) isHardwareCardView = true;
  }
  isLoadingHardwareCenter(true);
  await sendDoorsRequestInHardware({
    getDoorsRequest: true,
    property_id: sessionStorage.getItem("propertyId"),
  });
  sendHardwareRequest({
    getScheduleRequest: true,
    property_id: sessionStorage.getItem("propertyId"),
    type:'door'
  });
  
  sendHardwareRequest({
    get_streaming_url_request: true
  });
  sendHardwareRequest({
    getHardwareRequest: true,
    property_id: sessionStorage.getItem("propertyId"),
  });
  sendHardwareRequest({
    get_signal_wire_credentials: true,
    property_id: sessionStorage.getItem("propertyId"),
  });
});

function getCsrf_token_hardware(data) {
  return new Promise((resolve, reject) => {
    $.ajax({
      url: "/include/dashboard/settings_requests.php",
      timeout: 10000, // 10 seconds delay
      type: "post",
      data,
      success: function (resp) {
        resolve(resp?.data);
      },
      error: function (xhr, status, error) {
        reject(xhr || error);
      },
    });
  });
}

async function sendDoorsRequestInHardware(data) {
  return new Promise((resolve, reject) => {
    $.ajax({
      url: "/include/property_builder/doors/doors_requests.php",
      type: "post",
      timeout: 10000, // 10 seconds delay
      data,
      success: function (resp1) {
        allDoors = resp1.data;
        // setOptionsOfDoorSelectBox(resp1?.data);
        resolve(resp1.data);
      },
      error: function (xhr, status, error) {
        console.log("error : ", error);
        if (xhr?.responseJSON?.error)
          showErrorGlobalToastMessage(xhr?.responseJSON?.error);
        else showErrorGlobalToastMessage(error);
        reject(error);
      },
    });
  });
}


function sendHardwareRequest(data) {
  $.ajax({
    url: "/include/property_builder/hardwares/hardwares_request.php",
    type: "post",
    timeout: 10000, // 10 seconds delay
    data,
    success: function (resp) {
      if (data?.addHardwareRequest) {
        hardwareView();
        sendHardwareRequest({
          getHardwareRequest: true,
          property_id: sessionStorage.getItem("propertyId"),
        });
      }
      if (data?.getHardwareRequest) {
        allHardwareDevices = resp?.data || [];
        if (window.innerWidth <= 600){
          createHardwareCardsPreview(allHardwareDevices);
        }else if(isHardwareCardView) createHardwareCardsPreview(allHardwareDevices);
        else createHardwareTablePreview(allHardwareDevices);
      }
      if (data?.getHardwareById) {
        bindValuesForEditingHardware(resp.data);
      }
      if (data?.deleteHardwareDevice || data?.editHardwareRequest) {
        hardwareView();
        sendHardwareRequest({
          getHardwareRequest: true,
          property_id: sessionStorage.getItem("propertyId"),
        });
      }
      if (
        data?.addHardwareSettingsRequest ||
        data?.deleteHardwareSettingsDataRequest
      ) {
        $("#add_hardware_settings_modal").modal("hide");
        window.location = "/dashboard.php?tab=property_builder&active=2";
      }
      if (data?.EditHardwareSettingsRequest) {
        isLoadingTestUrl(false);
        $("#add_hardware_settings_modal").modal("hide");
        sendHardwareRequest({
          getHardwareRequest: true,
          property_id: sessionStorage.getItem("propertyId"),
        });
      }
      if (data?.getScheduleRequest) {
        allSchedules = resp.data;
      }
      if (data?.get_signal_wire_credentials) {
        if (resp?.data?.length) {
          signalWireCredentials = resp?.data[0];
          sendHardwareRequest({
            get_signal_wire_numbers: true,
            signalWireId: signalWireCredentials?.id,
          });
        } else allSignalWireNumbers = [];
      }
      if (data?.get_signal_wire_numbers) {
        allSignalWireNumbers = resp?.data;
        populateNumbers(allSignalWireNumbers);
      }else if(data?.get_streaming_url_request){
        backendUrl=`${resp?.data}/api`;
      }
    },
    error: function (xhr, status, error) {      
      isLoadingTestUrl(false);
      isLoadingHardwareCenter(false);
      if (
        xhr?.responseJSON?.error.includes("SQLSTATE[23000]") &&
        xhr?.responseJSON?.error.includes("fk_hardware_settings_device_id")
      ) {
        showErrorGlobalToastMessage(
          "You are controlling the devices using it. So please delete the controlled devices and then delete it "
        );
        return;
      }
      if (xhr?.responseJSON?.error)
        showErrorGlobalToastMessage(xhr?.responseJSON?.error);
      else showErrorGlobalToastMessage(error);
    },
  });
}

function populateNumbers(numbers) {
  let selectBox = document.getElementById("system_control_number");
  selectBox.innerHTML = '<option value="">Select a number</option>';
  numbers.forEach((num) => {
    let option = document.createElement("option");
    option.value = num?.phone_number;
    option.textContent = num?.phone_number;
    selectBox.appendChild(option);
  });
}

async function fetchDataForHardwareSettings(id) {
  return new Promise((resolve, reject) => {
    $.ajax({
      url: "/include/property_builder/hardwares/hardwares_request.php",
      type: "POST",
      timeout: 10000, // 10 seconds delay
      data: { getHardwareSettingsDataRequest: true, id }, // Send the itemId in the request
      success: function (resp) {
        resolve(resp.data);
      },
      error: function (xhr, status, error) {
        reject(error);
      },
    });
  });
}

async function createHardwareCardsPreview(dataArray, searchValue) {
  try {    
    isLoadingHardwareCenter(true);
    let textMatchedHardwares = dataArray.filter(
      (event) =>
        !searchValue ||
        Object.values(event).some(
          (field) => field && field.toString().toLowerCase().includes(searchValue)
        )
    );
    let data = textMatchedHardwares;
    document.getElementById("Hardware_Table").innerHTML="";
    let html = "";
    if (data.length === 0) {
      const searchValue = document.getElementById("search_hardware_value")?.value;
      if (searchValue && searchValue.trim() !== "") {
        html += `<div class="text-center">
          <div class="no-data-card" style="text-align: center; margin: 20px;">
            <div class="card">
              <div class="card-body">
                <h5 class="card-text">No Hardware Found</h5>
                <p class="card-text">No hardware found matching "${searchValue}".</p>
              </div>
            </div>
          </div>
        </div>`;
      } else {
        html += `
          <div class="text-center p-4">
            <i class="fas fa-info-circle text-muted fa-3x mb-3"></i>
            <h5 class="text-muted">No Hardware Found</h5>
            <p class="text-muted">There are no hardware to display.</p>
          </div>
        `;
      }
    } else {
      for (const item of data) {
        const is_sms_io_device = item?.device_type == "SMSIO";
        const device_image_url = createImageForDevice(item);
        allHardwareSettingsTableData[item.id] =
          await fetchDataForHardwareSettings(item.id);
        const windowWidth = window.innerWidth;
        html += `
          <div class="border border-red p-3 mb-4 rounded">
            <div class="d-flex flex-wrap">
              <div class="detail_section d-flex flex-wrap">
                <div class="device_images_cards px-2">
                  <img src="${device_image_url}" alt="device image">
                </div>
                <div class="name">
                  <span class="text-bold">${item.model || "Model Name"}</span>
                  <i class='fas fa-edit text-primary mx-1' style='cursor: pointer;' title='Edit Hardware' onclick="editHardware(${
                    item.id
                  })"></i>
                  <i class='fas fa-trash-alt text-danger mx-1' style='cursor: pointer;' title='Delete Door' onclick='deleteHardwareDevice(${
                    item.id
                  })'></i>
                  ${
                    item?.hardware_is_active !== "true"
                      ? `<div class="not_Active_hardware">
                            <span class="badge badge-danger">
                                <i class="fas fa-exclamation-circle"></i> Not Active
                            </span>
                          </div>`
                      : `<div class="Active_hardware">
                            <span class="badge badge-success">
                                <i class="fas fa-exclamation-circle"></i> Active
                            </span>
                          </div>`
                  }
                  ${
                    is_sms_io_device
                      ? `<div class="not_active_hardware py-1" onclick="openDownloadModal(${item?.id})" style='cursor: pointer;'>
                      <span class="badge badge-success">
                        <i class='fas fa-download mx-1'></i>
                      </span>
                      Download Manual
                  </div>`
                      : ""
                  }
        `;

        // Conditionally render the card for settings data
        if (item?.hardware_is_active === "true") {
          const settingsData = allHardwareSettingsTableData[item.id];
          if (settingsData && settingsData.length > 0) {
            html += `<div class="assigned_doors">`;

            settingsData.forEach((setting, index) => {

              let settingOutput=setting?.output;
              if(item?.model=="UC300"){
                settingOutput=UC300Options.find(ele=>ele.value==setting?.output)?.key
              }

              let inputs_html = '';
              let parsedData = parseString(setting.inputs);
              inputs_html =
              parsedData && parsedData.length
                ? parsedData.map((ele) => ele).join(", ")
                : "N/A"

              let timer_html= '';
              if(!is_sms_io_device){
                timer_html = setting.title || "N/A"
              }else {
                timer_html = setting?.sms_duration || "N/A"
              }

              let outputStatus = setting.status;

              let status_class = "";
              if(!is_sms_io_device){
                outputStatus == "On"
                  ? (status_class = "status-on")
                  : (status_class = "status-off");
              }else {
                setting.status == "On"
                  ? (status_class = "status-on")
                  : (status_class = "status-off");
              }

                let relay_function=null;
                if(!is_sms_io_device){
                  relay_function = `<button class="status_check_button" id="hardware_status_${item.id}_${setting.id}" data-id="${setting?.id}" data-item-id="${item?.id}" onclick="StatusOfRelay(this,${item.id},'On',${setting.id})">Get status</button>`;
                }else {
                  relay_function = `<button class="status_check_button checkStatusButtonPreview" data-id="${setting?.id}" data-item-id="${item?.id}" onclick="testHardwareSMSIoPreview(this, '${item?.id}', '${setting?.id}')">Get status</button>`;
                }

              html += `
                <div class="mt-1 mb-2 cards_detail">
                  <div class="d-flex justify-content-center"> 
                    <i class='fas fa-edit text-primary mx-1' style='cursor: pointer;' title='Edit Door' onclick='editHardwareSettingsInModal(${
                      setting.id
                    },${item.id})'></i>
                    <i class='fas fa-trash-alt text-danger mx-1' style='cursor: pointer;' title='Delete Door' onclick='deleteHardwareSettingsData(${
                      setting.id
                    },${item.id})'></i>
                  </div>
                  <div class="d-flex justify-content-between">
                    <div class="titles">
                      <div class="font-weight-bold">Door name:</div>
                      <div class="font-weight-bold">Output:</div>
                      <div class="font-weight-bold" style="margin-top: 4px;">Output Time:</div>
                      <div class="font-weight-bold">Schedule:</div>
                      <div class="font-weight-bold">Input:</div>
                      <div class="font-weight-bold">O/I Status:</div>
                    </div>

                    <div class="values">
                      <div class="">${setting?.door_name}</div>
                      <div class="">${settingOutput || "N/A"}</div>
                      <div class="">${setting?.sms_duration?setting?.sms_duration:"N/A"}</div>
                      <div class="">${setting?.title}</div>
                      <div class="">${inputs_html}</div>
                      <div> ${relay_function} <span id="SMSIOStatus${item.id}_${setting.id}" style="font-weight:700"> ${!is_sms_io_device?outputStatus:setting.status} </span> ${setting.status_check_date ? `<span>at ${new Date(setting.status_check_date).toLocaleDateString()}</span>` : ''}</div>
                    </div>
                  </div>
                  </div>
                  ${
                    index === settingsData.length - 1
                      ? `
                    <div class="icon-container" onclick="addNewHardwareSettingInModal(${item?.id})">
                      <i class="fas fa-plus"></i>
                    </div>
                    `
                      : ``
                  }                   
              `;
            });

            // html += `</div>`;
          } else {
            html += `<div class="text-center mt-3"><div title="add new hardware setting" class="icon-container" onclick="addNewHardwareSettingInModal(${item?.id})">
                      <i class="fas fa-plus"></i>
                    </div></div>`;
          }
        }

        // Close the main div
        html += ` </div>
                  `;

        html += `     
                </div>
              </div>
            </div>
            </div>`;
      }
    }
    
    document.getElementById("Hardware_Table").innerHTML=html
    isLoadingHardwareCenter(false);
    $(".bootstrap_switch").bootstrapSwitch();
  } catch (error) {
    console.log("error in creating view", error);
    
    isLoadingHardwareCenter(false);
  }
}

async function createHardwareTablePreview(dataArray, properties) {
  try {
    isLoadingHardwareCenter(true);
    let data = dataArray;
    document.getElementById("Hardware_Table").innerHTML=""
    let html = "";
  
    if (data.length === 0) {
      const searchValue = document.getElementById("search_hardware_value")?.value;
      if (searchValue && searchValue.trim() !== "") {
        html += `<div class="text-center">
          <div class="no-data-card" style="text-align: center; margin: 20px;">
            <div class="card">
              <div class="card-body">
                <h5 class="card-text">No Hardware Found</h5>
                <p class="card-text">No hardware found matching "${searchValue}".</p>
              </div>
            </div>
          </div>
        </div>`;
      } else {
        html += `
          <div class="text-center p-4">
            <i class="fas fa-info-circle text-muted fa-3x mb-3"></i>
            <h5 class="text-muted">No Hardware Found</h5>
            <p class="text-muted">There are no hardware to display.</p>
          </div>
        `;
      }
    } else {
      for (const item of data) {
        const device_image_url = createImageForDevice(item);
  
        const is_sms_io_device = item?.device_type == "SMSIO";
        allHardwareSettingsTableData[item.id] =
          await fetchDataForHardwareSettings(item.id);
        html += `
            <div class="border border-red p-3 mb-4 rounded">
              <div class="d-flex flex-wrap">
                <div class="detail_section d-flex">
                  <div class="device_images">
                    <img src="${device_image_url}" alt="device image">
                  </div>
                  <div class="name">
                    <span class="text-bold">${item.model || "Model Name"}</span>
                    <i class='fas fa-edit text-primary mx-1' style='cursor: pointer;' title='Edit Hardware' onclick="editHardware(${
                      item.id
                    })"></i>
                    <i class='fas fa-trash-alt text-danger mx-1' style='cursor: pointer;' title='Delete Door' onclick='deleteHardwareDevice(${
                      item.id
                    })'></i>
                    ${
                      item?.hardware_is_active !== "true"
                        ? `<div class="not_active_hardware">
                              <span class="badge badge-danger">
                                <i class="fas fa-exclamation-circle"></i> Not Active
                              </span>
                            </div>`
                        : ""
                    }
                    ${
                      is_sms_io_device && item?.model !== "UC300"
                        ? `<div class="not_active_hardware py-3" onclick="openDownloadModal(${item?.id})" style='cursor: pointer;'>
                        <span class="badge badge-success">
                          <i class='fas fa-download mx-1'></i>
                        </span>
                        Download Manual
                      </div>`
                        : ""
                    }
                  </div>
                </div>
              </div>
          `;
  
        if (item?.hardware_is_active === "true") {
          const settingsData = allHardwareSettingsTableData[item.id];
          if (item?.device_type != "SMSIO") {
            html += await webRelayTable(item, settingsData);
          } else {
            html += await SMSIOTable(item, settingsData);
          }
        }
  
        // Close the main div
        html += `</div>`;
      }
    }
  
    document.getElementById("Hardware_Table").innerHTML=html;
    isLoadingHardwareCenter(false);
    $(".bootstrap_switch").bootstrapSwitch();

    $(".hardware_data_table").each(function () {  
      if (!$.fn.DataTable.isDataTable(this)) {
        $(this).DataTable({
          "responsive": true,
          "order": [],
          "paging": false,
          "pageLength": -1,
          "searching": false,
        });
      }else if (data?.length > 0) {
        $(this).DataTable().order([]).draw();
      }
    });
  } catch (error) {
    console.log("error in creating view", error);
    isLoadingHardwareCenter(false);
  }
}

async function webRelayTable(item, settingsData) {
  let webRelayHtml = "";
  webRelayHtml = ` <div class="table-responsive" style="overflow-x: auto !important;">
                  <table class="hardware_data_table table table-bordered table-head-fixed text-nowrap table-hover" id="myHardwareWebRelay">
                    <thead>
                      <tr>
                        <th>Door name</th>
                        <th>Output</th>
                        <th>Output Time</th>
                        <th>Schedule</th>
                        <th>Input</th>
                        <th>Status</th>
                        <th>
                          <div style="line-height: 1;">
                            Output/Input Status
                            <small style="font-size: 70%; color: #666;">Last Known</small>
                          </div>
                        </th>
                        <th>Action</th>
                      </tr>
                    </thead>
                    <tbody id="hardware_table_body_${item.id}">`;

  if (settingsData && settingsData.length > 0) {
    settingsData.forEach((setting) => {
      const outputStatus = setting.status;
      // let status_class = "";
      // outputStatus == "On"
      //   ? (status_class = "status-on")
      //   : (status_class = "status-off");

      let parsedData = parseString(setting.inputs);
      
      webRelayHtml += `
        <tr data-setting-id="${setting.id}">
          <td style="vertical-align: middle;">${
            setting.door_name || "N/A"
          }</td>
          <td  style="vertical-align: middle;">${
            setting?.output || "N/A"
          }</td>
          <td style="vertical-align: middle;">${
            setting.sms_duration || "N/A"
          } </td>
          <td style="vertical-align: middle;">${
            setting.title || "N/A"
          } </td>
          <td style="vertical-align: middle;">
            ${
              parsedData && parsedData.length
                ? parsedData.map((ele) => ele).join(", ")
                : "N/A"
            }
          </td>
          <td>
            <button class="status_check_button" id="hardware_status_${item.id}_${setting.id}" data-id="${setting?.id}" data-item-id="${item?.id}" onclick="StatusOfRelay(this,${item.id},'On',${setting.id})">Get status</button> 
          </td>
          <td>
            <span style="font-weight:700">${outputStatus}</span>${setting.status_check_date ? `<span>at ${new Date(setting.status_check_date).toLocaleString()}</span>` : ''}
          </td>
          <td style="vertical-align: middle;">
            <i class='fas fa-edit text-primary mx-1' style='cursor: pointer;' title='Edit Door setting' onclick="editHardwareSettings(${
              setting.id
            }, ${item.id})"></i>
            <i class='fas fa-trash-alt text-danger mx-1' style='cursor: pointer;' title='Delete Door setting' onclick='deleteHardwareSettingsData(${
              setting.id
            },${item.id})'></i>
          </td>
        </tr>
      `;
    });
  } else {
    if (item?.device_type != "SMSIO") {
      addNewRow(item.id);
    } else {
      addNewRowOfSmsIo(item.id);
    }
  }
  webRelayHtml += `
                  </tbody>
                </table>
                <div class="p-2">
                  ${
                    item?.device_type != "SMSIO"
                      ? `<button class="btn btn-primary d-flex"  onclick="addNewRow(${item.id})">Add New Row <img style="width:20px;margin-left:5px;display:none" id="loadingAddNewRowIndicator" src="/include/images/loader.gif" alt="" srcset=""></button>`
                      : `<button class="btn btn-primary d-flex"  onclick="addNewRowOfSmsIo(${item.id})">Add New Row <img style="width:20px;margin-left:5px;display:none" id="loadingAddNewRowIndicator" src="/include/images/loader.gif" alt="" srcset=""></button>`
                  }
                </div>
              </div>
            `;
  return webRelayHtml;
}

async function SMSIOTable(item, settingsData) {
  let smsIOHtml = "";
  smsIOHtml = ` <div class="table-responsive p-0" style="overflow-x: auto !important;">
                  <table class="hardware_data_table table table-bordered table-head-fixed text-nowrap table-hover" id="myHarSMSIoWebRelay">
                    <thead>
                      <tr>
                        <th>Door name</th>
                        <th>Output</th>
                        <th>Ouput Time</th>
                        <th>Schedule</th>
                        <th>Input</th>
                        <th>Status</th>
                        <th>
                          <div style="line-height: 1;">
                            Output/Input Status
                            <small style="font-size: 70%; color: #666;">Last Known</small>
                          </div>
                        </th>
                        <th>Action</th>
                      </tr>
                    </thead>
                    <tbody id="hardware_table_body_${item.id}">`;

  if (settingsData && settingsData.length > 0) {

    settingsData.forEach((setting) => {
      const button = `<button class="status_check_button checkStatusButtonPreview" data-id="${setting?.id}" data-item-id="${item?.id}" onclick="testHardwareSMSIoPreview(this, '${item?.id}', '${setting?.id}')">Get status</button>`;
      let outputValue = "";
      if(item?.model == "UC300"){
        outputValue = UC300Options?.find(
          (ele) => ele?.value == setting?.output
        )?.key;
      }else {
        outputValue = UC1414Options?.find(
          (ele) => ele?.value == setting?.output
        )?.key;
      }

      const outputStatus = setting.status;

      let parsedData = parseString(setting.inputs);
      smsIOHtml += `
        <tr data-setting-id="${setting.id}">
          <td style="vertical-align: middle;">${
            setting.door_name || "N/A"
          }</td>
          <td style="vertical-align: middle;" col-span-2>${
            outputValue || "N/A"
          }</td>
          <td style="vertical-align: middle;">${
            setting?.sms_duration || "N/A"
          } </td>
          <td style="vertical-align: middle;">${
            setting?.title || "N/A"
          } </td>
          <td style="vertical-align: middle;" col-span-2>${
            parsedData && parsedData.length
              ? parsedData.map((ele) => ele).join(", ")
              : "N/A"
          }</td>
          <td style="vertical-align: middle;">${button}</td>
          <td style="vertical-align: middle;"><span style="font-weight:700" id="SMSIOStatus${item.id}_${setting.id}"> ${outputStatus} </span> ${setting.status_check_date ? `<span>at ${new Date(setting.status_check_date).toLocaleString()}</span>` : ''}</td>
          <td style="vertical-align: middle;">
            <i class='fas fa-edit text-primary mx-1' style='cursor: pointer;' title='Edit Door setting' onclick="editSMSHardwareSettings(${
              setting.id
            }, ${item.id})"></i>
            <i class='fas fa-trash-alt text-danger mx-1' style='cursor: pointer;' title='Delete Door setting' onclick='deleteHardwareSettingsData(${
              setting.id
            },${item.id})'></i>
          </td>
        </tr>
      `;
    });
  } else {
    addNewRowOfSmsIo(item.id);
  }

  smsIOHtml += `
                  </tbody>
                </table>
                <div class="p-2">
                  ${
                    item?.device_type != "SMSIO"
                      ? `<button class="btn btn-primary d-flex"  onclick="addNewRow(${item.id})">Add New Row <img style="width:20px;margin-left:5px;display:none" id="loadingAddNewRowIndicator" src="/include/images/loader.gif" alt="" srcset=""></button>`
                      : `<button class="btn btn-primary d-flex"  onclick="addNewRowOfSmsIo(${item.id})">Add New Row <img style="width:20px;margin-left:5px;display:none" id="loadingAddNewRowIndicator" src="/include/images/loader.gif" alt="" srcset=""></button>`
                  }
                </div>
              </div>
            `;
  return smsIOHtml;
}

function createImageForDevice(device) {
  const windowWidth = window.innerWidth;
  const isWideScreen = windowWidth > 600;

  // Define a mapping for device models to image URLs
  const imageMap = {
    UC300: {
      wide: "/include/images/Milesight_UC300_croped.png",
      narrow: "/include/images/Milesight_UC300_croped_horizontal.png",
    },
    UC1414: {
      wide: "/include/images/Ursalink UC1414.png",
      narrow: "/include/images/Ursalink UC1414.png",
    },
    "Original Web Relay 1 I/O Model X-WR-1R12-1I-I": {
      wide: "/include/images/Original Web Relay 1 IO Model X-WR-1R12-1I-I.png",
      narrow:
        "/include/images/Original Web Relay 1 IO Model X-WR-1R12-1I-I_horizontal.png",
    },
    "X-401 Web Relay 2 I/O Model X-401-I": {
      wide: "/include/images/X-401 Web Relay 2 IO Model X-401-I.png",
      narrow:
        "/include/images/X-401 Web Relay 2 IO Model X-401-I_horizontal.png",
    },
    "X-412 Web Relay 4 I/O Model X-412-I": {
      wide: "/include/images/X-412 Web Relay 4 IO Model X-412-I.png",
      narrow:
        "/include/images/X-412 Web Relay 4 IO Model X-412-I_horizontal.png",
    },
    "X-432 Web Relay 16 I/O Model X-432-I": {
      wide: "/include/images/x432a.png",
      narrow: "/include/images/horizontal.png",
    },
  };

  return imageMap[device?.model]?.[isWideScreen ? "wide" : "narrow"] || "";
}
async function addNewRowOfSmsIo(itemId) {
  if (isLoadingAddNewRowInTable) return;
  try {
    if (
      $(`#hardware_table_body_${itemId}`).find("#new-row-marker").length > 0
    ) {
      console.log("New row already exists, skipping...");
      return;
    }

    isLoadingAddNewRowInTable = true;
    isLoadingAddNewRow(true);
    const availableDoors = getAllAvailableDoors();
    let device = allHardwareDevices.find((ele) => ele.id == itemId);
    
    const filteredOutputs = device?.model == "UC300" ? UC300Options : UC1414Options;
    let outputsToExclude = allHardwareSettingsTableData[itemId]?.map(item => item.output) || [];
    const availableOutputs = filteredOutputs.filter(
      (output) => !outputsToExclude.includes(output.value)
    );

    const filteredInputs = device?.model == "UC1414" ? UC1414InputOptions : UC300InputOptions;    

    let newRow = `
      <tr id="new-row-marker">
        <td style="vertical-align: middle;">
          <input type="hidden" id="new-row-marker">
          <select class="form-control" style="min-width: 160px;" required id="doorValue">
            <option value="" disabled selected>Select Door</option>
            ${availableDoors
              .map(
                (door) =>
                  `<option value="${door.id}">${door.door_name}</option>`
              )
              .join("")}
          </select>
        </td>
        <td style="vertical-align: middle;">
          <select class="form-control" style="min-width: 160px;" required id="outputValue">
            <option value="" disabled selected>Select Output</option>
            ${availableOutputs
              ?.map(
                (output) =>
                  `<option value="${output.value}">${output.key}</option>`
              )
              .join("")}
          </select>
        </td>

        <td style="vertical-align: middle;">
          ${device?.model == "UC300" ? `<input type="number" id="sms_io_duration_sms" name="sms_io_duration_sms" class="form-control" title="Sms duration" value="1" max="65535" min="1">` : ``}
        </td>

        <td style="vertical-align: middle;">
          <select class="form-control" style="min-width: 160px;" required id="saveTimerValue">
            <option value="">Select Schedule</option>
              ${allSchedules
                ?.map(
                  (schedule) =>
                    `<option value="${schedule.id}">${schedule.title}</option>`
                )
                .join("")}
          </select>
        </td>

        <td style="vertical-align: middle;">
          <select class="form-control" style="min-width: 160px;" required id="outputValue">
            <option value="" disabled selected>Select Input</option>
            ${filteredInputs
              ?.map(
                (input) =>
                  `<option value="${input.value}">${input.key}</option>`
              )
              .join("")}
          </select>
        </td>
        <td style="vertical-align: middle;">
          <button class="btn btn-primary testHardwareSMSIoButton" data-item-id="${itemId}">Check status</button>
        </td>
        <td style="vertical-align: middle;"><span id="relayStatus${itemId}"></span></td>
        <td style="vertical-align: middle;">
          <button class="btn btn-primary saveSmsIoButton" data-item-id="${itemId}">Save</button>
        </td>
      </tr>
    `;

    const wrappedRow = `<table><tbody>${newRow}</tbody></table>`;
    const cleanWrapped = DOMPurify.sanitize(wrappedRow);
    const sanitizedRow = $(cleanWrapped).find("tbody").html();
    $(`#hardware_table_body_${itemId}`).append(sanitizedRow);
    addNewRowOfSmsIoEventsBinding(`#hardware_table_body_${itemId}`);

    isLoadingAddNewRow(false);
    isLoadingAddNewRowInTable = false;
  } catch (error) {
    console.log("error while adding new row ", error);
    isLoadingAddNewRow(false);
    isLoadingAddNewRowInTable = false;
  }
}

function addNewRowOfSmsIoEventsBinding(containerId) {
  const container = $(containerId);
  container.off("click", ".saveSmsIoButton");
  container.off("click", ".testHardwareSMSIoButton");
  container.on("click", ".saveSmsIoButton", function () {
    const itemId = $(this).data("item-id");
    saveHardwareSettings(this, itemId);
  });
  container.on("click", ".testHardwareSMSIoButton", function () {
    const itemId = $(this).data("item-id");
    testHardwareSMSIo(this, itemId);
  });
}

let testingRowDetails = {
  isTesting: false,
  testingId: "",
  testingSettingsId: "",
};

async function testHardwareSMSIo(button, itemId) {
  // its testing the row status
  const hardware = allHardwareDevices.find((ele) => ele?.id == itemId);
  try {
    let message_body = "";
    if (hardware?.model == "UC300") message_body = `${hardware?.password};status`;
    else message_body = "get status, Reply-STOP-to-opt-out";
    if (!signalWireCredentials)
      throw new Error(`Please add signal wire credentials.`);
    if(!backendUrl){
      throw new Error(`Please add Server VOIP URL`);
    }

    let payload = {
      from_number: hardware?.invisible_intercom_control_number,
      to_number: hardware?.sms_io_number,
      message_body,
      project_id: signalWireCredentials?.project_id,
      space_url: signalWireCredentials?.space_url,
      api_token: signalWireCredentials?.api_token,
    };

    testingRowDetails.isTesting = true;
    testingRowDetails.testingId = itemId;
    testingRowDetails.testingSettingsId = "";
    document.getElementById("smsTestingStatus").innerHTML = "";
    updateStatusMessage("Sending");
    $("#testing_hardware_sms_device").modal({
      backdrop: "static",
      keyboard: false,
    });

    const data = encryptData(payload);
    const csrfToken=await getCsrf_token_hardware({get_csrf_token:true})
    let smsTested = await sendSmsThroughNode({ data }, `${backendUrl}/send_sms`,csrfToken);
    if (smsTested?.socket) { 
      connectSocket(smsTested.socket);
    }
    let fetchStatus = {
      message_sid: smsTested?.message?.sid,
      project_id: signalWireCredentials?.project_id,
      space_url: signalWireCredentials?.space_url,
      api_token: signalWireCredentials?.api_token,
    };
    const fetchEncryption = encryptData(fetchStatus);
    let status = "queued";
    let smsStatus = undefined;
    let statusCounter = 0;
    while (status == "queued" || status == "initiated" || status == "sent") {
      smsStatus = await sendSmsThroughNode(
        {data:fetchEncryption},
        `${backendUrl}/fetch_sms_status`,
        csrfToken
      );
      status = smsStatus?.message?.status;
      updateStatusMessage(status);
      if (smsStatus?.socket) connectSocket(smsStatus?.socket);
      statusCounter++;
      if (statusCounter > 40) {
        smsStatus.message.status = "Not Delivered";
        break;
      }
    }
    if (smsStatus?.message?.status == "delivered") {
      isLoadingToAddNewEvent = false;
      updateStatusMessage("delivered");
      updateStatusMessage("Waiting for device response", "timer");
    }
  } catch (error) {
    console.log("got error", error);
    testingRowDetails.isTesting = false;
    setTimeout(() => {
      $("#testing_hardware_sms_device").modal("hide");
    }, 500);
    // const relayElement = $(`#relayStatus${itemId}`);
    // relayElement
    //   .removeClass("status-on status-off")
    //   .addClass("status-off")
    //   .html("Off");
    showErrorGlobalToastMessage(JSON.stringify(error?.message || error));
  }
}

async function testHardwareSMSIoPreview(button, itemId, Id=null) {
  // its testing the row status
  const hardware = allHardwareDevices.find((ele) => ele?.id == itemId);
  try {
    let message_body = "";
    if (hardware?.model == "UC300") message_body = `${hardware?.password};status`;
    else message_body = "get status, Reply-STOP-to-opt-out";
    if (!signalWireCredentials)
      throw new Error(`Please add signal wire credentials.`);
    if(!backendUrl){
      throw new Error(`Please add Server VOIP URL`);
    }

    let payload = {
      from_number: hardware?.invisible_intercom_control_number,
      to_number: hardware?.sms_io_number,
      message_body,
      project_id: signalWireCredentials?.project_id,
      space_url: signalWireCredentials?.space_url,
      api_token: signalWireCredentials?.api_token,
    };

    testingRowDetails.isTesting = true;
    testingRowDetails.testingId = itemId;
    testingRowDetails.testingSettingsId = Id;
    document.getElementById("smsTestingStatus").innerHTML = "";
    updateStatusMessage("Sending");
    $("#testing_hardware_sms_device").modal({
      backdrop: "static",
      keyboard: false,
    });

    const data = encryptData(payload);
    const csrfToken=await getCsrf_token_hardware({get_csrf_token:true})
    let smsTested = await sendSmsThroughNode({ data }, `${backendUrl}/send_sms`,csrfToken);
    if (smsTested?.socket) { 
      connectSocket(smsTested.socket);
    }

    let fetchStatus = {
      message_sid: smsTested?.message?.sid,
      project_id: signalWireCredentials?.project_id,
      space_url: signalWireCredentials?.space_url,
      api_token: signalWireCredentials?.api_token,
    };
    const fetchEncryption = encryptData(fetchStatus);
    let status = "queued";
    let smsStatus = undefined;
    let statusCounter = 0;
    while (status == "queued" || status == "initiated" || status == "sent") {
      smsStatus = await sendSmsThroughNode(
        { data: fetchEncryption },
        `${backendUrl}/fetch_sms_status`,
        csrfToken
      );
      status = smsStatus?.message?.status;
      updateStatusMessage(status);
      statusCounter++;
      if (statusCounter > 40) {
        smsStatus.message.status = "Not Delivered";
        break;
      }
    }
    if (smsStatus?.message?.status == "delivered") {
      isLoadingToAddNewEvent = false;
      updateStatusMessage("delivered");
      updateStatusMessage("Waiting for device response", "timer");
    }
  } catch (error) {
    console.log("got error", error);
    testingRowDetails.isTesting = false;
    setTimeout(() => {
      $("#testing_hardware_sms_device").modal("hide");
    }, 500);
    updateSMSIOTableWithStatus(testingRowDetails?.testingSettingsId, false,null);
    showErrorGlobalToastMessage(JSON.stringify(error?.message || error));
  }
}

let latestStatus = "";
function updateStatusMessage(status, icon = "check") {
  if (latestStatus === status) return;
  latestStatus = status;
  const statusDisplay = document.getElementById("smsTestingStatus");
  if (statusDisplay) {
    statusDisplay.innerHTML += DOMPurify.sanitize(`<div>Message status : <span class="font-weight-bold">${status} </span>${
      icon == "check"
        ? `<i class="fas fa-check" style="color: green; font-size: 16px;"></i>`
        : `<i class="fas fa-stopwatch" style="color: gray; font-size: 16px;"></i>`
    } </div>`);
  }
}

function connectSocket(wsUrl) {
  const testStatusIcon = document.getElementById("testStatusIconSMS");
  const testHardwareButton = document.getElementById("testHardwareButtonSMS");
  if (wsUrl) {
    const ws = new WebSocket(wsUrl);
    ws.onopen = () => {
      console.log("WebSocket connection established.");
      ws.connectionTimeout = setTimeout(() => {
        if (!isTestDeviceStatus) {
          ws.close();
          showErrorGlobalToastMessage(
            "No response received within 40 seconds. Connection closed."
          );
          console.log("WebSocket connection closed due to timeout.");
        }
      }, 40000);
    };

    ws.onmessage = async (event) => {
      clearTimeout(ws.connectionTimeout);     
      const eventData = await parseJSONData(event?.data);
      updateStatusMessage("Device is active", "check");
      if (testingRowDetails?.isTesting) {
        const relayElement = $(`#relayStatus${testingRowDetails?.testingId}`);
        isTestDeviceStatus = true;
        relayElement
          .removeClass("status-on status-off")
          .addClass("status-on")
          .html(DOMPurify.sanitize("On"));
      } else {
        testHardwareButton.style.backgroundColor = "#229b3c";
        testStatusIcon.style.display = "block";
        testStatusIcon.innerHTML =
        '<i class="fas fa-check" style="color: white; margin-left: 5px;"></i>';
        isTestDeviceStatus = true;
      }
      setTimeout(() => {
        $("#testing_hardware_sms_device").modal("hide");
      }, 1000);
      if(testingRowDetails?.isTesting && testingRowDetails?.testingSettingsId){
        updateSMSIOTableWithStatus(testingRowDetails?.testingSettingsId,true,eventData);
      }
      ws.close();
    };
    ws.onclose = () => {
      clearTimeout(ws.connectionTimeout);
      testingRowDetails.isTesting = false;
      $("#testing_hardware_sms_device").modal("hide");
      if (!isTestDeviceStatus){
        showErrorGlobalToastMessage("Did not receive any response. Try again");
      }
      if(!isTestDeviceStatus && testingRowDetails?.testingSettingsId){
        updateSMSIOTableWithStatus(testingRowDetails?.testingSettingsId, false,null);
      }
      console.log("WebSocket connection closed");
    };
  } else {
    console.error("Failed to get SMS status:", result.error_message);
  }
}

async function updateSMSIOTableWithStatus(id,status,eventData){
  const hardware = allHardwareDevices.find((ele) => ele?.id == testingRowDetails?.testingId);
  const settings = allHardwareSettingsTableData[hardware?.id].find((ele) => ele?.id == id);
  const status_string = await getDeviceStatusString(settings,eventData,hardware);

  const payload = {
    updateSMSIOTableWithStatusRequest: true,
    id,
    status: eventData ? status_string || "Off" : status ? "On" : "Off",
    status_check_date: new Date().toISOString()
  }
  
  const hardwarePromiseData = await hardwarePromiseRequest(payload);
  console.log("hardwarePromiseData",hardwarePromiseData);
  sendHardwareRequest({
    getHardwareRequest: true,
    property_id: sessionStorage.getItem("propertyId"),
  });
}

async function getDeviceStatusString(settings,eventData,hardware){
  let status_string='';
  if(eventData && hardware?.model == "UC300"){
    const selected_output=settings.output;
    const statusInfo = await getSMSIOStatusInfo(eventData?.Body);
    if(selected_output=="1"){
      status_string=statusInfo.output1;
    }else if(selected_output=="2"){
      status_string=statusInfo.output2;
    }
    const selected_input=parseString(settings.inputs);
    if(selected_input?.length>0){
      selected_input?.forEach(input=>{
        if(input=="Input 1"){
          status_string+=" "+statusInfo?.input1;
        }else if(input=="Input 2"){
          status_string+=" "+statusInfo?.input2;
        }
      })
    }
    return status_string;
  }else if (eventData && hardware?.model == "UC1414"){ 
    const selected_output = settings.output;
    const str = eventData?.Body;
    const statusInfo = await getSMSIOStatusInfoUC1414(str);
    
    if(selected_output=="output 1"){
      status_string=statusInfo.output1;
    }else if(selected_output=="output 2"){
      status_string=statusInfo.output2;
    }
    const selected_input=parseString(settings.inputs);
    if(selected_input?.length>0){
      selected_input?.forEach(input=>{
        if(input=="Input 1"){
          status_string+=" "+statusInfo?.input1;
        }else if(input=="Input 2"){
          status_string+=" "+statusInfo?.input2;
        }
      })
    }
    
    return status_string;
  }
}

async function getSMSIOStatusInfo(str) {
  const sections = str.split(";");

  const doSection = sections.find(s => s.trim().startsWith("DO"));
  const diSection = sections.find(s => s.trim().startsWith("DI"));

  if (!doSection || !diSection) return null;

  const doValues = doSection
    .split(",")
    .slice(1)
    .map(v => v.trim())
    .filter(v => v);

  const diValues = diSection
    .split(",")
    .slice(1)
    .map(v => v.trim())
    .filter(v => v);

  const result = {
    output1: doValues[0] === "Open" ? "On" : "Off",
    output2: doValues[1] === "Open" ? "On" : "Off",
    input1: diValues[0] === "Activate" ? "On" : "Off",
    input2: diValues[1] === "Activate" ? "On" : "Off",
    input3: diValues[2] === "Activate" ? "On" : "Off",
    input4: diValues[3] === "Activate" ? "On" : "Off",
  };

  return result;
}

async function getSMSIOStatusInfoUC1414(str) {
  const parts = str?.split(",")?.filter(p => p?.includes("/"));
  const values = parts
    .map(p => p.split("/").map(v => v.trim()))
    .flat();
  const result = {
    input1: values[0]=="De-Activate"?"Off":"On",
    input2: values[1]=="De-Activate"?"Off":"On",
    output1: values[2]=="De-Activate"?"Off":"On",
    output2: values[3]=="De-Activate"?"Off":"On",
    
  }
  return result;
}

async function hardwarePromiseRequest(data) {
  return new Promise((resolve, reject) => {
    $.ajax({
      url: "/include/property_builder/hardwares/hardwares_request.php",
      type: "POST",
      timeout: 10000, // 10 seconds delay
      data,
      success: function (resp) {
        resolve(resp.data);
      },
      error: function (xhr, status, error) {
        reject(error);
      },
    });
  });
}

async function editSMSHardwareSettings(id, itemId) {
  const rowToEdit = $(`#hardware_table_body_${itemId}`).find(
    `tr[data-setting-id="${id}"]`
  );
  if (!rowToEdit.length) return; // Exit if row not found
  let hardwareTableData = allHardwareSettingsTableData[itemId].find(
    (ele) => ele.id == id
  );
  if (!hardwareTableData) return;
  const hardware_device = allHardwareDevices?.find(
    (ele) => ele.id == hardwareTableData?.device_id
  );

  const availableDoors = getAllAvailableDoors(hardwareTableData?.assigned_door);
  const filteredOutputs =
    hardware_device?.model == "UC300" ? UC300Options : UC1414Options;
  const filteredInputs = hardware_device?.model == "UC1414" ? UC1414InputOptions : UC300InputOptions;

  let newEditableRow = `
    <tr data-setting-id="${id}">
      <td style="vertical-align: middle;">
        <select class="form-control" required id="editDoorValue">
          <option value="" disabled>Select Door</option>
          ${availableDoors
            .map(
              (door) =>
                `<option value="${door.id}" ${
                  door.door_name === hardwareTableData.door_name
                    ? "selected"
                    : ""
                }>${door.door_name}</option>`
            )
            .join("")}
        </select>
      </td>
      <td style="vertical-align: middle;">
        <select class="form-control" required value="${
          hardwareTableData?.output
        }" id="editOutputValue">
          <option value="" disabled >Select Output</option>
            ${filteredOutputs
              ?.map(
                (output) =>
                  `<option value="${output.value}">${output.key}</option>`
              )
              .join("")}
        </select>
      </td>
      <td style="vertical-align: middle;">${hardware_device?.model == "UC300" ? `<input type="number" value="${hardwareTableData?.sms_duration}" id="edit_sms_io_duration_sms" name="sms_io_duration_sms" class="form-control" title="Sms duration" value="1" max="65,535" min="1">` : ``}</td>

      <td style="vertical-align: middle;">
          <select class="form-control" style="min-width: 160px;" required id="editTimerValue">
            <option value="">Select Schedule</option>
              ${allSchedules
                ?.map(
                  (schedule) =>
                    `<option value="${schedule.id}" ${
                      hardwareTableData?.calendarId == schedule.id ? "selected" : ""
                    }>${schedule.title}</option>`
                )
                .join("")}
          </select>
      </td>

      <td style="vertical-align: middle;">
       <select class="form-control select2-multi" required id="editInputValue" value="${hardwareTableData?.inputs}" multiple>
          <option value="" disabled >Select Input</option>
            ${filteredInputs
              ?.map(
                (input) =>
                  `<option value="${input.value}">${input.key}</option>`
              )
              .join("")}
        </select>
      </td>

      <td style="vertical-align: middle;"><button class="btn btn-primary checkStatusButton" data-id="${id}" data-item-id="${itemId}">Check status</button></td>
      <td style="vertical-align: middle;"><span id="relayStatus${itemId}"></span></td>
      <td style="vertical-align: middle;"><button class="btn btn-primary saveEditHardwareSettingsButton" data-id="${id}" data-item-id="${itemId}">Save</button></td>
    </tr>
  `;

  const wrappedRow = `<table><tbody>${newEditableRow}</tbody></table>`;
  const cleanWrapped = DOMPurify.sanitize(wrappedRow);
  const sanitizedTr = $(cleanWrapped).find("tr").first();
  rowToEdit.replaceWith(sanitizedTr);
  newEditableRowEventsBinding(`#hardware_table_body_${itemId}`);

  $(`#hardware_table_body_${itemId} .select2-multi`).select2({
    theme: "bootstrap4",
    placeholder: "Select Input",
    allowClear: true,
  });
}

function newEditableRowEventsBinding(containerId) {
  const container = $(containerId);
  container.off("click", ".saveEditHardwareSettingsButton");
  container.off("click", ".checkStatusButton");
  
  container.on("click", ".saveEditHardwareSettingsButton", function () {
    const id = $(this).data("id");
    const itemId = $(this).data("item-id");
    saveEditHardwareSettings(this, itemId, id);
  });
  container.on("click", ".checkStatusButton", function () {
    const itemId = $(this).data("item-id");
    testHardwareSMSIo(this, itemId);
  });
}

async function editHardwareSettings(id, itemId) {
  const rowToEdit = $(`#hardware_table_body_${itemId}`).find(
    `tr[data-setting-id="${id}"]`
  );
  if (!rowToEdit.length) {
    return; // Exit if row not found
  }
  let hardwareTableData = allHardwareSettingsTableData[itemId].find(
    (ele) => ele.id == id
  );
  if (!hardwareTableData) return;

  const inputOutputDat = await getAvailableOutputs(
    itemId,
    hardwareTableData?.output
  );
  const availableOutputs = inputOutputDat?.outputs || [];
  const availableInputs = inputOutputDat?.inputs || [];
  const availableDoors = getAllAvailableDoors(hardwareTableData?.assigned_door);

  let newEditableRow = `
    <tr data-setting-id="${id}">
      <td style="vertical-align: middle;">
        <select class="form-control" required id="editDoorValue">
          <option value="" disabled>Select Door</option>
          ${availableDoors
            .map(
              (door) =>
                `<option value="${door.id}" ${
                  door.door_name === hardwareTableData.door_name
                    ? "selected"
                    : ""
                }>${door.door_name}</option>`
            )
            .join("")}
        </select>
      </td>
      <td style="vertical-align: middle;">
        <select class="form-control" required id="editOutputValue">
          <option value="" disabled>Select Output</option>
          ${availableOutputs
            ?.map(
              (output) =>
                `<option value="${output.key}" ${
                  hardwareTableData.output === output.key ? "selected" : ""
                }>${output.key}</option>`
            )
            .join("")}
        </select>
      </td>
      <td style="vertical-align: middle;"><input type="number" value="${hardwareTableData?.sms_duration}" id="edit_sms_io_duration_sms" name="sms_io_duration_sms" class="form-control" title="Sms duration" value="1" max="65,535" min="1"></td>
      <td style="vertical-align: middle;">
        <select class="form-control" required id="editTimerValue">
        <option value="">Select Schedule</option>
          ${allSchedules
            ?.map(
              (schedule) =>
                `<option value="${schedule.id}" ${
                  hardwareTableData?.calendarId == schedule.id ? "selected" : ""
                }>${schedule.title}</option>`
            )
            .join("")}
        </select>
      </td>

      <td style="vertical-align: middle;">
        <select class="form-control select2-multi" required id="editInputValue" multiple>
          ${availableInputs
            ?.map(
              (input) =>
                `<option value="${input.key}" ${
                  hardwareTableData.inputs.includes(input.key) ? "selected" : ""
                }>${input.key}</option>`
            )
            .join("")}
        </select>
      </td>
      <td style="vertical-align: middle;"><button class="btn btn-primary testStatusOfRelayButtonEdit" data-item-id="${itemId}" onclick="testStatusOfRelay(this,${itemId})">Check status</button></td>
      <td style="vertical-align: middle;"><span id="relayStatus${itemId}"></span></td>
      <td style="vertical-align: middle;"><button class="btn btn-primary saveEditHardwareSettingsButtonInEdit" data-id="${id}" data-item-id="${itemId}">Save</button></td>
    </tr>
  `;
  const wrappedRow = `<table><tbody>${newEditableRow}</tbody></table>`;
  const cleanWrapped = DOMPurify.sanitize(wrappedRow);
  const sanitizedTr = $(cleanWrapped).find("tr").first();
  rowToEdit.replaceWith(sanitizedTr);
  const container = $(`#hardware_table_body_${itemId}`);
  container.off("click", ".saveEditHardwareSettingsButtonInEdit");
  container.off("click", ".testStatusOfRelayButtonEdit");
  container.on("click", ".saveEditHardwareSettingsButtonInEdit", function () {
    const id = $(this).data("id");
    const itemId = $(this).data("item-id");
    saveEditHardwareSettings(this, itemId, id);
  });

  container.on("click", ".testStatusOfRelayButtonEdit", function () {
    const itemId = $(this).data("item-id");
    testStatusOfRelay(this, itemId);
  });


  $(`#hardware_table_body_${itemId} .select2-multi`).select2({
    theme: "bootstrap4",
    placeholder: "Select Input",
    allowClear: true,
  });
}

function saveEditHardwareSettings(button, itemId, id) {
  const row = button.closest("tr");
  const assignedTo = row.querySelector("#editDoorValue").value;
  const outputValue = row.querySelector("#editOutputValue").value;
  const inputValue = $(row).find("#editInputValue").val();
  const timerValue = $(row).find("#editTimerValue").val();
  const sms_duration = $(row).find("#edit_sms_io_duration_sms").val();
  

  if (!assignedTo || !outputValue) {
    showErrorGlobalToastMessage("Please add all required values");
    return;
  }
  if (inputValue?.length > 3) {
    showErrorGlobalToastMessage("You can only select three Inputs");
    return;
  }

  const device = allHardwareDevices?.find((ele) => ele.id == itemId);
  let payload = {
    device_id: itemId,
    id,
    assigned_door: assignedTo,
    inputs: JSON.stringify(inputValue),
    output: outputValue,
    ipAddress: device?.ip_address,
    ipPort: device?.http_port,
    completeUrl: device?.complete_url,
    timer: timerValue ? timerValue : null,
    sms_duration:sms_duration||0,
    property_id: sessionStorage.getItem("propertyId"),
    EditHardwareSettingsRequest: true,
    status_check_date:new Date().toISOString()
  };

  sendHardwareRequest(payload);
}

function parseString(stringifyData) {
  try {
    const decodedData = stringifyData.replace(/&quot;/g, '"');
    return JSON.parse(decodedData);
  } catch (error) {
    return "";
  }
}
async function addNewRow(itemId) {
  if (isLoadingAddNewRowInTable) return;
  try {
    if (
      $(`#hardware_table_body_${itemId}`).find("#new-row-marker").length > 0
    ) {
      console.log("New row already exists, skipping...");
      return;
    }
    const availableDoors = getAllAvailableDoors();
    const inputOutputDat = await getAvailableOutputs(itemId);
    const availableOutputs = inputOutputDat?.outputs || [];
    const availableInputs = inputOutputDat?.inputs || [];
    isLoadingAddNewRowInTable = true;
    isLoadingAddNewRow(true);
    let newRow = `
      <tr>
        <td style="vertical-align: middle;">
          <input type="hidden" id="new-row-marker">
          <select class="form-control" style="min-width: 160px;" required id="doorValue">
            <option value="" disabled selected>Select Door</option>
            ${availableDoors
              .map(
                (door) =>
                  `<option value="${door.id}">${door.door_name}</option>`
              )
              .join("")}
          </select>
        </td>
        <td style="vertical-align: middle;">
          <select class="form-control" style="min-width: 160px;" required id="outputValue">
            <option value="" disabled selected>Select Output</option>
            ${availableOutputs
              ?.map(
                (output) =>
                  `<option value="${output.key}">${output.key}</option>`
              )
              .join("")}
          </select>
        </td>
        <td style="vertical-align: middle;">
            <input type="number" class="form-control" id="sms_io_duration_sms" placeholder="Output Time" min="0">
        </td>
        <td style="vertical-align: middle;">
          <select class="form-control" style="min-width: 160px;" required id="saveTimerValue">
            <option value="">Select Schedule</option>
              ${allSchedules
                ?.map(
                  (schedule) =>
                    `<option value="${schedule.id}">${schedule.title}</option>`
                )
                .join("")}
          </select>
        </td>
        <td style="vertical-align: middle;">
           <select class="form-control select2-multi" style="min-width: 160px;" required id="inputValue" multiple>
            ${availableInputs
              ?.map(
                (input) => `<option value="${input.key}">${input.key}</option>`
              )
              .join("")}
          </select>
        </td>
        <td style="vertical-align: middle;"><button class="btn btn-primary testStatusOfRelayButtonAddNew" data-item-id="${itemId}">Check status</button></td>
        <td style="vertical-align: middle;"><span id="relayStatus${itemId}"></span></td>
        <td style="vertical-align: middle;"><button class="btn btn-primary saveHardwareSettingsButton" data-item-id="${itemId}">Save</button> </td>
      </tr>
    `;

    const wrappedRow = `<table><tbody>${newRow}</tbody></table>`;
    const cleanWrapped = DOMPurify.sanitize(wrappedRow);
    const sanitizedRow = $(cleanWrapped).find("tbody").html();
    $(`#hardware_table_body_${itemId}`).append(sanitizedRow);

    addNewRowEventsBinding(`#hardware_table_body_${itemId}`);
    $(`#hardware_table_body_${itemId} .select2-multi`).select2({
      theme: "bootstrap4",
      placeholder: "Select Input",
      allowClear: true,
    });
    isLoadingAddNewRow(false);
    isLoadingAddNewRowInTable = false;
  } catch (error) {
    console.log("Error while adding new row web relay", error);
    isLoadingAddNewRow(false);
    isLoadingAddNewRowInTable = false;
  }
}

function addNewRowEventsBinding(containerId) {
  const container = $(containerId);
  container.off("click", ".testStatusOfRelayButtonAddNew");
  container.off("click", ".saveHardwareSettingsButton");
  container.on("click", ".testStatusOfRelayButtonAddNew", function () {
    const itemId = $(this).data("item-id");
    testStatusOfRelay(this, itemId);
  });
  container.on("click", ".saveHardwareSettingsButton", function () {
    const itemId = $(this).data("item-id");
    saveHardwareSettings(this, itemId);
  });
}

async function getAvailableOutputs(hardwareId, editOutput = null) {
  const hardware = allHardwareDevices?.find((ele) => ele.id == hardwareId);
  if (hardware) {
    let objectData = await fetchDataForItem(hardware?.complete_url,hardware?.user_name,hardware?.password);
    allOutputsForDevice = [];
    allInputsForDevice = [];
    if (hardware?.model == "Original Web Relay 1 I/O Model X-WR-1R12-1I-I") {
      allOutputsForDevice = objectData?.outputs?.slice(0, 1);
      allInputsForDevice = objectData?.inputs?.slice(0, 1);
    } else if (hardware?.model == "X-401 Web Relay 2 I/O Model X-401-I") {
      allOutputsForDevice = objectData?.outputs?.slice(0, 2);
      allInputsForDevice = objectData?.inputs?.slice(0, 2);
    } else if (hardware?.model == "X-412 Web Relay 4 I/O Model X-412-I") {
      allOutputsForDevice = objectData?.outputs?.slice(0, 4);
      allInputsForDevice = objectData?.inputs?.slice(0, 4);
    } else if (hardware?.model == "X-432 Web Relay 16 I/O Model X-432-I") {
      allOutputsForDevice = objectData?.outputs?.slice(0, 16);
      allInputsForDevice = objectData?.inputs?.slice(0, 16);
    }
    let outputsToExclude =
      allHardwareSettingsTableData[hardwareId]?.map((item) => item.output) ||
      [];

    if (editOutput)
      outputsToExclude = outputsToExclude?.filter((ele) => ele !== editOutput);
    const filteredOutputs = allOutputsForDevice?.filter(
      (output) => !outputsToExclude.some((exclude) => exclude === output.key)
    );
    return { outputs: filteredOutputs, inputs: allInputsForDevice };
  }
}

function getAllAvailableDoors(editDoor = null) {
  let allUsedDoors = [];

  if (allHardwareSettingsTableData) {
    Object.keys(allHardwareSettingsTableData)?.map((key) => {
      allHardwareSettingsTableData[key].map((setting) => {
        if (setting?.assigned_door !== editDoor)
          allUsedDoors.push({ door_id: setting?.assigned_door });
      });
    });
    const remainingDoors = allDoors.filter(
      (door) => !allUsedDoors.some((usedDoor) => usedDoor.door_id === door.id)
    );
    return remainingDoors;
  } else return [];
}
async function changeStatusOfInput(button, itemId, status, settingId, input) {
  try {
    if (isLoadingTest) return;
    isLoadingTest = true;
    let hardwareSetting = allHardwareSettingsTableData[itemId]?.find(
      (ele) => ele.id == settingId
    );

    let urlToStatus = "";
    if (status == "1") {
      urlToStatus = `${hardwareSetting?.completeUrl}?${input}=0`;
    } else {
      urlToStatus = `${hardwareSetting?.completeUrl}?${input}=1`;
    }

    let respOfStatus = await fetchDataForItem(urlToStatus);
    isLoadingTest = false;
  } catch (error) {
    isLoadingTest = false;
    showErrorGlobalToastMessage(error);
  }
}
async function StatusOfRelay(button, itemId, on, settingId) {
  if (isLoadingTest) return;
  const originalText = button.textContent || button.innerText;
  button.disabled = true;
  button.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Loading';
  try {
    isLoadingTest = true;
    
    let hardwareSetting = allHardwareSettingsTableData[itemId]?.find(
      (ele) => ele.id == settingId
    );

    let hardwareDevice = allHardwareDevices.find((ele) => ele.id == itemId);
    let respOfStatus = await fetchDataForItem(hardwareSetting?.completeUrl,hardwareDevice?.user_name,hardwareDevice?.password);
    const hardwareInputs=parseString(hardwareSetting?.inputs);
    const inputStatus = hardwareInputs.map((inputKey) => {
      const value = respOfStatus?.inputs.find((inputObj) => {
        return inputObj.key === inputKey;
      });
    
      return {
        key: inputKey,
        value: value?.value
      };
    });
    let inputStatusSting="";
    inputStatus.map((ele)=>{
      if(ele.value==1){
        inputStatusSting+="On ";
      }else {
        inputStatusSting+="Off ";
      }
    })
    
    const outputStatus =
      respOfStatus?.outputs.find((ele) => ele.key == hardwareSetting.output)
          ?.value == 1
          ? "On"
          : "Off";
    const completeStatusString=outputStatus+ " " + inputStatusSting;
    
    const statusUpdatePayload = {
      updateSMSIOTableWithStatusRequest: true,
      id: settingId,
      status: completeStatusString,
      status_check_date: new Date().toISOString()
    };

    await hardwarePromiseRequest(statusUpdatePayload);
    
    sendHardwareRequest({
      getHardwareRequest: true,
      property_id: sessionStorage.getItem("propertyId"),
    });
    
    // Reset button state
    button.disabled = false;
    button.innerHTML = originalText;
    isLoadingTest = false;
    console.log("worked :",hardwareSetting?.completeUrl);
  } catch (error) {
    // Reset button state on error
    button.disabled = false;
    button.innerHTML = originalText;
    isLoadingTest = false;
    
    const statusUpdatePayload = {
      updateSMSIOTableWithStatusRequest: true,
      id: settingId,
      status: 'Off',
      status_check_date: new Date().toISOString()
    };
    showErrorGlobalToastMessage("Device is offline");
    await hardwarePromiseRequest(statusUpdatePayload);
    sendHardwareRequest({
      getHardwareRequest: true,
      property_id: sessionStorage.getItem("propertyId"),
    });
    console.log("got error while changing status", error);
  }
}

async function saveHardwareSettings(button, itemId) {
  const row = button.closest("tr");
  const assignedTo = row.querySelector("#doorValue").value;
  const outputValue = row.querySelector("#outputValue").value;
  const inputValue = $(row).find("#inputValue").val();
  const timer = $(row).find("#saveTimerValue").val();
  const sms_duration = $(row).find("#sms_io_duration_sms").val();
  const status = $(`#relayStatus${itemId}`).text();
  const property_id = sessionStorage.getItem("propertyId");
  if (!property_id) {
    showErrorGlobalToastMessage("Please select property id from header");
    return;
  }
  if (!assignedTo || !outputValue || !status) {
    showErrorGlobalToastMessage(
      "Please add all required values and check status to continue"
    );
    return;
  }

  const isAlreadyAssigned = allHardwareSettingsTableData[itemId]?.find(
    (ele) => ele.output == outputValue
  );

  const isAlreadyAssignedDoor = allHardwareSettingsTableData[itemId]?.find(
    (ele) => ele.assigned_door == assignedTo
  );

  if (isAlreadyAssignedDoor) {
    showErrorGlobalToastMessage(
      "You have already assigned the door. Please select another one"
    );
    return;
  }

  if (isAlreadyAssigned) {
    showErrorGlobalToastMessage(
      "You have already assigned the Input/Output. Please select another one "
    );
    return;
  }
  if (inputValue?.length > 3) {
    showErrorGlobalToastMessage("You can only select three Inputs");
    return;
  }

  const device = allHardwareDevices?.find((ele) => ele.id == itemId);
  let payload = {
    device_id: itemId,
    assigned_door: assignedTo,
    inputs: JSON.stringify(inputValue) || " ",
    output: outputValue,
    ipAddress: device?.ip_address,
    ipPort: device?.http_port,
    completeUrl: device?.complete_url,
    status,
    addHardwareSettingsRequest: true,
    property_id,
    sms_duration: sms_duration || 0,
    status_check_date:new Date().toISOString()
  };
  if (timer) payload["timer"] = timer;
  else payload["timer"] = "null";
  sendHardwareRequest(payload);
}

async function testStatusOfRelay(button, itemId) {
  // Check if already loading to prevent multiple requests
  if (isLoadingTest) return;
  
  // Store original button text BEFORE any changes
  const originalText = button.textContent || button.innerText;
  button.disabled = true;
  button.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Loading';
  
  try {
    isLoadingTest = true;
    const row = button.closest("tr");
    const outputValue = row.querySelector("#outputValue")?.value || row.querySelector("#editOutputValue")?.value;
    const inputValue = row.querySelector("#inputValue")?.value || row.querySelector("#editInputValue")?.value;
    
    document.getElementById(`relayStatus${itemId}`).innerHTML=""
    if (!outputValue) {
      isLoadingTest = false;
      button.disabled = false;
      button.innerHTML = originalText;
      showErrorGlobalToastMessage("Please select Input/Output");
      return;
    }
    
    let selectedDevice = allHardwareDevices?.find((ele) => ele.id == itemId);
    let objectData = await fetchDataForItem(selectedDevice?.complete_url,selectedDevice?.user_name,selectedDevice?.password);
    
    let statusText = "";
    let statusClass = "";
    
    if (outputValue) {
      let selected = objectData?.outputs?.find((ele) => ele.key == outputValue);
      const outputStatus = selected?.value == "0" ? "Off" : "On";
      statusText += outputStatus;
    } 
    if (inputValue) {
      let selected = objectData?.inputs?.find((ele) => ele.key == inputValue);
      const inputStatus = selected?.value == "0" ? "Off" : "On";
      statusText += " " + inputStatus;
    }

    // Update the text and apply the appropriate class
    const relayElement = $(`#relayStatus${itemId}`);
    relayElement
      .removeClass("status-on status-off") // Remove any existing status class
      .addClass(statusClass) // Add the new class
      .html(DOMPurify.sanitize(statusText)); // Update the text
      
    // Reset button state
    button.disabled = false;
    button.innerHTML = originalText;
    isLoadingTest = false;
  } catch (error) {
    // Reset button state on error
    button.disabled = false;
    button.innerHTML = originalText;
    isLoadingTest = false;
    showErrorGlobalToastMessage("Error checking status: " + (error?.message || error));
    console.log("Error checking status:", error);
  }
}

async function fetchDataForItem(deviceUrl, userName='', password='', status = false) {  
  return new Promise((resolve, reject) => {
    $.ajax({
      url: "/include/property_builder/hardwares/hardwares_request.php",
      type: "POST",
      timeout: 10000, // 10 seconds delay
      data: { checkHardwareStatusRequest: true, request_url: deviceUrl,userName,password }, // Send the itemId in the request
      success: function (resp) {
        try {
          if (!status) {
            const parsedData = JSON.parse(resp.data);
            const filteredData = {
              inputs: [],
              outputs: [],
            };
            for (const key in parsedData) {
              if (parsedData.hasOwnProperty(key) && key.includes("relay")) {
                filteredData.outputs.push({ value: parsedData[key], key });
              }
            }
            for (const key in parsedData) {
              if (
                parsedData.hasOwnProperty(key) &&
                key.includes("digitalInput")
              ) {
                filteredData.inputs.push({ value: parsedData[key], key });
              }
            }
            resolve(filteredData);
          } else {
            resolve(resp.data);
          }
        } catch (error) {
          console.error("Error parsing response data: ", error);
          reject(error);
        }
      },
      error: function (xhr, status, error) {
        if (xhr?.responseJSON?.error) reject(xhr?.responseJSON?.error);
        else reject(error);
      },
    });
  });
}

function bindValuesForEditingHardware(data) {
  if (data?.device_type == "SMSIO") {
    handleTypeChange(false); // creating the fields for SMSIO
  } else {
    handleTypeChange(true); // creating the fields for Web Relay
  }
  // const form_container = document.getElementById("hardware_form");
  // const hardware_view_container = document.getElementById("hardware_view");
  // hardware_view_container.style.display = "none";
  // form_container.style.display = "block";

  document.querySelector("#hardwareId").value = data?.id || "";
  document.querySelector("#device_type").value = data?.device_type || "";
  document.querySelector("#webrelayModel").value = data?.model || "";
  document.querySelector("#hardware_is_active").value =
    data?.hardware_is_active || "";
  // document.querySelector("#property_id").value = data?.property_id || "";
  document.querySelector("#sms_io_password").value =
    data?.password || "";
  document.querySelector("#hardware_user_name").value = data?.user_name || "";
  document.querySelector("#hardware_password").value = data?.password || "";
  document.querySelector("#ip_address").value = data?.ip_address || "";
  document.querySelector("#http_port").value = data?.http_port || "";
  document.querySelector("#sms_io_number").value = data?.sms_io_number || "";
  document.querySelector("#system_control_number").value =
    data?.invisible_intercom_control_number || "";
  createHardwareUrl();
  setModelOptions(data);

  $("#add_edit_hardware_form_modal").modal("show");
  setTimeout(() => {
    onSelectionChange();
  }, 100);
}

// function deleteHardwareDevice(id) {
//   if (!confirm("Are you sure you want to delete")) return;
//   sendHardwareRequest({ id, deleteHardwareDevice: true ,property_id:sessionStorage.getItem("propertyId")});
// }
function deleteHardwareDevice(id) {
  showConfirmModal("Are you sure you want to delete?", function () {
    sendHardwareRequest({
      id,
      deleteHardwareDevice: true,
      property_id: sessionStorage.getItem("propertyId"),
    });
  });
}

// function deleteHardwareSettingsData(id, device_id) {
//   if (!confirm("Are you sure you want to delete")) return;
//   sendHardwareRequest({
//     device_id,
//     id,
//     deleteHardwareSettingsDataRequest: true,
//     property_id:sessionStorage.getItem("propertyId")
//   });
// }
function deleteHardwareSettingsData(id, device_id) {
  showConfirmModal("Are you sure you want to delete?", function () {
    sendHardwareRequest({
      device_id,
      id,
      deleteHardwareSettingsDataRequest: true,
      property_id: sessionStorage.getItem("propertyId"),
    });
  });
}

function editHardware(id) {
  sendHardwareRequest({ id, getHardwareById: true });
}

function addNewHardwareForm() {
  console.log("addNewHardwareForm");
  $("#add_edit_hardware_form_modal").modal("show");
  clearAllValues();
}

// function addNewHardwareForm() {
//   const form_container = document.getElementById("hardware_form");
//   const hardware_view_container = document.getElementById("hardware_view");
//   hardware_view_container.style.display = "none";
//   form_container.style.display = "block";
//   isTestDeviceStatus = false;
//   clearAllValues();
// }

function clearAllValues() {
  document.querySelector("#webrelayModel").value = "";
  document.querySelector("#device_type").value = "";
  document.querySelector("#ip_address").value = "";
  document.querySelector("#hardware_password").value = "";
  document.querySelector("#hardware_user_name").value = "";
  document.querySelector("#device_url").value = "";
  document.querySelector("#http_port").value = "";
  document.querySelector("#system_control_number").value = "";
  document.querySelector("#sms_io_number").value = "";
  document.querySelector("#sms_io_password").value = "";
  
  clearTestStatus();
  
  handleTypeChange(true); // create view for
  onSelectionChange();
}

// Function to clear all test status indicators
function clearTestStatus() {
  // Reset the global test status flag
  isTestDeviceStatus = false;
  
  // Clear web relay test status
  const testStatusIcon = document.getElementById("testStatusIcon");
  if (testStatusIcon) {
    testStatusIcon.style.display = "none";
    testStatusIcon.innerHTML = "";
  }
  
  // Clear SMS test status
  const testStatusIconSMS = document.getElementById("testStatusIconSMS");
  if (testStatusIconSMS) {
    testStatusIconSMS.style.display = "none";
    testStatusIconSMS.innerHTML = "";
  }
  
  // Clear testing messages
  const testingMessage = document.getElementById("testingMessage");
  if (testingMessage) {
    testingMessage.innerHTML = "";
  }
}

function hardwareView() {
  // const form_container = document.getElementById("hardware_form");
  // const hardware_view_container = document.getElementById("hardware_view");
  // hardware_view_container.style.display = "block";
  // form_container.style.display = "none";
  $("#add_edit_hardware_form_modal").modal("hide");
}

function addHardwareToDatabase(event) {
  event?.preventDefault();

  let hardwareId = document.getElementById("hardwareId").value;
  let hardware_is_active = document.getElementById("hardware_is_active").value;
  let sms_io_number = document.getElementById("sms_io_number").value;
  let invisible_intercom_control_number = document.getElementById(
    "system_control_number"
  ).value;
  hardware_is_active = hardware_is_active == "true" ? true : false;
  const device_type = document.getElementById("device_type").value;
  const http_port = document.getElementById("http_port").value;
  const ip_address = document.getElementById("ip_address").value;
  const webrelayModel = document.getElementById("webrelayModel").value;
  const hardware_user_name =
    document.getElementById("hardware_user_name").value;
  const hardware_password = document.getElementById("hardware_password").value;
  const sms_io_password = document.getElementById("sms_io_password").value;
  
  const device_url = document.getElementById("device_url").value;
  const propertyId = sessionStorage.getItem("propertyId");
  if (
    device_type === "SMSIO" &&
    (!sms_io_number || !invisible_intercom_control_number)
  ) {
    showErrorGlobalToastMessage("Please fill all the required fields");
    return;
  } else if (device_type != "SMSIO" && (!http_port || !ip_address)) {
    showErrorGlobalToastMessage("Please fill all the required fields");
    return;
  }

  if (hardware_is_active && !isTestDeviceStatus) {
    showErrorGlobalToastMessage("Please test before saving!");
    return;
  }

  if (webrelayModel == "UC300" && !sms_io_password) {
    showErrorGlobalToastMessage(
      "Password is required"
    );
    return;
  }

  if (!propertyId) {
    showErrorGlobalToastMessage("Please select the property from header");
    return;
  }
  const hardwareData = {
    model: webrelayModel,
    property_id: propertyId,
    device_type: device_type,
    ip_address: ip_address,
    http_port: http_port,
    user_name: hardware_user_name,
    password: webrelayModel=="UC300"? sms_io_password: hardware_password,
    invisible_intercom_control_number,
    sms_io_number,
    hardware_is_active,
    sms_io_duration:0,
    complete_url: device_url,
  };

  if (hardwareId) {
    hardwareData["id"] = hardwareId;
    hardwareData["editHardwareRequest"] = true;
    sendHardwareRequest(hardwareData);
  } else {
    hardwareData["addHardwareRequest"] = true;
    sendHardwareRequest(hardwareData);
  }
}

function showHardwareToastMessage(errorMessage, delayTime = 3000) {
  document.getElementById("hardwareToastMessage").style.display = "block";
  document.getElementById("hardwareErrorMessage").innerHTML = errorMessage;
  var toastEl = document.getElementById("hardwareErrorToast");
  var toast = new bootstrap.Toast(toastEl, {
    delay: delayTime,
    autohide: false,
  });
  toast.show();
  setTimeout(() => {
    closeHardwareToastMessage();
  }, 4000);
}

function closeHardwareToastMessage() {
  const toastEl = document.getElementById("hardwareToastMessage");
  toastEl.style.display = "none";
}

function createHardwareUrl() {
  const deviceType = document.getElementById("device_type").value;
  const ip_address = document.getElementById("ip_address").value;
  const hardware_password = document.getElementById("hardware_password").value;
  const hardware_user_name =
    document.getElementById("hardware_user_name").value;
  const http_port = document.getElementById("http_port").value;
  let url = "";
  url = `http://${hardware_user_name}:${hardware_password}@${ip_address}:${http_port}`;
  document.getElementById("device_url").value = `${url}/state.json`;
  handleActiveChange();
}

function setModelOptions(editData = null) {
  const deviceType = document.getElementById("device_type").value;
  const modelSelect = document.getElementById("webrelayModel");

  clearTestStatus();

  if (deviceType == "SMSIO") handleTypeChange(false);
  else handleTypeChange(true);
  onSelectionChange();
  modelSelect.innerHTML =
    '<option value="" disabled selected>Select Model</option>';
  if (options[deviceType]) {
    options[deviceType].forEach((option) => {
      const opt = document.createElement("option");
      opt.value = option.value;
      opt.textContent = option.label;
      if (editData?.model == option.value) {
        opt.selected = true;
      }
      modelSelect.appendChild(opt);
    });
  }
  handleActiveChange();
}

function handleTypeChange(webRelay = false) {
  let web_relay_elements = document.getElementsByClassName(
    "web_relay_container"
  );
  for (let i = 0; i < web_relay_elements.length; i++) {
    web_relay_elements[i].style.display = webRelay ? "block" : "none";
    web_relay_elements[i].required = true;
  }
  let sms_io_elements = document.getElementsByClassName("sms_io_container");
  for (let j = 0; j < sms_io_elements.length; j++) {
    sms_io_elements[j].style.display = webRelay ? "none" : "block";
    sms_io_elements[j].required = true;
  }
}

async function testSMSIODeviceStatus() {
  if (isLoadingTest) {
    console.log("already being tested");
    return;
  }
  const testStatusIcon = document.getElementById("testStatusIconSMS");
  const webRelayModel = document.getElementById("webrelayModel")?.value;
  const testHardwareButton = document.getElementById("testHardwareButtonSMS");
  const sms_io_password = document.getElementById("sms_io_password").value;
  
  // Clear previous test status when starting new test
  testStatusIcon.style.display = "none";
  testStatusIcon.innerHTML = "";
  isTestDeviceStatus = false;

  let to_number = document.getElementById("sms_io_number").value;
  let from_number = document.getElementById("system_control_number").value;

  if (!to_number) {
    showErrorGlobalToastMessage("Please select SMS IO");
    return;
  }

  if (!from_number) {
    showErrorGlobalToastMessage("Please select Invisible intercom number");
    return;
  }

  let message_body = "";
  if (webRelayModel == "UC300") {
    if(!sms_io_password) {
      showErrorGlobalToastMessage("Password is required for testing");
      return;
    } 
    message_body = `${sms_io_password};status`;
  } else {
    message_body = "get status, Reply-STOP-to-opt-out";
  }

  try {
    isLoadingTest = true;
    document.getElementById("testingMessage").innerHTML=""

    if (!signalWireCredentials)
      throw new Error(`Please add signal wire credentials.`);
    if (!backendUrl)
      throw new Error(`Please add Server VOIP URL`);
    let payload = {
      from_number,
      to_number,
      message_body,
      project_id: signalWireCredentials?.project_id,
      space_url: signalWireCredentials?.space_url,
      api_token: signalWireCredentials?.api_token,
    };

    document.getElementById("smsTestingStatus").innerHTML = "";
    updateStatusMessage("Sending");
    $("#testing_hardware_sms_device").modal({
      backdrop: "static",
      keyboard: false,
    });
    testingRowDetails.isTesting = false;
    const data = encryptData(payload);
    const csrfToken=await getCsrf_token_hardware({get_csrf_token:true})
    let smsTested = await sendSmsThroughNode({data}, `${backendUrl}/send_sms`,csrfToken);
    if (smsTested?.socket) { 
      connectSocket(smsTested.socket);
    }
    let fetchStatus = {
      message_sid: smsTested?.message?.sid,
      project_id: signalWireCredentials?.project_id,
      space_url: signalWireCredentials?.space_url,
      api_token: signalWireCredentials?.api_token,
    };
    const fetchEncryption = encryptData(fetchStatus);
    let status = "queued";
    let smsStatus = undefined;
    let statusCounter = 0;
    while (status == "queued" || status == "initiated" || status == "sent") {
      smsStatus = await sendSmsThroughNode(
        { data: fetchEncryption },
        `${backendUrl}/fetch_sms_status`,
        csrfToken
      );
      status = smsStatus?.message?.status;
      updateStatusMessage(status);
      statusCounter++;
      if (statusCounter > 40) {
        smsStatus.message.status = "Not Delivered";
        break;
      }
    }
    if (smsStatus?.message?.status == "delivered") {
      isLoadingToAddNewEvent = false;
      updateStatusMessage("delivered");
      updateStatusMessage("Waiting for device response", "timer");
    }
    isLoadingTest = false;
    isLoadingSMSUrl(false);
  } catch (error) {
    setTimeout(() => {
      $("#testing_hardware_sms_device").modal("hide");
    }, 500);
    showErrorGlobalToastMessage(error);
    testHardwareButton.style.backgroundColor = "#e33232";
    testHardwareButton.style.border = "none";
    testStatusIcon.style.display = "block";
    testStatusIcon.innerHTML =
      '<i class="fas fa-times" style="color: white; margin-left: 5px;"></i>';
    document.getElementById("testingMessage").innerHTML=error;
    isLoadingTest = false;
    isLoadingSMSUrl(false);
    isTestDeviceStatus = false;
  }
}

async function sendSmsThroughNode(data, url,token) {
  return new Promise((resolve, reject) => {
    $.ajax({
      url,
      type: "POST",
      data,
      timeout: 10000, // 10 seconds delay
      headers: {
        authorization: `${token}`
      },
      success: function (resp) {
        try {
          if (resp?.message) {
            resolve(resp);
          }
        } catch (error) {
          reject(error);
        }
      },
      error: function (xhr, status, error) {
        if (xhr?.responseJSON?.error || xhr?.responseJSON?.error_message)
          reject(xhr?.responseJSON?.error || xhr?.responseJSON?.error_message);
        else reject(error);
      },
    });
  });
}

function enforcePlusAndNumbers(input) {
  if (!input.value.startsWith("+")) {
    input.value = "+" + input.value.replace(/\D/g, ""); // Add "+" if missing
  } else {
    input.value = "+" + input.value.slice(1).replace(/\D/g, "");
  }
}

async function testDeviceStatus() {
  if (isLoadingTest) return;
  const testStatusIcon = document.getElementById("testStatusIcon");
  const testHardwareButton = document.getElementById("testHardwareButton");
  
  // Clear previous test status when starting new test
  testStatusIcon.style.display = "none";
  testStatusIcon.innerHTML = "";
  isTestDeviceStatus = false;
  
  try {
    isLoadingTest = true;
    document.getElementById("testingMessage").innerHTML=""
    isLoadingTestUrl(true);
    let deviceUrl = document.getElementById("device_url").value;
    let userName = document.getElementById("hardware_user_name").value;
    let password = document.getElementById("hardware_password").value;
    if (deviceUrl) {
      let obj = await fetchDataForItem(deviceUrl, userName, password);
      if (obj) isTestDeviceStatus = true;
      // $(`#testingMessage`).html("URl is Good");
      // testHardwareButton.style.backgroundColor="green"
      testHardwareButton.style.backgroundColor = "#229b3c";
      testStatusIcon.style.display = "block";
      testStatusIcon.innerHTML =
        '<i class="fas fa-check" style="color: white; margin-left: 5px;"></i>';
    }
    isLoadingTest = false;
    isLoadingTestUrl(false);
  } catch (error) {
    testHardwareButton.style.backgroundColor = "#e33232";
    testHardwareButton.style.border = "none";
    testStatusIcon.style.display = "block";
    testStatusIcon.innerHTML =
      '<i class="fas fa-times" style="color: white; margin-left: 5px;"></i>';

    document.getElementById("testingMessage").innerHTML = error;

    isLoadingTest = false;
    isLoadingTestUrl(false);
    isTestDeviceStatus = false;
  }
}

function isLoadingTestUrl(isLoading) {
  let elem = document.getElementById("loadingTestIndicator");
  if (elem) {
    if (isLoading) elem.style.display = "block";
    else elem.style.display = "none";
  }
}

function isLoadingSMSUrl(isLoading) {
  let elem = document.getElementById("loadingTestIndicatorSMS");
  if (elem) {
    if (isLoading) elem.style.display = "block";
    else elem.style.display = "none";
  }
}

function isLoadingAddNewRow(isLoading) {
  let elem = document.getElementById("loadingAddNewRowIndicator");
  if (elem) {
    if (isLoading) elem.style.display = "block";
    else elem.style.display = "none";
  }
}

function isLoadingHardwareCenter(isLoading) {
  let ele = document.getElementById("hardware_center_loading_indicator");
  if (isLoading) {
    ele.style.display = "flex";
  } else {
    ele.style.display = "none";
  }
}

async function editHardwareSettingsInModal(id, itemId) {
  try {
    $("#add_hardware_settings_modal").modal("show");
    let hardwareSettingsData = allHardwareSettingsTableData[itemId].find(
      (ele) => ele.id == id
    );

    const hardwareDevice = allHardwareDevices?.find((ele) => ele?.id == itemId);
    const is_sms_io_device = hardwareDevice?.device_type == "SMSIO";
    const deviceModel = hardwareDevice?.model;

    const availableDoors=getAllAvailableDoors(hardwareSettingsData.assigned_door);
    await setOptionsOfDoorSelectBox(availableDoors);
    document.getElementById("assign_door").value =
      hardwareSettingsData?.assigned_door;
    let objectData = "";
    if (!is_sms_io_device) {
      objectData = await fetchDataForItem(hardwareSettingsData?.completeUrl,hardwareDevice?.userName,hardwareDevice?.password);
    }
    document.getElementById("hardware_settings_edit_id").value =
      hardwareSettingsData.id;
    document.getElementById("hardware_device_id").value = itemId;
    const relayOutputBox = document.getElementById("web_relay_output");
    const web_relay_input = document.getElementById("web_relay_input");
    const hardware_settings_timer = document.getElementById(
      "hardware_settings_timer"
    );
    relayOutputBox.innerHTML =
      '<option value="" disabled >Select output</option>';
    web_relay_input.innerHTML = "";
    hardware_settings_timer.innerHTML =
      '<option value="" selected>Select Schedule</option>';
    allSchedules?.forEach((item) => {
      const timerOption = document.createElement("option");
      timerOption.value = item.id;
      timerOption.textContent = item?.title;
      if (item?.id == hardwareSettingsData.timer) {
        timerOption.selected = true;
      }
      hardware_settings_timer.appendChild(timerOption);
    });

    if (!is_sms_io_device) {
      objectData?.outputs?.forEach((item) => {
        const option = document.createElement("option");
        option.value = item?.key;
        option.textContent = item?.key;
        if (item?.key == hardwareSettingsData?.output) {
          option.selected = true;
        }
        relayOutputBox.appendChild(option);
      });

      const web_relay_input = document.getElementById("web_relay_input");
      web_relay_input.innerHTML = "";
      objectData?.inputs?.forEach((item) => {
        const inputOption = document.createElement("option");
        inputOption.value = item?.key;
        inputOption.textContent = item?.key;
        if (hardwareSettingsData.inputs.includes(item?.key)) {
          inputOption.selected = true;
        }
        web_relay_input.appendChild(inputOption);
      });

      $(`#web_relay_input`).select2({
        theme: "bootstrap4",
        placeholder: "Select input",
        allowClear: true,
      });
      // Add Check status button for web relay in modal
      let checkStatusBtn = document.getElementById('webrelay_check_status_btn');
      if (!checkStatusBtn) {
        checkStatusBtn = document.createElement('button');
        checkStatusBtn.id = 'webrelay_check_status_btn';
        checkStatusBtn.type = 'button';
        checkStatusBtn.className = 'btn btn-primary my-2';
        checkStatusBtn.innerText = 'Check status modal';
        checkStatusBtn.onclick = function() {
          testWebRelayStatusModal(this, itemId);
        };
        outputSelectBox.parentNode.appendChild(checkStatusBtn);
        // Add status span after the button
        checkStatusBtn.insertAdjacentHTML('afterend', `<span id="relayStatus${itemId}" class="ml-2"></span>`);
      }
    } else{
      let outputOptions=[]
      let inputOptions=[];
      const sms_duration_container=document.getElementById("sms_duration_container")
      const sms_io_duration_input=document.getElementById("sms_io_duration_input");
      if (deviceModel == "UC300") {
        if(sms_duration_container)sms_duration_container.style.display="block";
        sms_io_duration_input.value=hardwareSettingsData?.sms_duration;
        outputOptions=UC300Options;
        inputOptions=UC300InputOptions;
      } else {
        if(sms_duration_container)sms_duration_container.style.display="none";
        outputOptions=UC1414Options;
        sms_io_duration_input.value=0;
        inputOptions=UC1414InputOptions;
      }
      console.log("inputOptions",inputOptions);
      inputOptions?.forEach((item) => {
        const inputOption = document.createElement("option");
        inputOption.value = item?.key;
        inputOption.textContent = item?.key;
        if (hardwareSettingsData.inputs.includes(item?.key)) {
          inputOption.selected = true;
        }
        web_relay_input.appendChild(inputOption);
      });
  
      $(`#web_relay_input`).select2({
        theme: "bootstrap4",
        placeholder: "Select input",
        allowClear: true,
      });

      let outputsToExclude = allHardwareSettingsTableData[itemId]
      ?.filter(item => item.id !== id)
      ?.map(item => item.output) || [];
    
    // Get the appropriate options based on device model
    
    // Filter out already selected outputs
    const availableOutputs = outputOptions.filter(
      (output) => !outputsToExclude.includes(output.value)
    );

    availableOutputs?.forEach((item) => {
        const option = document.createElement("option");
        option.value = item?.value;
        option.textContent = item?.key;
        if (item?.value == hardwareSettingsData?.output) {
          option.selected = true;
        }
        relayOutputBox.appendChild(option);
      });
    } 
    let not_show_on_sms = document.getElementsByClassName("not_show_on_sms");
    console.log("not_show_on_sms",not_show_on_sms);
    
    for (let i = 0; i < not_show_on_sms.length; i++) {
      not_show_on_sms[i].style.display = !is_sms_io_device ? "block" : "none";
    }
  } catch (error) {
    console.log("got error in catch section", error);
  }
}

async function add_hardware_settings_data(event) {
  event.preventDefault();
  const hardware_device_id = document.getElementById("hardware_device_id").value;
  const hardware_settings_edit_id = document.getElementById("hardware_settings_edit_id").value;
  const web_relay_output = document.getElementById("web_relay_output").value;
  const assign_door = document.getElementById("assign_door").value;
  const hardware_settings_timer = document.getElementById("hardware_settings_timer").value;
  const inputValue = $("#web_relay_input").val() || " ";
  if (inputValue?.length > 3) {
    showErrorGlobalToastMessage("You cannot select inputs more than 3");
    return;
  }

  if (!assign_door || !inputValue || !web_relay_output) {
    showErrorGlobalToastMessage(
      "Please add all required values and check status to continue"
    );
    return;
  }

  const isAlreadyAssigned = allHardwareSettingsTableData[
    hardware_device_id
  ]?.find((ele) => ele.output == web_relay_output);

  const isAlreadyAssignedDoor = allHardwareSettingsTableData[
    hardware_device_id
  ]?.find((ele) => ele.assigned_door == assign_door);

  if (isAlreadyAssignedDoor && !hardware_settings_edit_id) {
    showErrorGlobalToastMessage(
      "You have already assigned the door. Please select another one"
    );
    return;
  }

  if (isAlreadyAssigned && !hardware_settings_edit_id) {
    showErrorGlobalToastMessage(
      "You have already assigned the Input/Output. Please select another one"
    );
    return;
  }
  const device = allHardwareDevices?.find(
    (ele) => ele.id == hardware_device_id
  );
  const sms_io_duration_input = document.getElementById("sms_io_duration_input")?.value;
  const property_id = sessionStorage.getItem("propertyId");
  if (!property_id) {
    showErrorGlobalToastMessage("Please select property id from the header");
    return;
  }
  // Get the relay status from the span
  const status = document.getElementById(`relayStatus${hardware_device_id}`)?.innerText || "";
  let payload = {
    device_id: hardware_device_id,
    assigned_door: assign_door,
    inputs: JSON.stringify(inputValue) || " ",
    output: web_relay_output,
    ipAddress: device?.ip_address,
    ipPort: device?.http_port,
    completeUrl: device?.complete_url,
    status,
    sms_duration: sms_io_duration_input || 0,
    property_id,
  };
  if (hardware_settings_timer) {
    payload["timer"] = hardware_settings_timer;
  } else {
    payload["timer"] = "null";
  }

  if (hardware_settings_edit_id) {
    payload["EditHardwareSettingsRequest"] = true;
    payload["id"] = hardware_settings_edit_id;
  } else {
    payload["addHardwareSettingsRequest"] = true;
  }
  sendHardwareRequest(payload);
}

async function setOptionsOfDoorSelectBox(doors) {
  console.log("setOptionsOfDoorSelectBox", doors);

  const selectBox = document.getElementById("assign_door");
  selectBox.innerHTML =
    '<option value="" disabled selected>Select door</option>';
  doors.forEach((door) => {
    const option = document.createElement("option");
    option.value = door.id;
    option.textContent = door.door_name;
    selectBox.appendChild(option);
  });
}

async function addNewHardwareSettingInModal(itemId) {
  const device = allHardwareDevices.find((ele) => ele.id == itemId);
  const is_sms_io_device = device?.device_type == "SMSIO";
  document.getElementById("assign_door").value = "";
  document.getElementById("hardware_settings_edit_id").value = null;
  document.getElementById("hardware_device_id").value = itemId;
  const outputSelectBox = document.getElementById("web_relay_output");
  const sms_duration_container=document.getElementById("sms_duration_container")

  $("#add_hardware_settings_modal").modal("show");
  outputSelectBox.innerHTML =
    '<option value="" disabled selected>Select output</option>';
    
  const availableDoors = getAllAvailableDoors();
  await setOptionsOfDoorSelectBox(availableDoors);
  const hardware_settings_timer = document.getElementById(
    "hardware_settings_timer"
  );

  hardware_settings_timer.innerHTML =
    '<option value="" selected>Select timer</option>';
  allSchedules?.forEach((item) => {
    const timerOption = document.createElement("option");
    timerOption.value = item.id;
    timerOption.textContent = item?.title;
    hardware_settings_timer.appendChild(timerOption);
  });

  if (!is_sms_io_device) {
    if(sms_duration_container)sms_duration_container.style.display="none";
    const inputOutputDat = await getAvailableOutputs(itemId);
    const availableOutputs = inputOutputDat?.outputs || [];
    const availableInputs = inputOutputDat?.inputs || [];

    availableOutputs?.forEach((item) => {
      const option = document.createElement("option");
      option.value = item?.key;
      option.textContent = item?.key;
      outputSelectBox.appendChild(option);
    });

    const web_relay_input = document.getElementById("web_relay_input");
    web_relay_input.innerHTML = "";
    availableInputs?.forEach((item) => {
      const inputOption = document.createElement("option");
      inputOption.value = item?.key;
      inputOption.textContent = item?.key;
      web_relay_input.appendChild(inputOption);
    });
    $(`#web_relay_input`).select2({
      theme: "bootstrap4",
      placeholder: "Select input",
      allowClear: true,
    });
    // Add Get status button for SMSIO in modal
    let getStatusBtn = document.getElementById('smsio_get_status_btn');
    if (!getStatusBtn) {
      getStatusBtn = document.createElement('button');
      getStatusBtn.id = 'smsio_get_status_btn';
      getStatusBtn.type = 'button';
      getStatusBtn.className = 'btn btn-primary my-2';
      getStatusBtn.innerText = 'Get status';
      getStatusBtn.onclick = function() {
        if (isLoadingTest) return;
        const originalText = this.textContent || this.innerText;
        this.disabled = true;
        this.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Loading';
        
        isLoadingTest = true;
        testWebRelayStatusModal(this, itemId, originalText);
      };
      outputSelectBox.parentNode.appendChild(getStatusBtn);
      getStatusBtn.insertAdjacentHTML('afterend', `<span id="relayStatus${itemId}" class="ml-2"></span>`);
    }
  } else {
    let outputOptions=[];
    let inputOptions=[];
    if(device?.model=="UC300"){
      sms_duration_container.style.display="block";
      outputOptions= UC300Options;
      inputOptions= UC300InputOptions;
    }else{
      sms_duration_container.style.display="none";
      outputOptions= UC1414Options;
      inputOptions= UC1414InputOptions;
    } 

    let outputsToExclude = allHardwareSettingsTableData[itemId]?.map(item => item.output) || [];
    const availableOutputs = outputOptions.filter(
      (output) => !outputsToExclude.includes(output.value)
    );
    availableOutputs?.forEach((item) => {
      const option = document.createElement("option");
      option.value = item?.value;
      option.textContent = item?.key;
      outputSelectBox.appendChild(option);
    });

    const web_relay_input = document.getElementById("web_relay_input");
    web_relay_input.innerHTML = "";
    inputOptions?.forEach((item) => {
      const inputOption = document.createElement("option");
      inputOption.value = item?.key;
      inputOption.textContent = item?.key;
      web_relay_input.appendChild(inputOption);
    });


    $(`#web_relay_input`).select2({
      theme: "bootstrap4",
      placeholder: "Select input",
      allowClear: true,
    });

    let getStatusBtn = document.getElementById('smsio_get_status_btn');
    if (!getStatusBtn) {
      getStatusBtn = document.createElement('button');
      getStatusBtn.id = 'smsio_get_status_btn';
      getStatusBtn.type = 'button';
      getStatusBtn.className = 'btn btn-primary my-2';
      getStatusBtn.innerText = 'Get status';
      getStatusBtn.onclick = function() {
        testHardwareSMSIo(this, itemId);
      };
      outputSelectBox.parentNode.appendChild(getStatusBtn);
      getStatusBtn.insertAdjacentHTML('afterend', `<span id="relayStatus${itemId}" class="ml-2"></span>`);
    }
  }

  const not_show_on_sms = document.getElementsByClassName("not_show_on_sms");
  for (let i = 0; i < not_show_on_sms.length; i++) {
    const visibility = !is_sms_io_device ? "block" : "none";
    not_show_on_sms[i].style.display = visibility;
  }
  try {
    
  } catch (error) {
    console.log("got error in catch section", error);
  }
}

async function onSelectionChange() {
  const duration = document.getElementById("sms_io_container_password");
  const webRelayModel = document.getElementById("webrelayModel")?.value;
  
  // Clear test status when model changes
  clearTestStatus();
  
  if (webRelayModel == "UC300") {
    duration.style.display = "block";
  } else {
    duration.style.display = "none";
  }
  handleActiveChange();
}

function handleActiveChange() {
  let SMSTestButton = document.getElementById("SMSTestButton");
  let webRelayTesting = document.getElementById("webRelayTesting");
  let hardware_is_active = document.getElementById("hardware_is_active").value;
  let device_type = document.getElementById("device_type").value;

  if (hardware_is_active == "false") {
    SMSTestButton.style.display = "none";
    webRelayTesting.style.display = "none";
  } else {
    if (device_type == "SMSIO") {
      SMSTestButton.style.display = "block";
    } else {
      webRelayTesting.style.display = "block";
    }
  }
}

function openDownloadModal(id) {
  document.querySelector("#hardware_download_id").value = id || "";
  const hardware_device = allHardwareDevices?.find((ele) => ele.id == id);
  const readme_file_button = document?.getElementById("readme_file_button");
  if (hardware_device?.model == "UC300" && readme_file_button) {
    readme_file_button.style.display = "none";
  } else if (readme_file_button) {
    readme_file_button.style.display = "block";
    $("#readme_file_button").html(DOMPurify.sanitize("Readme UC1414"));
  }
  $("#download_hardware_config_modal").modal("show");
}

function download_hardware_config_data() {
  const hardware_download_id = document.getElementById(
    "hardware_download_id"
  ).value;
  const hardware_device = allHardwareDevices?.find(
    (ele) => ele.id == hardware_download_id
  );
  let filePath = "";
  if (hardware_device?.model == "UC300") {
    filePath = "/js/property_builder/readme_uc300.txt";
  } else filePath = "/js/property_builder/Config_file.txt";

  const newFileName =
    document.getElementById("download_file_name").value || "Configurations";
  const a = document.createElement("a");
  a.href = filePath;
  a.download = newFileName;
  document.body.appendChild(a);
  a.click();
  document.body.removeChild(a);
}

function download_hardware_Readme_file() {
  let filePath = "/js/property_builder/readme_uc1414.txt";
  const newFileName =
    document.getElementById("download_file_name").value || "readme";
  const a = document.createElement("a");
  a.href = filePath;
  a.download = newFileName;
  document.body.appendChild(a);
  a.click();
  document.body.removeChild(a);
}

let hardwareDebounceTimer;

function searchHardwareDevices(){
  if(!isHardwareCardView){
    searchTable('hardware_data_table', 'search_hardware_value');
    return;
  }
  clearTimeout(hardwareDebounceTimer);
  hardwareDebounceTimer = setTimeout(() => {
    const searchInput = document.getElementById("search_hardware_value");
    if (!searchInput) {
      console.warn("Search input not found: search_hardware_value");
      return;
    }
    
    const searchValue = searchInput.value.toLowerCase();
    let matchedHardware = allHardwareDevices.filter(
      (event) =>
        !searchValue ||
        Object.values(event).some(
          (field) =>
            field && field.toString().toLowerCase().includes(searchValue)
        )
    );
    
    // Re-render based on current view
    if (window.innerWidth <= 600 || isHardwareCardView) {
      createHardwareCardsPreview(matchedHardware, searchValue);
    } else {
      createHardwareTablePreview(matchedHardware);
    }
  }, 300);
}

async function testWebRelayStatusModal(button, itemId, originalText) {
  try {
    const outputValue = document.getElementById("web_relay_output")?.value;
    document.getElementById(`relayStatus${itemId}`).innerHTML = "";
    if (!outputValue) {
      button.disabled = false;
      button.innerHTML = originalText;
      isLoadingTest = false;
      showErrorGlobalToastMessage("Please select Output");
      return;
    }
    let selectedDevice = allHardwareDevices?.find((ele) => ele.id == itemId);
    let objectData = await fetchDataForItem(selectedDevice?.complete_url, selectedDevice?.user_name, selectedDevice?.password);
    let selected = objectData?.outputs?.find((ele) => ele.key == outputValue);

    const relayStatus = selected?.value == "0" ? "Off" : "On";
    const statusClass = relayStatus === "On" ? "status-on" : "status-off";

    const relayElement = $(`#relayStatus${itemId}`);
    relayElement
      .removeClass("status-on status-off")
      .addClass(statusClass)
      .html(DOMPurify.sanitize(relayStatus));
      
    // Reset button state on success
    button.disabled = false;
    button.innerHTML = originalText;
    isLoadingTest = false;
  } catch (error) {
    // Reset button state on error
    button.disabled = false;
    button.innerHTML = originalText;
    isLoadingTest = false;
    showErrorGlobalToastMessage("Error checking status: " + (error?.message || error));
    console.log("Error checking status:", error);
  }
}