<script>
  import { 
    FlaskConical, 
    AlertTriangle, 
    CheckCircle2, 
    X, 
    Save, 
    User, 
    FileText, 
    TestTube, 
    Calendar, 
    Clock, 
    Hash, 
    MessageSquare, 
    Copy,
    ChevronDown,
    ChevronUp,
    Calculator,
    RefreshCw
  } from 'lucide-svelte';
import { calculateByTestSite } from '$lib/api/calculator.js';
  import { updateResult } from '$lib/api/results.js';
  import { error as toastError, success as toastSuccess } from '$lib/utils/toast.js';
  import Modal from '$lib/components/Modal.svelte';
  import { untrack } from 'svelte';

  let { 
    order = $bindable(),
    open = $bindable(false),
    onSaved
  } = $props();

  // Form state - array of result entries
  let results = $state([]);
  let formLoading = $state(false);
  let saveProgress = $state({ current: 0, total: 0 });
  let calcLoading = $state(false);
  
  // Expandable rows for comments
  let expandedRows = $state(new Set());
  
  // Keyboard shortcuts enabled
  let shortcutsEnabled = $state(true);
  
  // Guard to prevent repeated initialization
  let initKey = $state('');
  
  // Calculation engine state
  /** @type {Map<number, string>} TestSiteID -> Result value */
  let resultMapById = $state(new Map());
  /** @type {Map<string, string>} TestSiteCode -> Result value */
  let resultMapByCode = $state(new Map());
  /** @type {Map<number, CalcDef>} TestSiteID -> Calculation definition */
  let calcDefs = $state(new Map());
  /** @type {Map<number, Set<number>>} Member TestSiteID -> Set of dependent CALC TestSiteIDs */
  let dependencyGraph = $state(new Map());

  /** @typedef {{ id: number, code: string, formula: string, members: Array<{id: number, code: string}>, decimal: number }} CalcDef */

  // Initialize results when order changes
  $effect(() => {
    if (order && open) {
      // Guard: only initialize once per order/open combination
      const currentKey = `${order.OrderID}-${open}`;
      if (initKey === currentKey) return;
      initKey = currentKey;
      
      // Use untrack to prevent the effect from tracking internal state mutations
      untrack(() => initializeResults());
    }
  });
  
  /**
   * Initialize results and build calculation context
   */
  function initializeResults() {
    // Map tests to editable result entries
    results = (order.Tests || []).map(test => ({
      ResultID: test.ResultID,
      TestSiteID: test.TestSiteID,
      TestSiteCode: test.TestSiteCode,
      TestSiteName: test.TestSiteName,
      Result: test.Result || '',
      SampleType: test.SampleType || '',
      WorkstationID: test.WorkstationID || '',
      EquipmentID: test.EquipmentID || '',
      Unit1: test.Unit1,
      Low: test.Low,
      High: test.High,
      LowSign: test.LowSign,
      HighSign: test.HighSign,
      RefDisplay: test.RefDisplay,
      RefNumID: test.RefNumID,
      ResultStatus: test.ResultStatus || 'PRE',
      EnteredBy: test.EnteredBy || '',
      EnteredDateTime: test.EnteredDateTime || '',
      Comment: test.Comment || '',
      flag: calculateFlag(test.Result, test.Low, test.High),
      saved: false,
      error: null,
      warning: null,
      // Dirty tracking
      changedByUser: false,
      changedByAutoCalc: false,
      lastAutoCalcAt: null,
      // Calc metadata
      TestType: test.TestType,
      FormulaCode: test.FormulaCode || null,
      Decimal: test.Decimal ?? 2,
      isCalculated: test.TestType === 'CALC' || (test.FormulaCode && test.FormulaCode.trim() !== ''),
      // Group members for dependency tracking
      testdefgrp: test.testdefgrp || []
    }));
    
    saveProgress = { current: 0, total: 0 };
    expandedRows = new Set();
    
    // Build calculation context
    buildCalcContext();
    
    console.log('Initialized results:', results.length, 'tests');
    console.log('Calc defs:', calcDefs.size, 'calculated tests');
    console.log('Calc test IDs:', Array.from(calcDefs.keys()));
    
  }
  
  /**
   * Build calculation context: result maps, calc definitions, dependency graph
   */
  function buildCalcContext() {
    resultMapById = new Map();
    resultMapByCode = new Map();
    calcDefs = new Map();
    dependencyGraph = new Map();
    
    // Build result lookup maps
    for (const row of results) {
      resultMapById.set(row.TestSiteID, row.Result ?? '');
      if (row.TestSiteCode) {
        resultMapByCode.set(row.TestSiteCode, row.Result ?? '');
      }
    }
    
    // Build calc definitions and dependency graph
    console.log('buildCalcContext: checking', results.length, 'results');
    for (const row of results) {
      console.log('  Result:', row.TestSiteCode, 'TestType:', row.TestType, 'isCalculated:', row.isCalculated, 'FormulaCode:', row.FormulaCode);
      if (!row.isCalculated) continue;
      
      // Parse members from testdefgrp or extract from formula
      const members = parseCalcMembers(row);
      console.log('    Parsed members:', members);
      
      const def = {
        id: row.TestSiteID,
        code: row.TestSiteCode,
        formula: row.FormulaCode || '',
        members,
        decimal: Number.isFinite(+row.Decimal) ? +row.Decimal : 2
      };
      
      calcDefs.set(def.id, def);
      console.log('    Added calc def for:', row.TestSiteCode);
      
      // Build reverse dependency graph: member -> [calcs that depend on it]
      for (const member of members) {
        if (!dependencyGraph.has(member.id)) {
          dependencyGraph.set(member.id, new Set());
        }
        dependencyGraph.get(member.id).add(def.id);
      }
    }
    console.log('buildCalcContext complete, calcDefs size:', calcDefs.size);
  }
  
  /**
   * Parse calculation members from row data
   * @param {Object} row - Result row
   * @returns {Array<{id: number, code: string}>}
   */
  function parseCalcMembers(row) {
    // First try to get from testdefgrp
    if (row.testdefgrp && row.testdefgrp.length > 0) {
      return row.testdefgrp.map(m => ({
        id: Number(m.TestSiteID),
        code: m.TestSiteCode
      }));
    }
    
    // Fallback: extract from formula by finding matching test codes
    const members = [];
    const formula = row.FormulaCode || '';
    const codePattern = /\b([A-Z][A-Z0-9_]*)\b/g;
    let match;
    
    while ((match = codePattern.exec(formula)) !== null) {
      const code = match[1];
      // Find test with this code in results
      const test = results.find(r => r.TestSiteCode === code);
      if (test) {
        members.push({ id: test.TestSiteID, code: test.TestSiteCode });
      }
    }
    
    return members;
  }
  
  /**
   * Get dependency hint text for a CALC test
   * @param {Object} row - Result row
   * @returns {string|null}
   */
  function getDependencyHint(row) {
    if (!row.isCalculated) return null;
    const def = calcDefs.get(row.TestSiteID);
    if (!def || def.members.length === 0) return null;
    const codes = def.members.map(m => m.code).join(', ');
    return `from ${codes}`;
  }
  
  // Keyboard shortcuts
  $effect(() => {
    if (!open) return;
    
    function handleKeyDown(event) {
      if (!shortcutsEnabled) return;
      
      // Ctrl+S: Save all
      if (event.ctrlKey && event.key === 's') {
        event.preventDefault();
        if (!formLoading) {
          handleSaveAll();
        }
      }
      
      // Escape: Close modal (only if not in input)
      if (event.key === 'Escape' && event.target.tagName !== 'INPUT' && event.target.tagName !== 'TEXTAREA') {
        event.preventDefault();
        handleClose();
      }
    }
    
    document.addEventListener('keydown', handleKeyDown);
    return () => document.removeEventListener('keydown', handleKeyDown);
  });

  function calculateFlag(value, low, high) {
    if (!value || value === '') return null;
    
    const numValue = parseFloat(value);
    if (isNaN(numValue)) return null;
    
    if (low !== null && numValue < low) return 'L';
    if (high !== null && numValue > high) return 'H';
    return null;
  }

  function updateResultFlag(index) {
    const entry = results[index];
    results[index].flag = calculateFlag(entry.Result, entry.Low, entry.High);
  }

  /**
   * Recalculate all CALC tests (used for initial load)
   */
  async function recalculateAll() {
    console.log('recalculateAll called, calcDefs size:', calcDefs.size);
    
    // Find all CALC tests that need computation
    const calcsToCompute = [];
    for (const [calcId, def] of calcDefs) {
      const row = results.find(r => r.TestSiteID === calcId);
      if (!row) {
        console.log('  Row not found for calcId:', calcId);
        continue;
      }
      
      console.log('  Checking calc test:', row.TestSiteCode, 'Result:', row.Result, 'changedByAutoCalc:', row.changedByAutoCalc);
      
      // Only auto-fill if empty or was previously auto-calculated
      if (!row.Result || row.Result === '' || row.changedByAutoCalc) {
        calcsToCompute.push({ calcId, def, row });
        console.log('    -> Will compute');
      } else {
        console.log('    -> Skipping (has manual value)');
      }
    }
    
    console.log('Total calcs to compute:', calcsToCompute.length);
    
    if (calcsToCompute.length === 0) return;
    
    await computeCalculations(calcsToCompute);
  }

  /**
   * Recalculate dependent CALC tests starting from a changed test
   * @param {number} changedTestSiteId - The test that changed
   */
  async function recalculateFrom(changedTestSiteId) {
    const queue = [changedTestSiteId];
    const visited = new Set();
    const calcsToCompute = [];
    
    while (queue.length > 0) {
      const currentId = queue.shift();
      
      // Get calcs that depend on this test
      const dependentCalcs = dependencyGraph.get(currentId);
      if (!dependentCalcs) continue;
      
      for (const calcId of dependentCalcs) {
        if (visited.has(calcId)) continue; // Loop protection
        visited.add(calcId);
        
        const def = calcDefs.get(calcId);
        const row = results.find(r => r.TestSiteID === calcId);
        if (!def || !row) continue;
        
        calcsToCompute.push({ calcId, def, row });
        
        // This calc might be a dependency for other calcs, add to queue
        queue.push(calcId);
      }
    }
    
    if (calcsToCompute.length > 0) {
      await computeCalculations(calcsToCompute);
    }
  }

  async function recalculateSingle(testSiteId) {
    const def = calcDefs.get(testSiteId);
    const row = results.find(r => r.TestSiteID === testSiteId);
    if (!def || !row) return;

    await computeCalculations([{ calcId: testSiteId, def, row }]);
    await recalculateFrom(testSiteId);
  }
  
  /**
   * Compute multiple calculations via backend API
   * @param {Array} calcsToCompute - Array of {calcId, def, row}
   */
  async function computeCalculations(calcsToCompute) {
    calcLoading = true;

    try {
      const calculations = calcsToCompute.map(({ def, row }) => {
        const values = {};
        for (const [code, rawValue] of resultMapByCode) {
          if (def.code && code === def.code) continue;
          const numValue = rawValue === '' || rawValue == null ? null : parseFloat(rawValue);
          if (Number.isFinite(numValue)) {
            values[code] = numValue;
          }
        }

        return {
          testSiteId: def.id,
          row,
          formula: def.formula,
          values,
          decimal: def.decimal
        };
      });

      const calcOutputs = await Promise.all(calculations.map(async calc => {
        try {
          const response = await calculateByTestSite(calc.testSiteId, calc.values);
          const apiResult = Number(response?.data?.result);

          if (response?.status !== 'success' || !Number.isFinite(apiResult)) {
            throw new Error(response?.message || 'Calculator service returned an invalid response');
          }

          return {
            testSiteId: calc.testSiteId,
            row: calc.row,
            result: apiResult,
            decimal: calc.decimal
          };
        } catch (err) {
          return {
            testSiteId: calc.testSiteId,
            row: calc.row,
            error: { type: 'CALC_API_ERROR', message: err?.message || 'Failed to calculate result' }
          };
        }
      }));

      for (const calcResult of calcOutputs) {
        const index = results.findIndex(r => r.TestSiteID === calcResult.testSiteId);
        if (index === -1) continue;

        if (calcResult.error) {
          results[index].warning = calcResult.error.message;
        } else {
          const factor = Math.pow(10, calcResult.decimal ?? 2);
          const rounded = Math.round(calcResult.result * factor) / factor;

          results[index].Result = String(rounded);
          results[index].changedByAutoCalc = true;
          results[index].lastAutoCalcAt = Date.now();
          results[index].warning = null;
          results[index].error = null;
          updateResultFlag(index);

          resultMapById.set(calcResult.testSiteId, results[index].Result);
          if (results[index].TestSiteCode) {
            resultMapByCode.set(results[index].TestSiteCode, results[index].Result);
          }
        }
      }
    } catch (err) {
      console.error('Calculation error:', err);
      toastError('Failed to compute calculated values');
    } finally {
      calcLoading = false;
    }
  }

  /**
   * Handle input change - update flag and trigger recalculation of dependent fields
   */
  function handleInputChange(index) {
    const row = results[index];
    
    // Update dirty flag
    results[index].changedByUser = true;
    results[index].saved = false;
    
    // Update lookup maps
    resultMapById.set(row.TestSiteID, row.Result);
    resultMapByCode.set(row.TestSiteCode, row.Result);
    
    updateResultFlag(index);
    
    // Recalculate dependent CALC fields
    recalculateFrom(row.TestSiteID);
  }

  function getFlagColor(flag) {
    if (flag === 'H') return 'text-error';
    if (flag === 'L') return 'text-warning';
    return 'text-success';
  }

  function getFlagBg(flag) {
    if (flag === 'H') return 'bg-error/10';
    if (flag === 'L') return 'bg-warning/10';
    return 'bg-success/10';
  }

  function getInputBg(flag) {
    if (flag === 'H') return 'bg-error/5 border-error/30';
    if (flag === 'L') return 'bg-warning/5 border-warning/30';
    return '';
  }
  
  function getResultStatusBadge(status) {
    const statusMap = {
      'PRE': { color: 'badge-info', label: 'Preliminary' },
      'FIN': { color: 'badge-success', label: 'Final' },
      'MOD': { color: 'badge-warning', label: 'Modified' },
      'COR': { color: 'badge-error', label: 'Corrected' }
    };
    return statusMap[status] || { color: 'badge-neutral', label: status };
  }
  
  function formatDateTime(dateString) {
    if (!dateString) return '-';
    const date = new Date(dateString);
    return date.toLocaleString();
  }
  
  function toggleCommentRow(index) {
    if (expandedRows.has(index)) {
      expandedRows.delete(index);
    } else {
      expandedRows.add(index);
    }
    expandedRows = expandedRows; // Trigger reactivity
  }
  
  function copyResultToClipboard(value) {
    navigator.clipboard.writeText(value).then(() => {
      toastSuccess('Result copied to clipboard');
    }).catch(() => {
      toastError('Failed to copy');
    });
  }
  
  function copyPreviousResult(index) {
    if (index === 0) return;
    // Prevent copying to calculated tests
    if (results[index].isCalculated) return;
    const prevResult = results[index - 1].Result;
    if (prevResult) {
      results[index].Result = prevResult;
      updateResultFlag(index);
    }
  }

  async function handleSaveAll() {
    // Filter to dirty entries (user changed or auto-calc changed)
    // Include cleared results (empty values) that were modified
    const entriesToSave = results.filter(r => 
      !r.saved && 
      (r.changedByUser || r.changedByAutoCalc)
    );
    
    if (entriesToSave.length === 0) {
      toastSuccess('Nothing to save');
      return;
    }

    formLoading = true;
    saveProgress = { current: 0, total: entriesToSave.length };

    try {
      // Save each result sequentially
      for (let i = 0; i < entriesToSave.length; i++) {
        const entry = entriesToSave[i];
        saveProgress.current = i + 1;

        const data = {
          Result: entry.Result,
          SampleType: entry.SampleType || null,
          WorkstationID: entry.WorkstationID ? parseInt(entry.WorkstationID) : null,
          EquipmentID: entry.EquipmentID ? parseInt(entry.EquipmentID) : null,
          RefNumID: entry.RefNumID || null,
          Comment: entry.Comment || null
        };

        const response = await updateResult(entry.ResultID, data);
        
        if (response.status === 'success') {
          // Mark as saved and clear dirty flags
          const resultIndex = results.findIndex(r => r.ResultID === entry.ResultID);
          if (resultIndex !== -1) {
            results[resultIndex].saved = true;
            results[resultIndex].error = null;
            results[resultIndex].changedByUser = false;
            results[resultIndex].changedByAutoCalc = false;
          }
        } else {
          // Mark with error
          const resultIndex = results.findIndex(r => r.ResultID === entry.ResultID);
          if (resultIndex !== -1) {
            results[resultIndex].error = response.message || 'Failed to save';
          }
        }
      }

      // Check if all were saved successfully
      const failedCount = results.filter(r => r.error).length;
      if (failedCount === 0) {
        toastSuccess(`Saved ${entriesToSave.length} result(s) successfully`);
        onSaved?.();
      } else {
        toastError(`${failedCount} result(s) failed to save`);
      }
    } catch (err) {
      toastError(err.message || 'Failed to save results');
    } finally {
      formLoading = false;
      saveProgress = { current: 0, total: 0 };
    }
  }

  function handleClose() {
    open = false;
  }

  function handleKeyDown(event, index) {
    // Navigate with Enter/Arrow keys
    if (event.key === 'Enter' && !event.shiftKey) {
      event.preventDefault();
      const nextIndex = index + 1;
      if (nextIndex < results.length) {
        const nextInput = document.getElementById(`result-input-${nextIndex}`);
        nextInput?.focus();
        nextInput?.select();
      }
    }
    
    // Shift+Enter: Previous field
    if (event.key === 'Enter' && event.shiftKey) {
      event.preventDefault();
      const prevIndex = index - 1;
      if (prevIndex >= 0) {
        const prevInput = document.getElementById(`result-input-${prevIndex}`);
        prevInput?.focus();
        prevInput?.select();
      }
    }
    
    // Alt+C: Copy previous result (disabled for calculated tests)
    if (event.key === 'c' && event.altKey) {
      event.preventDefault();
      if (!results[index].isCalculated) {
        copyPreviousResult(index);
      }
    }
  }

  const pendingCount = $derived(results.filter(r => !r.Result || r.Result === '').length);
  const savedCount = $derived(results.filter(r => r.saved).length);
</script>

<Modal bind:open={open} title="Enter Results - Order {order?.OrderID}" size="xl">
  {#snippet children()}
    <div class="space-y-4">
      <!-- Order Info Header -->
      <div class="bg-base-200/50 rounded-lg p-3">
        <div class="flex items-center justify-between">
          <div class="flex items-center gap-4">
            <div class="flex items-center gap-2">
              <User class="w-4 h-4 text-primary" />
              <span class="text-sm font-medium">{order?.PatientName || 'Unknown'}</span>
              <span class="text-xs text-base-content/50">(ID: {order?.InternalPID})</span>
            </div>
            <div class="flex items-center gap-2">
              <FileText class="w-4 h-4 text-primary" />
              <span class="text-xs text-base-content/70">{order?.Tests?.length || 0} tests</span>
            </div>
          </div>
          <div class="flex items-center gap-2 text-xs">
            {#if pendingCount > 0}
              <span class="badge badge-warning badge-sm">{pendingCount} pending</span>
            {/if}
            {#if savedCount > 0}
              <span class="badge badge-success badge-sm">{savedCount} saved</span>
            {/if}
          </div>
        </div>
      </div>
      
      <!-- Specimen Information -->
      {#if order?.Specimens?.length > 0}
        <div class="card bg-base-100 border border-base-200">
          <div class="card-body p-3">
            <div class="flex items-center gap-2 mb-2">
              <TestTube class="w-4 h-4 text-primary" />
              <span class="text-sm font-semibold">Specimen Information</span>
            </div>
            <div class="grid grid-cols-2 md:grid-cols-4 gap-3 text-xs">
              {#each order.Specimens as specimen, index (specimen.SpecimenID ?? specimen.Barcode ?? index)}
                <div class="bg-base-200/50 rounded p-2">
                  <div class="flex items-center gap-1 text-base-content/60 mb-1">
                    <Hash class="w-3 h-3" />
                    <span>Barcode</span>
                  </div>
                  <div class="font-mono font-medium">{specimen.Barcode || '-'}</div>
                </div>
                <div class="bg-base-200/50 rounded p-2">
                  <div class="flex items-center gap-1 text-base-content/60 mb-1">
                    <FlaskConical class="w-3 h-3" />
                    <span>Type</span>
                  </div>
                  <div class="font-medium">{specimen.SpecimenType || '-'}</div>
                </div>
                <div class="bg-base-200/50 rounded p-2">
                  <div class="flex items-center gap-1 text-base-content/60 mb-1">
                    <Calendar class="w-3 h-3" />
                    <span>Collected</span>
                  </div>
                  <div class="font-medium">{specimen.CollectionDateTime ? new Date(specimen.CollectionDateTime).toLocaleString() : '-'}</div>
                </div>
                <div class="bg-base-200/50 rounded p-2">
                  <div class="flex items-center gap-1 text-base-content/60 mb-1">
                    <User class="w-3 h-3" />
                    <span>Collector</span>
                  </div>
                  <div class="font-medium">{specimen.Collector || '-'}</div>
                </div>
              {/each}
            </div>
          </div>
        </div>
      {/if}

      <!-- Results Table -->
      <div class="overflow-x-auto max-h-[400px] overflow-y-auto">
        <table class="table table-sm">
          <thead class="sticky top-0 bg-base-100 z-10">
            <tr class="bg-base-200">
              <th class="text-xs font-semibold w-12">Code</th>
              <th class="text-xs font-semibold">Test Name</th>
              <th class="text-xs font-semibold w-28">Result</th>
              <th class="text-xs font-semibold w-12">Flag</th>
              <th class="text-xs font-semibold w-20">Reference</th>
              <th class="text-xs font-semibold w-14">Unit</th>
              <th class="text-xs font-semibold w-16">Status</th>
              <th class="text-xs font-semibold w-10 text-center">Cmt</th>
              <th class="text-xs font-semibold w-10"></th>
            </tr>
          </thead>
          <tbody>
            {#each results as result, index (result.ResultID)}
              {@const statusBadge = getResultStatusBadge(result.ResultStatus)}
              <tr class="hover:bg-base-200/30 {result.saved ? 'opacity-60' : ''}">
                <td class="text-xs font-mono">{result.TestSiteCode}</td>
                <td class="text-xs">
                  <div class="flex flex-col">
                    <div class="flex items-center gap-1">
                      <span>{result.TestSiteName}</span>
                      {#if result.isCalculated}
                        <span class="badge badge-xs badge-primary" title="Auto-calculated: {result.FormulaCode}">CALC</span>
                      {/if}
                    </div>
                    {#if result.isCalculated}
                      {@const hint = getDependencyHint(result)}
                      {#if hint}
                        <div class="text-xs text-primary/70">{hint}</div>
                      {/if}
                    {/if}
                    {#if result.warning}
                      <div class="text-warning text-xs flex items-center gap-1">
                        <AlertTriangle class="w-3 h-3" />
                        {result.warning}
                      </div>
                    {/if}
                    {#if result.error}
                      <div class="text-error text-xs">{result.error}</div>
                    {/if}
                    {#if result.EnteredBy}
                      <div class="text-xs text-base-content/40">
                        By {result.EnteredBy} at {formatDateTime(result.EnteredDateTime)}
                      </div>
                    {/if}
                  </div>
                </td>
                <td class="p-1">
                  <label class="input input-sm input-bordered flex items-center gap-1 w-full {getInputBg(result.flag)} {result.isCalculated ? 'border-primary/50 bg-primary/5' : ''}">
                    {#if result.isCalculated}
                      <Calculator class="w-3 h-3 text-primary flex-shrink-0" title="Auto-calculated" />
                    {:else if result.flag === 'H'}
                      <AlertTriangle class="w-3 h-3 text-error flex-shrink-0" />
                    {:else if result.flag === 'L'}
                      <AlertTriangle class="w-3 h-3 text-warning flex-shrink-0" />
                    {:else if result.Result}
                      <CheckCircle2 class="w-3 h-3 text-success flex-shrink-0" />
                    {/if}
                    {#if result.isCalculated}
                      <!-- CALC tests: read-only display with refresh button -->
                      <input 
                        id="result-input-{index}"
                        type="text" 
                        class="grow bg-transparent outline-none text-sm font-mono cursor-not-allowed"
                        placeholder="Auto"
                        value={result.Result}
                        readonly
                        disabled={formLoading}
                      />
                      <button
                        class="btn btn-ghost btn-xs p-0 min-h-0 h-auto"
                        onclick={() => recalculateSingle(result.TestSiteID)}
                        disabled={calcLoading || formLoading}
                        title="Recalculate"
                      >
                        <RefreshCw class="w-3 h-3 text-primary {calcLoading ? 'animate-spin' : ''}" />
                      </button>
                    {:else}
                      <!-- Regular tests: editable -->
                      <input 
                        id="result-input-{index}"
                        type="text" 
                        class="grow bg-transparent outline-none text-sm font-mono"
                        placeholder="..."
                        bind:value={result.Result}
                        oninput={() => handleInputChange(index)}
                        onkeydown={(e) => handleKeyDown(e, index)}
                        disabled={result.saved || formLoading}
                      />
                    {/if}
                    {#if result.Unit1}
                      <span class="text-xs text-base-content/50 flex-shrink-0">{result.Unit1}</span>
                    {/if}
                  </label>
                </td>
                <td class="text-xs text-center">
                  {#if result.flag}
                    <span class="badge {result.flag === 'H' ? 'badge-error' : 'badge-warning'} badge-sm">
                      {result.flag}
                    </span>
                  {:else}
                    <span class="text-base-content/30">-</span>
                  {/if}
                </td>
                <td class="text-xs text-base-content/60">{result.RefDisplay || '-'}</td>
                <td class="text-xs">{result.Unit1 || '-'}</td>
                <td class="text-xs">
                  <span class="badge {statusBadge.color} badge-sm">{statusBadge.label}</span>
                </td>
                <td class="text-center">
                  <button 
                    class="btn btn-ghost btn-xs {result.Comment ? 'text-primary' : 'text-base-content/30'}"
                    onclick={() => toggleCommentRow(index)}
                    title="{result.Comment || 'Add comment'}"
                  >
                    <MessageSquare class="w-3 h-3" />
                  </button>
                </td>
                <td class="text-center">
                  <div class="flex gap-1">
                    <button 
                      class="btn btn-ghost btn-xs text-base-content/30 hover:text-primary"
                      onclick={() => copyPreviousResult(index)}
                      disabled={index === 0 || result.isCalculated}
                      title="Copy previous result (Alt+C)"
                    >
                      <Copy class="w-3 h-3" />
                    </button>
                  </div>
                </td>
              </tr>
              <!-- Comment Row -->
              {#if expandedRows.has(index)}
                <tr class="bg-base-200/30">
                  <td colspan="9" class="p-2">
                    <div class="flex items-start gap-2">
                      <MessageSquare class="w-4 h-4 text-primary mt-1 flex-shrink-0" />
                      <div class="flex-1">
                        <label class="form-control">
                          <span class="label-text text-xs text-base-content/60">Test Comment</span>
                          <textarea
                            class="textarea textarea-sm textarea-bordered w-full text-xs"
                            placeholder="Enter comment for this test result..."
                            bind:value={result.Comment}
                            disabled={result.saved || formLoading}
                            rows="2"
                          ></textarea>
                        </label>
                      </div>
                      <button 
                        class="btn btn-ghost btn-xs self-end"
                        onclick={() => toggleCommentRow(index)}
                      >
                        <ChevronUp class="w-4 h-4" />
                      </button>
                    </div>
                  </td>
                </tr>
              {/if}
            {/each}
          </tbody>
        </table>
      </div>

      <!-- Legend -->
      <div class="flex flex-wrap gap-4 text-xs text-base-content/60 pt-2 border-t">
        <div class="flex items-center gap-1">
          <span class="badge badge-error badge-sm">H</span>
          <span>High</span>
        </div>
        <div class="flex items-center gap-1">
          <span class="badge badge-warning badge-sm">L</span>
          <span>Low</span>
        </div>
        <div class="flex items-center gap-1">
          <CheckCircle2 class="w-3 h-3 text-success" />
          <span>Normal</span>
        </div>
        <div class="flex items-center gap-2 ml-auto">
          <span class="kbd kbd-sm">Enter</span>
          <span>Next</span>
          <span class="kbd kbd-sm">Shift+Enter</span>
          <span>Prev</span>
          <span class="kbd kbd-sm">Alt+C</span>
          <span>Copy</span>
          <span class="kbd kbd-sm">Ctrl+S</span>
          <span>Save</span>
          <span class="kbd kbd-sm">Esc</span>
          <span>Close</span>
        </div>
      </div>

      <!-- Progress -->
      {#if formLoading && saveProgress.total > 0}
        <div class="flex items-center gap-2 text-sm">
          <span class="loading loading-spinner loading-xs"></span>
          <span>Saving {saveProgress.current} of {saveProgress.total}...</span>
        </div>
      {/if}
    </div>
  {/snippet}

  {#snippet footer()}
    <button class="btn btn-ghost btn-sm" onclick={handleClose} disabled={formLoading}>
      <X class="w-4 h-4" />
      Close
    </button>
    <button 
      class="btn btn-primary btn-sm" 
      onclick={handleSaveAll}
      disabled={formLoading}
    >
      {#if formLoading}
        <span class="loading loading-spinner loading-xs"></span>
        Saving...
      {:else}
        <Save class="w-4 h-4" />
        Save All Results
      {/if}
    </button>
  {/snippet}
</Modal>
