<script>
  import { Plus, Trash2, Hash, Edit2, X, ChevronDown, ChevronUp } from 'lucide-svelte';
  import { valueSets } from '$lib/stores/valuesets.js';
  import { onMount } from 'svelte';

  let { formData = $bindable(), isDirty = $bindable(false) } = $props();

  let isEditing = $state(false);
  let editingIndex = $state(null);
  let validationError = $state('');
  let showAdvanced = $state(false);
  let specimenTypes = $state([]);

  let simpleRefNum = $state({
    NumRefType: 'REF',
    Low: '',
    High: '',
    Sex: '0',
    AgeStart: '',
    AgeEnd: '',
    AgeUnit: 'years',
    SpcType: '',
    Display: 1,
    Flag: '',
    Interpretation: '',
    Notes: ''
  });

  const numRefTypeOptions = [
    { value: 'REF', label: 'Reference' },
    { value: 'CRTC', label: 'Critical' },
    { value: 'VAL', label: 'Validation' },
    { value: 'RERUN', label: 'Rerun' }
  ];

  const sexOptions = [
    { value: '0', label: 'All' },
    { value: '1', label: 'Female' },
    { value: '2', label: 'Male' }
  ];

  const ageUnits = [
    { value: 'days', label: 'Days' },
    { value: 'weeks', label: 'Weeks' },
    { value: 'months', label: 'Months' },
    { value: 'years', label: 'Years' }
  ];

  onMount(async () => {
    try {
      const items = await valueSets.load('specimen_type');
      specimenTypes = items.map(item => ({
        value: item.value || '',
        label: item.label || ''
      }));
    } catch (err) {
      console.error('Failed to load specimen types:', err);
    }
  });

  function handleFieldChange() {
    isDirty = true;
    validationError = '';
  }

  function convertAgeToDays(value, unit) {
    if (!value && value !== 0) return null;
    const num = parseInt(value);
    switch (unit) {
      case 'days': return num;
      case 'weeks': return num * 7;
      case 'months': return num * 30;
      case 'years': return num * 365;
      default: return num;
    }
  }

  function convertDaysToUnit(days, unit) {
    if (days === null || days === undefined) return '';
    switch (unit) {
      case 'days': return days;
      case 'weeks': return Math.floor(days / 7);
      case 'months': return Math.floor(days / 30);
      case 'years': return Math.floor(days / 365);
      default: return days;
    }
  }

  function resetForm() {
    simpleRefNum = {
      NumRefType: 'REF',
      Low: '',
      High: '',
      Sex: '0',
      AgeStart: '',
      AgeEnd: '',
      AgeUnit: 'years',
      SpcType: '',
      Display: 1,
      Flag: '',
      Interpretation: '',
      Notes: ''
    };
    validationError = '';
    isEditing = false;
    editingIndex = null;
    showAdvanced = false;
  }

  function sexOverlaps(sex1, sex2) {
    if (sex1 === '0' || sex2 === '0') return true;
    return sex1 === sex2;
  }

  function specimenOverlaps(spec1, spec2) {
    if (!spec1 && !spec2) return true;
    if ((!spec1 && spec2) || (spec1 && !spec2)) return false;
    return spec1 === spec2;
  }

  function ageOverlaps(start1, end1, start2, end2) {
    const s1 = start1 || 0;
    const e1 = end1 || 54750;
    const s2 = start2 || 0;
    const e2 = end2 || 54750;
    return s1 < e2 && e1 > s2;
  }

  function findOverlappingRange(newRef, excludeIndex = null) {
    const ageStart = convertAgeToDays(simpleRefNum.AgeStart, simpleRefNum.AgeUnit) || 0;
    const ageEnd = convertAgeToDays(simpleRefNum.AgeEnd, simpleRefNum.AgeUnit) || 54750;

    for (let i = 0; i < (formData.refnum?.length || 0); i++) {
      if (excludeIndex !== null && i === excludeIndex) continue;

      const existing = formData.refnum[i];

      if (existing.NumRefType !== newRef.NumRefType) continue;

      if (!sexOverlaps(existing.Sex, newRef.Sex)) continue;

      if (!specimenOverlaps(existing.SpcType, newRef.SpcType)) continue;

      if (ageOverlaps(existing.AgeStart, existing.AgeEnd, ageStart, ageEnd)) {
        return existing;
      }
    }
    return null;
  }

  function validateSimpleRefNum() {
    if (!simpleRefNum.Low && !simpleRefNum.High) {
      return { valid: false, error: 'Please enter at least one value' };
    }

    const low = simpleRefNum.Low !== '' ? parseFloat(simpleRefNum.Low) : null;
    const high = simpleRefNum.High !== '' ? parseFloat(simpleRefNum.High) : null;

    if (low !== null && high !== null && low >= high) {
      return { valid: false, error: 'Low value must be less than high value' };
    }

    if (simpleRefNum.AgeStart !== '' || simpleRefNum.AgeEnd !== '') {
      const ageStart = simpleRefNum.AgeStart !== '' ? parseInt(simpleRefNum.AgeStart) : null;
      const ageEnd = simpleRefNum.AgeEnd !== '' ? parseInt(simpleRefNum.AgeEnd) : null;

      if (ageStart !== null && ageEnd !== null && ageStart >= ageEnd) {
        return { valid: false, error: 'Age start must be less than age end' };
      }
    }

    const newRef = {
      NumRefType: simpleRefNum.NumRefType,
      Sex: simpleRefNum.Sex,
      SpcType: simpleRefNum.SpcType || null,
      AgeStart: convertAgeToDays(simpleRefNum.AgeStart, simpleRefNum.AgeUnit) || 0,
      AgeEnd: convertAgeToDays(simpleRefNum.AgeEnd, simpleRefNum.AgeUnit) || 54750
    };

    const excludeIndex = isEditing ? editingIndex : null;
    const overlap = findOverlappingRange(newRef, excludeIndex);

    if (overlap) {
      return {
        valid: false,
        error: `Overlaps with existing range: ${getNumRefTypeLabel(overlap.NumRefType)}, ${getSexLabel(overlap.Sex)}, ${getAgeDisplay(overlap.AgeStart)}-${getAgeDisplay(overlap.AgeEnd)}`
      };
    }

    return { valid: true };
  }

  function saveRange() {
    const validation = validateSimpleRefNum();
    if (!validation.valid) {
      validationError = validation.error;
      return;
    }

    const newRef = {
      NumRefType: simpleRefNum.NumRefType,
      RangeType: 'RANGE',
      Sex: simpleRefNum.Sex,
      AgeStart: convertAgeToDays(simpleRefNum.AgeStart, simpleRefNum.AgeUnit) || 0,
      AgeEnd: convertAgeToDays(simpleRefNum.AgeEnd, simpleRefNum.AgeUnit) || 54750,
      Low: simpleRefNum.Low !== '' ? parseFloat(simpleRefNum.Low) : null,
      High: simpleRefNum.High !== '' ? parseFloat(simpleRefNum.High) : null,
      LowSign: null,
      HighSign: null,
      SpcType: simpleRefNum.SpcType || null,
      Display: simpleRefNum.Display,
      Flag: simpleRefNum.Flag || null,
      Interpretation: simpleRefNum.Interpretation || null,
      Notes: simpleRefNum.Notes || null
    };

    if (isEditing && editingIndex !== null) {
      const updated = formData.refnum?.map((r, i) => i === editingIndex ? newRef : r) || [];
      formData.refnum = updated;
    } else {
      formData.refnum = [...(formData.refnum || []), newRef];
    }

    resetForm();
    handleFieldChange();
  }

  function editRange(index) {
    const ref = formData.refnum[index];
    simpleRefNum = {
      NumRefType: ref.NumRefType || 'REF',
      Low: ref.Low !== null ? String(ref.Low) : '',
      High: ref.High !== null ? String(ref.High) : '',
      Sex: ref.Sex || '0',
      AgeStart: convertDaysToUnit(ref.AgeStart, 'years'),
      AgeEnd: convertDaysToUnit(ref.AgeEnd, 'years'),
      AgeUnit: 'years',
      SpcType: ref.SpcType || '',
      Display: ref.Display === 1 || ref.Display === '1' || ref.Display === true ? 1 : 0,
      Flag: ref.Flag || '',
      Interpretation: ref.Interpretation || '',
      Notes: ref.Notes || ''
    };
    isEditing = true;
    editingIndex = index;
    validationError = '';
    showAdvanced = true;
  }

  function removeRange(index) {
    const newRanges = formData.refnum?.filter((_, i) => i !== index) || [];
    formData.refnum = newRanges;
    if (isEditing && editingIndex === index) {
      resetForm();
    } else if (isEditing && editingIndex > index) {
      editingIndex--;
    }
    handleFieldChange();
  }

  function getSexLabel(sex) {
    return sexOptions.find(s => s.value === sex)?.label || sex;
  }

  function getNumRefTypeLabel(numRefType) {
    return numRefTypeOptions.find(opt => opt.value === numRefType)?.label || numRefType;
  }

  function getAgeDisplay(ageDays) {
    if (ageDays === null || ageDays === undefined) return '';
    if (ageDays < 30) return `${ageDays}d`;
    if (ageDays < 365) return `${Math.floor(ageDays / 30)}mo`;
    return `${Math.floor(ageDays / 365)}y`;
  }

  function getAgeUnitSuffix() {
    const unit = simpleRefNum.AgeUnit;
    if (unit === 'days') return 'D';
    if (unit === 'weeks') return 'W';
    if (unit === 'months') return 'M';
    if (unit === 'years') return 'Y';
    return 'Y';
  }

  function getDisplayLabel(value) {
    return value === 1 || value === '1' || value === true ? 'Y' : 'N';
  }

  export function validateAll() {
    const seen = new Set();
    for (const range of formData.refnum || []) {
      const key = `${range.NumRefType}-${range.Sex}-${range.AgeStart}-${range.AgeEnd}`;
      if (seen.has(key)) {
        return false;
      }
      seen.add(key);
    }
    return true;
  }
</script>

<div class="space-y-5">
  <h2 class="text-lg font-semibold text-gray-800">Numeric Reference Ranges</h2>

  <!-- Form Section -->
  <div class="bg-base-100 border border-base-300 rounded-lg p-3">
    {#if validationError}
      <div class="alert alert-error alert-sm mb-2">
        <span>{validationError}</span>
      </div>
    {/if}

    <!-- Main Fields -->
    <div class="grid grid-cols-[0.9fr_0.8fr_0.9fr_0.9fr_0.6fr_1fr_1fr_auto] gap-2 items-end">
      <!-- NumRefType -->
      <div class="flex flex-col">
        <label class="text-xs text-gray-600 mb-0.5">Type</label>
        <select class="select select-sm select-bordered w-full" bind:value={simpleRefNum.NumRefType}>
          {#each numRefTypeOptions as opt (opt.value)}
            <option value={opt.value}>{opt.label}</option>
          {/each}
        </select>
      </div>

      <!-- Sex -->
      <div class="flex flex-col">
        <label class="text-xs text-gray-600 mb-0.5">Sex</label>
        <select class="select select-sm select-bordered w-full" bind:value={simpleRefNum.Sex}>
          {#each sexOptions as opt (opt.value)}
            <option value={opt.value}>{opt.label}</option>
          {/each}
        </select>
      </div>

      <!-- Age From with Suffix -->
      <div class="flex flex-col">
        <label class="text-xs text-gray-600 mb-0.5">From</label>
        <label class="input input-sm input-bordered flex items-center gap-1 w-full">
          <input
            type="number"
            class="grow bg-transparent outline-none"
            bind:value={simpleRefNum.AgeStart}
            min="0"
            placeholder="0"
          />
          <span class="text-xs text-gray-500">{getAgeUnitSuffix()}</span>
        </label>
      </div>

      <!-- Age To with Suffix -->
      <div class="flex flex-col">
        <label class="text-xs text-gray-600 mb-0.5">To</label>
        <label class="input input-sm input-bordered flex items-center gap-1 w-full">
          <input
            type="number"
            class="grow bg-transparent outline-none"
            bind:value={simpleRefNum.AgeEnd}
            min="0"
            placeholder="150"
          />
          <span class="text-xs text-gray-500">{getAgeUnitSuffix()}</span>
        </label>
      </div>

      <!-- Age Unit -->
      <div class="flex flex-col">
        <label class="text-xs text-gray-600 mb-0.5">Unit</label>
        <select class="select select-sm select-bordered w-full" bind:value={simpleRefNum.AgeUnit}>
          {#each ageUnits as opt (opt.value)}
            <option value={opt.value}>{opt.label}</option>
          {/each}
        </select>
      </div>

      <!-- Low Value -->
      <div class="flex flex-col">
        <label class="text-xs text-gray-600 mb-0.5">Low</label>
        <input
          type="number"
          step="0.01"
          class="input input-sm input-bordered w-full"
          bind:value={simpleRefNum.Low}
        />
      </div>

      <!-- High Value -->
      <div class="flex flex-col">
        <label class="text-xs text-gray-600 mb-0.5">High</label>
        <input
          type="number"
          step="0.01"
          class="input input-sm input-bordered w-full"
          bind:value={simpleRefNum.High}
        />
      </div>

      <!-- Action Buttons -->
      <div class="flex items-end justify-center">
        <div class="flex gap-1">
          {#if isEditing}
            <button class="btn btn-sm btn-ghost" onclick={resetForm}>
              <X class="w-4 h-4" />
            </button>
          {/if}
          <button class="btn btn-sm btn-primary" onclick={saveRange}>
            <Plus class="w-4 h-4" />
          </button>
        </div>
      </div>
    </div>

    <!-- Toggle Advanced -->
    <div class="mt-2 pt-2 border-t border-base-200">
      <button 
        class="btn btn-xs btn-ghost text-gray-500 flex items-center gap-1" 
        onclick={() => showAdvanced = !showAdvanced}
      >
        {#if showAdvanced}
          <ChevronUp class="w-3 h-3" />
          <span>Hide Advanced</span>
        {:else}
          <ChevronDown class="w-3 h-3" />
          <span>Show Advanced</span>
        {/if}
      </button>
    </div>

    <!-- Advanced Fields (Hidden by default) -->
    {#if showAdvanced}
      <div class="mt-3 pt-3 border-t border-base-200 space-y-2">
        <!-- Row 1: Specimen, Flag, Display, Interpretation -->
        <div class="grid grid-cols-4 gap-2">
          <!-- SpcType -->
          <div class="flex flex-col">
            <label class="text-xs text-gray-600 mb-0.5">Specimen</label>
            <select class="select select-sm select-bordered w-full" bind:value={simpleRefNum.SpcType}>
              <option value="">Select...</option>
              {#each specimenTypes as opt (opt.value)}
                <option value={opt.value}>{opt.label}</option>
              {/each}
            </select>
          </div>

          <!-- Flag -->
          <div class="flex flex-col">
            <label class="text-xs text-gray-600 mb-0.5">Flag</label>
            <input
              type="text"
              class="input input-sm input-bordered w-full"
              bind:value={simpleRefNum.Flag}
              placeholder="H, L, N"
              maxlength="10"
            />
          </div>

          <!-- Display (Y/N Select) -->
          <div class="flex flex-col">
            <label class="text-xs text-gray-600 mb-0.5">Display</label>
            <select class="select select-sm select-bordered w-full" bind:value={simpleRefNum.Display}>
              <option value={1}>Y</option>
              <option value={0}>N</option>
            </select>
          </div>

          <!-- Interpretation -->
          <div class="flex flex-col">
            <label class="text-xs text-gray-600 mb-0.5">Interpretation</label>
            <input
              type="text"
              class="input input-sm input-bordered w-full"
              bind:value={simpleRefNum.Interpretation}
              placeholder="Interpretation..."
            />
          </div>
        </div>

        <!-- Row 2: Notes -->
        <div>
          <label class="text-xs text-gray-600 mb-0.5">Notes</label>
          <textarea
            class="textarea textarea-sm textarea-bordered w-full"
            bind:value={simpleRefNum.Notes}
            placeholder="Additional notes..."
            rows="2"
          ></textarea>
        </div>
      </div>
    {/if}
  </div>

  <!-- List Section - Bottom -->
  <div class="space-y-3">
    <h3 class="text-sm font-medium text-gray-600 uppercase tracking-wide">
      Current Ranges ({formData.refnum?.length || 0})
    </h3>
    
    {#if !formData.refnum || formData.refnum.length === 0}
      <div class="text-center py-8 bg-base-200 rounded-lg">
        <Hash class="w-12 h-12 mx-auto text-gray-400 mb-2" />
        <p class="text-sm text-gray-500">No numeric ranges defined</p>
        <p class="text-xs text-gray-400">Add reference ranges using the form above</p>
      </div>
    {:else}
      <div class="overflow-x-auto border border-base-200 rounded-lg">
        <table class="table table-sm table-compact">
          <thead>
            <tr class="bg-base-200">
              <th class="w-16">Type</th>
              <th class="w-16">Sex</th>
              <th class="w-24">Age</th>
              <th class="w-20">Specimen</th>
              <th class="w-16">Flag</th>
              <th class="w-12">Disp</th>
              <th class="w-24">Range</th>
              <th class="w-24 text-center">Edit</th>
              <th class="w-12 text-center">Del</th>
            </tr>
          </thead>
          <tbody>
            {#each formData.refnum as ref, idx (idx)}
              <tr class="hover:bg-base-100">
                <td class="text-xs">{getNumRefTypeLabel(ref.NumRefType)}</td>
                <td>{getSexLabel(ref.Sex)}</td>
                <td class="text-sm">{getAgeDisplay(ref.AgeStart)}-{getAgeDisplay(ref.AgeEnd)}</td>
                <td class="text-sm">{ref.SpcType || '—'}</td>
                <td class="text-sm">{ref.Flag || '—'}</td>
                <td class="text-sm">{getDisplayLabel(ref.Display)}</td>
                <td class="font-mono text-sm">
                  {ref.Low !== null && ref.Low !== '' ? ref.Low : '—'} 
                  - 
                  {ref.High !== null && ref.High !== '' ? ref.High : '—'}
                </td>
                <td class="text-center">
                  <button
                    class="btn btn-ghost btn-xs"
                    onclick={() => editRange(idx)}
                    title="Edit Range"
                  >
                    <Edit2 class="w-3 h-3" />
                  </button>
                </td>
                <td class="text-center">
                  <button
                    class="btn btn-ghost btn-xs text-error"
                    onclick={() => removeRange(idx)}
                    title="Remove Range"
                  >
                    <Trash2 class="w-3 h-3" />
                  </button>
                </td>
              </tr>
            {/each}
          </tbody>
        </table>
      </div>
    {/if}
  </div>
</div>
