<?php
// index.php
require_once 'config.php'; // This file should call session_start()
// Define the earliest month available (adjust this value as needed)
$minMonth = isset($minMonth) ? $minMonth : "2023-01";

// Retrieve messages/errors from session (set by refresh endpoints)
$message = $_SESSION['message'] ?? null;
$error = $_SESSION['error'] ?? null;
unset($_SESSION['message'], $_SESSION['error']);
?>
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>QuickBooks Data Manager - Dashboard</title>
  <style>
    /* Basic Styles */
    body {
      font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
      margin: 20px;
      line-height: 1.6;
      background-color: #f8f9fa;
      color: #212529;
    }
    h1, h2 { color: #343a40; }
    .container {
      max-width: 95%;
      margin: 0 auto;
      background-color: #fff;
      padding: 20px;
      border-radius: 8px;
      box-shadow: 0 2px 4px rgba(0,0,0,0.1);
    }
    .message {
      padding: 12px 15px;
      margin-bottom: 15px;
      border-radius: 4px;
      border: 1px solid transparent;
      white-space: pre-wrap;
    }
    .success { background-color: #d1e7dd; border-color: #badbcc; color: #0f5132; }
    .error { background-color: #f8d7da; border-color: #f5c2c7; color: #842029; }
    .warning { background-color: #fff3cd; border: 1px solid #ffeeba; color: #856404; }
    .button {
      display: inline-block;
      padding: 10px 15px;
      background-color: #0d6efd;
      color: white;
      text-decoration: none;
      border-radius: 4px;
      margin: 5px;
      border: none;
      cursor: pointer;
      transition: background-color 0.15s ease-in-out;
      font-size: 0.95em;
    }
    .button:hover { background-color: #0b5ed7; }
    .button-refresh { background-color: #198754; }
    .button-refresh:hover { background-color: #157347; }
    .button-download { background-color: #ffc107; color: #000; }
    .button-download:hover { background-color: #e0a800; }
    #display-area {
      margin-top: 20px;
      border: 1px solid #dee2e6;
      padding: 15px;
      background-color: #fff;
      min-height: 100px;
      word-wrap: break-word;
      overflow-x: auto;
      border-radius: 4px;
    }
    table {
      border-collapse: collapse;
      width: 100%;
      margin-top: 10px;
    }
    th, td {
      border: 1px solid #dee2e6;
      padding: 6px 8px;
      text-align: left;
      font-size: 0.85em;
      vertical-align: top;
      word-break: break-word;
    }
    th { background-color: #e9ecef; font-weight: 600; white-space: nowrap; }
    tr:nth-child(even) { background-color: #f8f9fa; }
    pre {
      background-color: #e9ecef;
      padding: 10px;
      border-radius: 4px;
      font-size: 0.85em;
      white-space: pre-wrap;
    }
    hr { border: none; border-top: 1px solid #dee2e6; margin: 20px 0; }
    .action-section { margin-bottom: 20px; }
    .filter-container {
      border: 1px solid #dee2e6;
      padding: 10px 15px;
      border-radius: 4px;
      background-color: #f1f1f1;
      margin-bottom: 20px;
      display: flex;
      align-items: center;
      gap: 10px;
    }
    /* P&L report tree styling */
    .pnl-report { margin-top: 15px; }
    .account-section {
      margin-left: 20px;
      border-left: 1px solid #ccc;
      padding-left: 10px;
      margin-bottom: 10px;
    }
    .account-header { cursor: pointer; font-weight: bold; }
    .account-content { margin-left: 15px; }
  </style>
</head>
<body>
  <div class="container">
    <h1>QuickBooks Data Manager - Dashboard</h1>
    <!-- Session Messages -->
    <?php if ($message): ?>
      <div class="message success"><?php echo nl2br(htmlspecialchars($message)); ?></div>
    <?php endif; ?>
    <?php if ($error): ?>
      <div class="message error"><?php echo nl2br(htmlspecialchars($error)); ?></div>
    <?php endif; ?>

    <!-- Filter Section -->
    <div class="filter-container">
      <label for="month-filter"><strong>Select Month:</strong></label>
      <input type="month" id="month-filter" value="<?php echo date('Y-m', strtotime('last month')); ?>" min="<?php echo $minMonth; ?>" max="<?php echo date('Y-m'); ?>">
      <button class="button" id="apply-month-filter">Apply Filter</button>
    </div>

    <!-- Action Buttons -->
    <div class="action-section">
      <div>
        <a href="download_data.php" class="button button-refresh">Refresh Base Data (Accounts & Prev Month)</a>
        <a href="download_transactions_curl.php" class="button button-download">Download/Update Transactions (2023-Now cURL)</a>
      </div>
      <hr>
      <div>
        <p><strong>Display Saved Data:</strong></p>
        <button class="button display-btn" data-type="accounts" data-period="all_time">Display Accounts</button>
        <button class="button display-btn" data-type="expenses" data-period="prev_month">Display Expenses (Prev. Month)</button>
        <button class="button display-btn" data-type="pnl_report" data-period="custom">Display P&amp;L Report</button>
        <button class="button display-btn" data-type="transactions_curl" data-period="custom">Display Transactions (Table)</button>
        <button class="button display-btn" data-type="transactions_curl_raw" data-period="custom">Display Transactions (Raw)</button>
        <button class="button display-btn" data-type="raw_table" data-period="custom">Display Raw Data (Table)</button>
        <!-- New button for Detailed QBO Table -->
        <button class="button display-btn" data-type="detailed_qbo" data-period="custom">Display QBO Detailed Table</button>
      </div>
    </div>
    <hr>
    <!-- Data Display Area -->
    <div id="display-area">
      Click a 'Display' button above to show the corresponding saved data file content.
    </div>
  </div>

  <script>
    // Global variable to hold the custom month selection (format YYYY-MM)
    let customMonth = null;
    const displayArea = document.getElementById('display-area');
    const displayButtons = document.querySelectorAll('.display-btn');

    // When "Apply Filter" is clicked, store the selected month.
    document.getElementById('apply-month-filter').addEventListener('click', () => {
      customMonth = document.getElementById('month-filter').value;
      displayArea.innerHTML = `<div class="message success">Filter applied: ${customMonth}</div>`;
    });

    // Helper function to safely retrieve nested properties.
    function getProp(obj, path, defaultValue = '') {
      try {
        const value = path.split('.').reduce((o, p) => o && typeof o === 'object' ? o[p] : undefined, obj);
        return value !== undefined && value !== null ? value : defaultValue;
      } catch (e) {
        console.error("getProp Error:", e, "on", obj, "with path", path);
        return defaultValue;
      }
    }

    // Function to render raw JSON data as a table with flexible columns.
    function displayRawTable(data, container) {
      container.innerHTML = '';
      if (!Array.isArray(data) || data.length === 0) {
        container.textContent = "No data available to display.";
        return;
      }
      const headersSet = new Set();
      data.forEach(item => {
        if (typeof item === "object" && item !== null) {
          Object.keys(item).forEach(key => headersSet.add(key));
        }
      });
      const headers = Array.from(headersSet).sort();
      
      const table = document.createElement("table");
      table.style.width = "100%";
      table.style.tableLayout = "auto";
      table.style.borderCollapse = "collapse";
      
      const thead = document.createElement("thead");
      const headerRow = document.createElement("tr");
      headers.forEach(header => {
        const th = document.createElement("th");
        th.style.border = "1px solid #dee2e6";
        th.style.padding = "6px 8px";
        th.style.whiteSpace = "normal";
        th.textContent = header;
        headerRow.appendChild(th);
      });
      thead.appendChild(headerRow);
      table.appendChild(thead);
      
      const tbody = document.createElement("tbody");
      data.forEach(item => {
        const row = document.createElement("tr");
        headers.forEach(header => {
          const td = document.createElement("td");
          td.style.border = "1px solid #dee2e6";
          td.style.padding = "6px 8px";
          td.style.whiteSpace = "normal";
          let value = item[header];
          if (typeof value === "object" && value !== null) {
            try {
              value = JSON.stringify(value);
            } catch (e) {
              value = "[Object]";
            }
          }
          td.textContent = value;
          row.appendChild(td);
        });
        tbody.appendChild(row);
      });
      table.appendChild(tbody);
      container.appendChild(table);
    }

    // Function to render transaction data in a table (existing code).
    function displayTransactionTable(data, container) {
      container.innerHTML = '';
      if (!Array.isArray(data) || data.length === 0) {
        container.textContent = 'No transaction data found or data is not an array.';
        return;
      }
      const table = document.createElement('table');
      table.classList.add('txn-table');
      const thead = table.createTHead();
      const tbody = table.createTBody();
      const headerRow = thead.insertRow();
      const headers = ['Type', 'Date', 'Account Name', 'Account ID', 'Uncategorized?', 'Name', 'Memo/Desc', 'Total', 'Line Detail Summary'];
      headers.forEach(headerText => {
        const th = document.createElement('th');
        th.textContent = headerText;
        headerRow.appendChild(th);
      });
      const uncategorizedKeywords = ["uncategorized", "ask my accountant", "suspense"];
      data.forEach(txn => {
        if (!txn || typeof txn !== 'object') return;
        const row = tbody.insertRow();
        let primaryAccountName = 'N/A';
        let primaryAccountId = '';
        let isUncategorized = false;
        let firstDetailLineProcessed = false;
        if (txn.Line && Array.isArray(txn.Line)) {
          for (const line of txn.Line) {
            if (!line || typeof line !== 'object') continue;
            const detailType = getProp(line, 'DetailType');
            let currentAccountName = '';
            let currentAccountId = '';
            if (detailType === 'AccountBasedExpenseLineDetail') {
              currentAccountName = getProp(line, 'AccountBasedExpenseLineDetail.AccountRef.name');
              currentAccountId = getProp(line, 'AccountBasedExpenseLineDetail.AccountRef.value');
            } else if (detailType === 'ItemBasedExpenseLineDetail') {
              currentAccountName = getProp(line, 'ItemBasedExpenseLineDetail.AccountRef.name');
              currentAccountId = getProp(line, 'ItemBasedExpenseLineDetail.AccountRef.value');
            } else if (detailType === 'JournalEntryLineDetail') {
              currentAccountName = getProp(line, 'JournalEntryLineDetail.AccountRef.name');
              currentAccountId = getProp(line, 'JournalEntryLineDetail.AccountRef.value');
            } else if (detailType === 'DiscountLineDetail') {
              currentAccountName = getProp(line, 'DiscountLineDetail.DiscountAccountRef.name', 'Discount');
              currentAccountId = getProp(line, 'DiscountLineDetail.DiscountAccountRef.value');
            }
            if (!firstDetailLineProcessed && currentAccountName && currentAccountName !== 'N/A') {
              primaryAccountName = currentAccountName;
              primaryAccountId = currentAccountId;
              firstDetailLineProcessed = true;
            }
            if (currentAccountName) {
              const lowerAccountName = currentAccountName.toLowerCase();
              if (uncategorizedKeywords.some(keyword => lowerAccountName.includes(keyword))) {
                isUncategorized = true;
              }
            }
          }
        }
        row.insertCell().textContent = getProp(txn, '_EntityType', 'N/A');
        let dateStr = getProp(txn, 'TxnDate', '');
        try {
          const d = new Date(dateStr);
          if (!isNaN(d.getTime())) { dateStr = d.toLocaleDateString(); } else { dateStr = getProp(txn, 'TxnDate', ''); }
        } catch(e) { dateStr = getProp(txn, 'TxnDate', ''); }
        row.insertCell().textContent = dateStr;
        row.insertCell().textContent = primaryAccountName;
        row.insertCell().textContent = primaryAccountId || 'N/A';
        const uncategorizedCell = row.insertCell();
        uncategorizedCell.textContent = isUncategorized ? 'Yes' : 'No';
        if (isUncategorized) { uncategorizedCell.classList.add('uncategorized-yes'); }
        let name = getProp(txn, 'CustomerRef.name') || getProp(txn, 'VendorRef.name');
        row.insertCell().textContent = name || 'N/A';
        let memo = getProp(txn, 'Memo', getProp(txn, 'PrivateNote', ''));
        if (memo.length > 50) memo = memo.substring(0, 50) + '...';
        row.insertCell().textContent = memo;
        let totalAmt = getProp(txn, 'TotalAmt', 0);
        try {
          totalAmt = parseFloat(totalAmt).toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 });
        } catch(e) { totalAmt = 'N/A'; }
        row.insertCell().textContent = totalAmt;
        const lineCell = row.insertCell();
        const lineSummaryList = document.createElement('ul');
        lineSummaryList.classList.add('line-summary');
        lineCell.appendChild(lineSummaryList);
        if (txn.Line && Array.isArray(txn.Line)) {
          txn.Line.forEach(line => {
            if (!line || typeof line !== 'object') return;
            const li = document.createElement('li');
            let detailText = '';
            let lineAmt = getProp(line, 'Amount', 0);
            const detailType = getProp(line, 'DetailType');
            let accountName = 'N/A';
            let accountId = '';
            let description = getProp(line, 'Description', '');
            if (description.length > 40) description = description.substring(0, 40) + '...';
            let entityText = '';
            switch(detailType) {
              case 'SalesItemLineDetail':
                accountName = `Item: ${getProp(line, 'SalesItemLineDetail.ItemRef.name', 'N/A')}`;
                accountId = getProp(line, 'SalesItemLineDetail.ItemAccountRef.value', '');
                break;
              case 'AccountBasedExpenseLineDetail':
                accountName = getProp(line, 'AccountBasedExpenseLineDetail.AccountRef.name', 'N/A');
                accountId = getProp(line, 'AccountBasedExpenseLineDetail.AccountRef.value');
                break;
              case 'ItemBasedExpenseLineDetail':
                const itemName = getProp(line, 'ItemBasedExpenseLineDetail.ItemRef.name');
                accountName = getProp(line, 'ItemBasedExpenseLineDetail.AccountRef.name', 'N/A');
                accountId = getProp(line, 'ItemBasedExpenseLineDetail.AccountRef.value');
                if (itemName) accountName = `Item: ${itemName} (${accountName})`;
                break;
              case 'JournalEntryLineDetail':
                accountName = getProp(line, 'JournalEntryLineDetail.AccountRef.name', 'N/A');
                accountId = getProp(line, 'JournalEntryLineDetail.AccountRef.value');
                const postingType = getProp(line, 'JournalEntryLineDetail.PostingType', '');
                detailText += `(${postingType}) `;
                const entityRef = getProp(line, 'JournalEntryLineDetail.Entity.EntityRef');
                if (entityRef && typeof entityRef === 'object') {
                  entityText = ` [Entity: ${getProp(entityRef, 'name', 'N/A')} (${getProp(entityRef, 'value', 'N/A')})]`;
                }
                break;
              case 'DiscountLineDetail':
                accountName = getProp(line, 'DiscountLineDetail.DiscountAccountRef.name', 'Discount');
                accountId = getProp(line, 'DiscountLineDetail.DiscountAccountRef.value');
                break;
              case 'PaymentLineDetail':
                accountName = "Payment Application";
                let linkedPmt = getProp(line, 'PaymentLineDetail.LinkedTxn.0');
                if(linkedPmt) { description += ` (Links to ${getProp(linkedPmt, 'TxnType')} ${getProp(linkedPmt, 'TxnId')})`; }
                break;
              default:
                accountName = detailType || 'Misc Line';
            }
            try {
              lineAmt = parseFloat(lineAmt).toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 });
            } catch(e) { lineAmt = 'N/A'; }
            detailText += `${accountName}`;
            if (accountId) detailText += ` (${accountId})`;
            detailText += `: ${lineAmt}`;
            if (description) { detailText += ` - "${description}"`; }
            detailText += entityText;
            li.textContent = detailText;
            lineSummaryList.appendChild(li);
          });
        } else if (txn._EntityType === 'Payment' && txn.LinkedTxn && Array.isArray(txn.LinkedTxn)) {
          txn.LinkedTxn.forEach(linked => {
            const li = document.createElement('li');
            li.textContent = `Links to ${getProp(linked, 'TxnType')} ${getProp(linked, 'TxnId')}`;
            lineSummaryList.appendChild(li);
          });
        } else {
          lineCell.textContent = '(No Line Details Found)';
        }
      });
      container.appendChild(table);
    }

    // Generic display function for JSON or table rendering.
    function displayData(data, container, dataType) {
      container.innerHTML = '';
      if (dataType === 'raw_table') {
        displayRawTable(data, container);
      } else if (dataType.includes('_raw')) {
        // For other _raw types, fallback to displaying raw JSON.
        displayRawJson(data, container);
      } else if (dataType.includes('transactions_curl') || dataType.includes('transactions')) {
        displayTransactionTable(data, container);
      } else if (Array.isArray(data) && data.length > 0) {
        const table = document.createElement('table');
        const thead = table.createTHead();
        const tbody = table.createTBody();
        const headerRow = thead.insertRow();
        let headers = [];
        for (let i = 0; i < Math.min(data.length, 5); i++) {
          if (data[i] && typeof data[i] === 'object') headers = [...new Set([...headers, ...Object.keys(data[i])])];
        }
        if (headers.length === 0 && data.length > 0 && data[0] && typeof data[0] === 'object') {
          headers = Object.keys(data[0]);
        }
        headers.sort();
        headers.forEach(headerText => {
          const th = document.createElement('th');
          th.textContent = headerText;
          headerRow.appendChild(th);
        });
        data.forEach(item => {
          if (!item || typeof item !== 'object') return;
          const row = tbody.insertRow();
          headers.forEach(header => {
            const cell = row.insertCell();
            let value = item[header];
            if (typeof value === 'object' && value !== null) {
              try { value = JSON.stringify(value); } catch (e) { value = '[Object]'; }
            }
            if (String(value).length > 150) value = String(value).substring(0, 150) + '...';
            cell.textContent = value !== null && value !== undefined ? value : '';
          });
        });
        container.appendChild(table);
      } else if (typeof data === 'object' && data !== null) {
        displayRawJson(data, container);
      } else {
        container.textContent = 'No data found or data is not in a displayable format.';
      }
    }

    // Function to render raw JSON data as a simple <pre> block.
    function displayRawJson(data, container) {
      container.innerHTML = '';
      const pre = document.createElement('pre');
      pre.textContent = JSON.stringify(data, null, 2);
      container.appendChild(pre);
    }

    // Fetch and display function based on button attributes.
    function fetchAndDisplay(dataType, period) {
      let displayTypeStr = dataType.replace(/_/g, ' ');
      if (dataType.includes('_raw')) {
        displayTypeStr = displayTypeStr.replace(' raw', '') + ' (Raw JSON)';
      }
      
      let year, month;
      if (period === 'custom' && customMonth) {
        [year, month] = customMonth.split('-');
        displayArea.innerHTML = `Loading ${displayTypeStr} data for ${customMonth} ...`;
      } else {
        let dateRef = new Date();
        if (period === 'prev_month') {
          dateRef = new Date(dateRef.getFullYear(), dateRef.getMonth(), 0);
        }
        year = dateRef.getFullYear();
        month = (dateRef.getMonth() + 1).toString().padStart(2, '0');
        displayArea.innerHTML = `Loading ${displayTypeStr} data for ${year}-${month} ...`;
      }
      
      let filename = '';
      if (dataType === 'pnl_report') {
        filename = `pnl_report.php?month=${year}-${month}`;
        // Call pnl_report endpoint directly.
        fetch(filename)
          .then(response => {
            if (!response.ok) {
              return response.json().catch(() => response.text())
                .then(errorData => {
                  let errorMsg = `HTTP error ${response.status}`;
                  if (typeof errorData === 'string') {
                    errorMsg = errorData || errorMsg;
                  } else if (errorData && errorData.error) {
                    errorMsg = errorData.error;
                  }
                  throw new Error(errorMsg);
                });
            }
            return response.json();
          })
          .then(data => {
            const title = document.createElement('h3');
            title.textContent = `Displaying: P&L Report for ${year}-${month}`;
            displayArea.innerHTML = '';
            displayArea.appendChild(title);
            renderPnLReport(data, displayArea);
          })
          .catch(error => {
            console.error(`Error fetching or displaying pnl_report data ('${filename}'):`, error);
            displayArea.innerHTML = `<div class="message error">
              Error loading pnl report data: ${error.message}<br>
              (Tried to load file: ${filename}).<br>
              Please ensure data has been refreshed/downloaded and the file exists.
            </div>`;
          });
      } else if (dataType === 'accounts') {
        filename = 'accounts.json';
      } else if (dataType === 'raw_table') {
        // Change this filename to match your actual file.
        filename = `transactions_curl_${year}-${month}.json`;
      } else if (dataType === 'detailed_qbo') {
        // For detailed QBO view, use your transactions file.
        filename = `transactions_curl_${year}-${month}.json`;
      } else {
        filename = `${dataType.replace('_raw','')}_${year}-${month}.json`;
      }
      
      if (dataType !== 'pnl_report') {
        // For dynamic PHP endpoints like detailed_qbo, you may choose to call directly.
        if (dataType === 'detailed_qbo') {
          fetch(`get_data.php?file=${encodeURIComponent(filename)}`)
            .then(response => {
              if (!response.ok) {
                return response.json().catch(() => response.text())
                  .then(errorData => {
                    let errorMsg = `HTTP error ${response.status}`;
                    if (typeof errorData === 'string') {
                      errorMsg = errorData || errorMsg;
                    } else if (errorData && errorData.error) {
                      errorMsg = errorData.error;
                    }
                    throw new Error(errorMsg);
                  });
              }
              return response.json();
            })
            .then(data => {
              const title = document.createElement('h3');
              title.textContent = `Displaying Detailed QBO Table for ${year}-${month}`;
              displayArea.innerHTML = '';
              displayArea.appendChild(title);
              // Call our new detailed table function.
              displayDetailedQboTable(data, displayArea);
            })
            .catch(error => {
              console.error(`Error fetching or displaying detailed_qbo data ('${filename}'):`, error);
              displayArea.innerHTML = `<div class="message error">
                Error loading detailed QBO data: ${error.message}<br>
                (Tried to load file: ${filename}).<br>
                Please ensure data has been refreshed/downloaded and the file exists.
              </div>`;
            });
        } else {
          fetch(`get_data.php?file=${encodeURIComponent(filename)}`)
            .then(response => {
              if (!response.ok) {
                return response.json().catch(() => response.text())
                  .then(errorData => {
                    let errorMsg = `HTTP error ${response.status}`;
                    if (typeof errorData === 'string') {
                      errorMsg = errorData || errorMsg;
                    } else if (errorData && errorData.error) {
                      errorMsg = errorData.error;
                    }
                    throw new Error(errorMsg);
                  });
              }
              return response.json();
            })
            .then(data => {
              const title = document.createElement('h3');
              title.textContent = `Displaying: ${filename} ${dataType.includes('_raw') ? '(Raw JSON)' : ''}`;
              displayArea.innerHTML = '';
              displayArea.appendChild(title);
              if (dataType === 'raw_table') {
                displayRawTable(data, displayArea);
              } else {
                displayData(data, displayArea, dataType);
              }
            })
            .catch(error => {
              if (dataType.includes('transactions_curl')) {
                console.warn(`Warning loading ${dataType} data ('${filename}'):`, error);
                displayArea.innerHTML = `<div class="message warning">
                  Warning loading ${dataType.replace(/_/g, ' ')} data: ${error.message}<br>
                  (Tried to load file: ${filename}). Data may be incomplete; please refresh data when available.
                </div>`;
                displayData([], displayArea, dataType);
              } else {
                console.error(`Error fetching or displaying ${dataType} data ('${filename}'):`, error);
                displayArea.innerHTML = `<div class="message error">
                  Error loading ${dataType.replace(/_/g, ' ')} data: ${error.message}<br>
                  (Tried to load file: ${filename}).<br>
                  Please ensure data has been refreshed/downloaded and the file exists.
                </div>`;
              }
            });
        }
      }
    }

    // Detailed QBO table: a nested table view for each transaction.
    function displayDetailedQboTable(data, container) {
      container.innerHTML = '';
      if (!Array.isArray(data) || data.length === 0) {
        container.textContent = 'No QBO transaction data found.';
        return;
      }
      const masterTable = document.createElement('table');
      masterTable.style.width = '100%';
      masterTable.style.borderCollapse = 'collapse';

      data.forEach((txn, idx) => {
        if (!txn || typeof txn !== 'object') return;

        // Separator row for visual clarity
        const sepRow = masterTable.insertRow();
        const sepCell = sepRow.insertCell();
        sepCell.colSpan = 2;
        sepCell.style.padding = '10px 0';

        // Top-level table for transaction summary
        const summaryTable = document.createElement('table');
        summaryTable.style.width = '100%';
        summaryTable.style.marginBottom = '6px';
        summaryTable.style.border = '1px solid #ccc';
        summaryTable.style.borderCollapse = 'collapse';

        // Define fields to show in the summary. Adjust as needed.
        const fieldsToShow = ['Id', 'TxnDate', 'TotalAmt', 'Balance'];
        fieldsToShow.forEach(field => {
          if (txn[field] !== undefined) {
            const row = summaryTable.insertRow();
            row.style.borderBottom = '1px solid #eee';
            const labelCell = row.insertCell();
            labelCell.style.padding = '6px 8px';
            labelCell.style.fontWeight = 'bold';
            labelCell.style.width = '120px';
            labelCell.textContent = field;
            const valueCell = row.insertCell();
            valueCell.style.padding = '6px 8px';
            if (typeof txn[field] === 'object') {
              valueCell.textContent = JSON.stringify(txn[field]);
            } else {
              valueCell.textContent = txn[field];
            }
          }
        });
        sepCell.appendChild(summaryTable);

        // If there's a Line array, create a sub-table.
        if (Array.isArray(txn.Line)) {
          const lineTable = document.createElement('table');
          lineTable.style.width = '100%';
          lineTable.style.border = '1px solid #ccc';
          lineTable.style.borderCollapse = 'collapse';
          lineTable.style.marginBottom = '20px';

          const lineThead = document.createElement('thead');
          const headerRow = document.createElement('tr');
          const lineHeaders = ['LineNum', 'DetailType', 'Amount', 'Description', 'AccountRef'];
          lineHeaders.forEach(h => {
            const th = document.createElement('th');
            th.textContent = h;
            th.style.border = '1px solid #dee2e6';
            th.style.padding = '6px 8px';
            th.style.whiteSpace = 'normal';
            headerRow.appendChild(th);
          });
          lineThead.appendChild(headerRow);
          lineTable.appendChild(lineThead);

          const lineTbody = document.createElement('tbody');
          txn.Line.forEach(line => {
            if (!line || typeof line !== 'object') return;
            const tr = document.createElement('tr');
            tr.style.borderBottom = '1px solid #eee';

            // LineNum
            let td = tr.insertCell();
            td.style.padding = '6px 8px';
            td.textContent = line.LineNum || '';

            // DetailType
            td = tr.insertCell();
            td.style.padding = '6px 8px';
            td.textContent = line.DetailType || '';

            // Amount
            td = tr.insertCell();
            td.style.padding = '6px 8px';
            td.textContent = line.Amount !== undefined ? String(line.Amount) : '';

            // Description
            td = tr.insertCell();
            td.style.padding = '6px 8px';
            td.style.whiteSpace = 'normal';
            td.textContent = line.Description || '';

            // AccountRef (if available, from SalesItemLineDetail, etc.)
            let acctRef = '';
            if (line.SalesItemLineDetail && line.SalesItemLineDetail.ItemAccountRef) {
              acctRef = line.SalesItemLineDetail.ItemAccountRef.name || '';
            } else if (line.AccountBasedExpenseLineDetail && line.AccountBasedExpenseLineDetail.AccountRef) {
              acctRef = line.AccountBasedExpenseLineDetail.AccountRef.name || '';
            }
            td = tr.insertCell();
            td.style.padding = '6px 8px';
            td.textContent = acctRef;

            lineTbody.appendChild(tr);
          });
          lineTable.appendChild(lineTbody);
          sepCell.appendChild(lineTable);
        }
        masterTable.appendChild(sepRow);
      });
      container.appendChild(masterTable);
    }

    // Generic display function for JSON or table rendering.
    function displayData(data, container, dataType) {
      container.innerHTML = '';
      if (dataType === 'raw_table') {
        displayRawTable(data, container);
      } else if (dataType.includes('_raw')) {
        displayRawJson(data, container);
      } else if (dataType.includes('transactions_curl') || dataType.includes('transactions')) {
        displayTransactionTable(data, container);
      } else if (Array.isArray(data) && data.length > 0) {
        const table = document.createElement('table');
        const thead = table.createTHead();
        const tbody = table.createTBody();
        const headerRow = thead.insertRow();
        let headers = [];
        for (let i = 0; i < Math.min(data.length, 5); i++) {
          if (data[i] && typeof data[i] === 'object') headers = [...new Set([...headers, ...Object.keys(data[i])])];
        }
        if (headers.length === 0 && data.length > 0 && data[0] && typeof data[0] === 'object') {
          headers = Object.keys(data[0]);
        }
        headers.sort();
        headers.forEach(headerText => {
          const th = document.createElement('th');
          th.textContent = headerText;
          headerRow.appendChild(th);
        });
        data.forEach(item => {
          if (!item || typeof item !== 'object') return;
          const row = tbody.insertRow();
          headers.forEach(header => {
            const cell = row.insertCell();
            let value = item[header];
            if (typeof value === 'object' && value !== null) {
              try { value = JSON.stringify(value); } catch (e) { value = '[Object]'; }
            }
            if (String(value).length > 150) value = String(value).substring(0, 150) + '...';
            cell.textContent = value !== null && value !== undefined ? value : '';
          });
        });
        container.appendChild(table);
      } else if (typeof data === 'object' && data !== null) {
        displayRawJson(data, container);
      } else {
        container.textContent = 'No data found or data is not in a displayable format.';
      }
    }

    // Simple function to display raw JSON in a <pre> block.
    function displayRawJson(data, container) {
      container.innerHTML = '';
      const pre = document.createElement('pre');
      pre.textContent = JSON.stringify(data, null, 2);
      container.appendChild(pre);
    }

    // Fetch and display function.
    function fetchAndDisplay(dataType, period) {
      let displayTypeStr = dataType.replace(/_/g, ' ');
      if (dataType.includes('_raw')) {
        displayTypeStr = displayTypeStr.replace(' raw', '') + ' (Raw JSON)';
      }
      
      let year, month;
      if (period === 'custom' && customMonth) {
        [year, month] = customMonth.split('-');
        displayArea.innerHTML = `Loading ${displayTypeStr} data for ${customMonth} ...`;
      } else {
        let dateRef = new Date();
        if (period === 'prev_month') {
          dateRef = new Date(dateRef.getFullYear(), dateRef.getMonth(), 0);
        }
        year = dateRef.getFullYear();
        month = (dateRef.getMonth() + 1).toString().padStart(2, '0');
        displayArea.innerHTML = `Loading ${displayTypeStr} data for ${year}-${month} ...`;
      }
      
      let filename = '';
      if (dataType === 'pnl_report') {
        filename = `pnl_report.php?month=${year}-${month}`;
        // Directly call pnl_report endpoint.
        fetch(filename)
          .then(response => {
            if (!response.ok) {
              return response.json().catch(() => response.text())
                .then(errorData => {
                  let errorMsg = `HTTP error ${response.status}`;
                  if (typeof errorData === 'string') { errorMsg = errorData || errorMsg; }
                  else if (errorData && errorData.error) { errorMsg = errorData.error; }
                  throw new Error(errorMsg);
                });
            }
            return response.json();
          })
          .then(data => {
            const title = document.createElement('h3');
            title.textContent = `Displaying: P&L Report for ${year}-${month}`;
            displayArea.innerHTML = '';
            displayArea.appendChild(title);
            renderPnLReport(data, displayArea);
          })
          .catch(error => {
            console.error(`Error fetching or displaying pnl_report data ('${filename}'):`, error);
            displayArea.innerHTML = `<div class="message error">
              Error loading pnl report data: ${error.message}<br>
              (Tried to load file: ${filename}).<br>
              Please ensure data has been refreshed/downloaded and the file exists.
            </div>`;
          });
      } else if (dataType === 'accounts') {
        filename = 'accounts.json';
      } else if (dataType === 'raw_table') {
        // Adjust this filename if necessary. Here we assume your raw transactions file is named "transactions_curl_raw_YYYY-MM.json"
        filename = `transactions_curl_${year}-${month}.json`;
      } else if (dataType === 'detailed_qbo') {
        filename = `transactions_curl_${year}-${month}.json`;
      } else {
        filename = `${dataType.replace('_raw','')}_${year}-${month}.json`;
      }
      
      if (dataType !== 'pnl_report') {
        if (dataType === 'detailed_qbo') {
          fetch(`get_data.php?file=${encodeURIComponent(filename)}`)
            .then(response => {
              if (!response.ok) {
                return response.json().catch(() => response.text())
                  .then(errorData => {
                    let errorMsg = `HTTP error ${response.status}`;
                    if (typeof errorData === 'string') { errorMsg = errorData || errorMsg; }
                    else if (errorData && errorData.error) { errorMsg = errorData.error; }
                    throw new Error(errorMsg);
                  });
              }
              return response.json();
            })
            .then(data => {
              const title = document.createElement('h3');
              title.textContent = `Displaying Detailed QBO Table for ${year}-${month}`;
              displayArea.innerHTML = '';
              displayArea.appendChild(title);
              displayDetailedQboTable(data, displayArea);
            })
            .catch(error => {
              console.error(`Error fetching or displaying detailed_qbo data ('${filename}'):`, error);
              displayArea.innerHTML = `<div class="message error">
                Error loading detailed QBO data: ${error.message}<br>
                (Tried to load file: ${filename}).<br>
                Please ensure data has been refreshed/downloaded and the file exists.
              </div>`;
            });
        } else {
          fetch(`get_data.php?file=${encodeURIComponent(filename)}`)
            .then(response => {
              if (!response.ok) {
                return response.json().catch(() => response.text())
                  .then(errorData => {
                    let errorMsg = `HTTP error ${response.status}`;
                    if (typeof errorData === 'string') { errorMsg = errorData || errorMsg; }
                    else if (errorData && errorData.error) { errorMsg = errorData.error; }
                    throw new Error(errorMsg);
                  });
              }
              return response.json();
            })
            .then(data => {
              const title = document.createElement('h3');
              title.textContent = `Displaying: ${filename} ${dataType.includes('_raw') ? '(Raw JSON)' : ''}`;
              displayArea.innerHTML = '';
              displayArea.appendChild(title);
              if (dataType === 'raw_table') {
                displayRawTable(data, displayArea);
              } else {
                displayData(data, displayArea, dataType);
              }
            })
            .catch(error => {
              if (dataType.includes('transactions_curl')) {
                console.warn(`Warning loading ${dataType} data ('${filename}'):`, error);
                displayArea.innerHTML = `<div class="message warning">
                  Warning loading ${dataType.replace(/_/g, ' ')} data: ${error.message}<br>
                  (Tried to load file: ${filename}). Data may be incomplete; please refresh data when available.
                </div>`;
                displayData([], displayArea, dataType);
              } else {
                console.error(`Error fetching or displaying ${dataType} data ('${filename}'):`, error);
                displayArea.innerHTML = `<div class="message error">
                  Error loading ${dataType.replace(/_/g, ' ')} data: ${error.message}<br>
                  (Tried to load file: ${filename}).<br>
                  Please ensure data has been refreshed/downloaded and the file exists.
                </div>`;
              }
            });
        }
      }
    }

    // Function to render the P&L report as an expandable tree.
    function renderPnLReport(data, container) {
      const reportContainer = document.createElement('div');
      reportContainer.classList.add('pnl-report');

      const netProfitEl = document.createElement('h4');
      netProfitEl.textContent = `Net Profit: ${data.netProfit}`;
      reportContainer.appendChild(netProfitEl);

      function renderAccount(account) {
        const accDiv = document.createElement('div');
        accDiv.classList.add('account-section');

        const header = document.createElement('div');
        header.classList.add('account-header');
        header.innerHTML = `<strong>${account.account}</strong> - Total: ${account.total} (${account.percentage || 'N/A'})`;
        header.addEventListener('click', () => {
          subList.style.display = subList.style.display === 'none' ? 'block' : 'none';
        });
        accDiv.appendChild(header);

        const subList = document.createElement('div');
        subList.classList.add('account-content');
        subList.style.display = 'none';

        if (account.subaccounts && Array.isArray(account.subaccounts) && account.subaccounts.length > 0) {
          account.subaccounts.forEach(sub => {
            subList.appendChild(renderAccount(sub));
          });
        } else if (account.transactions && Array.isArray(account.transactions) && account.transactions.length > 0) {
          account.transactions.sort((a, b) => b.amount - a.amount);
          const transList = document.createElement('ul');
          account.transactions.forEach(txn => {
            const li = document.createElement('li');
            li.textContent = `${txn.date} - ${txn.amount} (${txn.percentage || 'N/A'})`;
            transList.appendChild(li);
          });
          subList.appendChild(transList);
        }
        accDiv.appendChild(subList);
        return accDiv;
      }

      if (data.summary && Array.isArray(data.summary)) {
        data.summary.forEach(account => {
          reportContainer.appendChild(renderAccount(account));
        });
      } else {
        reportContainer.textContent = 'No P&L data available.';
      }
      container.appendChild(reportContainer);
    }

    // Attach event listeners to display buttons.
    if (displayButtons.length > 0) {
      displayButtons.forEach(button => {
        button.addEventListener('click', () => {
          const dataType = button.getAttribute('data-type');
          const period = button.getAttribute('data-period') || 'current_month';
          if (!dataType) {
            console.error("Button is missing data-type attribute.");
            return;
          }
          fetchAndDisplay(dataType, period);
        });
      });
    }
  </script>
</body>
</html>
