<script>
  import { onMount } from 'svelte';
  import Modal from '$lib/components/Modal.svelte';
  import { ORDER_STATUS, ORDER_PRIORITY } from '$lib/api/orders.js';
  import { fetchPatients } from '$lib/api/patients.js';
  import { fetchTests } from '$lib/api/tests.js';
  import { fetchVisitsByPatient } from '$lib/api/visits.js';
  import { fetchDisciplines } from '$lib/api/organization.js';
  import { success as toastSuccess, error as toastError } from '$lib/utils/toast.js';
  import { User, Building2, Hash, FileText, AlertCircle, Plus, X, Search, Beaker, Filter, ChevronRight, ChevronLeft, Trash2 } from 'lucide-svelte';

  /** @type {{ 
   *   open: boolean,
   *   order: Object | null,
   *   patient: Object | null,
   *   loading: boolean,
   *   onSave: () => void,
   *   onCancel: () => void
   * }} */
  let { 
    open = $bindable(false),
    order = null,
    patient = null,
    loading = false,
    onSave,
    onCancel
  } = $props();

  // Form state
  let formData = $state({
    OrderID: '',
    InternalPID: '',
    PatVisitID: '',
    SiteID: 1,
    PlacerID: '',
    Priority: 'R',
    ReqApp: '',
    Comment: '',
    Tests: []
  });

  let formLoading = $state(false);
  let formError = $state('');
  let patientSearchQuery = $state('');
  let patientSearchResults = $state([]);
  let showPatientSearch = $state(false);
  let selectedPatient = $state(null);
  let patientVisits = $state([]);
  let visitsLoading = $state(false);
  let testSearchQuery = $state('');
  let testSearchResults = $state([]);
  let showTestSearch = $state(false);
  let isInitialized = $state(false);

  // Dual-column test selection state
  let availableTests = $state([]);
  let disciplines = $state([]);
  let selectedDiscipline = $state('');
  let testsLoading = $state(false);
  let testsPage = $state(1);
  let testsHasMore = $state(false);
  let testsPerPage = $state(100);

  // Reset form when modal opens (only when transitioning from closed to open)
  $effect(() => {
    if (open && !isInitialized) {
      isInitialized = true;

      // Load disciplines and initial tests for dual-column layout
      loadDisciplines();
      loadInitialTests();

      if (order) {
        // Edit mode - populate form
        formData = {
          OrderID: order.OrderID || '',
          InternalPID: order.InternalPID || '',
          PatVisitID: order.PatVisitID || '',
          SiteID: order.SiteID || 1,
          PlacerID: order.PlacerID || '',
          Priority: order.Priority || 'R',
          ReqApp: order.ReqApp || '',
          Comment: order.Comment || '',
          Tests: order.Tests ? [...order.Tests] : []
        };
        selectedPatient = {
          InternalPID: order.InternalPID,
          PatientID: order.PatientID,
          FullName: order.PatientName
        };
      } else {
        // Create mode - reset form
        formData = {
          OrderID: '',
          InternalPID: '',
          PatVisitID: '',
          SiteID: 1,
          PlacerID: '',
          Priority: 'R',
          ReqApp: '',
          Comment: '',
          Tests: []
        };

        // If patient prop is provided, auto-select it
        if (patient) {
          selectedPatient = patient;
          formData.InternalPID = patient.InternalPID;
          loadPatientVisits(patient.InternalPID);
        } else {
          selectedPatient = null;
        }

        patientSearchQuery = '';
        patientSearchResults = [];
      }
      formError = '';
      showPatientSearch = false;
      testSearchQuery = '';
      selectedDiscipline = '';
      testsPage = 1;
      testsHasMore = false;
    } else if (!open) {
      // Reset initialization flag when modal closes
      isInitialized = false;
    }
  });

  async function searchPatients() {
    if (!patientSearchQuery.trim()) return;
    
    formLoading = true;
    try {
      const response = await fetchPatients({ 
        Name: patientSearchQuery.trim(),
        perPage: 10 
      });
      patientSearchResults = response.data || [];
      showPatientSearch = true;
    } catch (err) {
      toastError('Failed to search patients');
      patientSearchResults = [];
    } finally {
      formLoading = false;
    }
  }

  function selectPatient(patient) {
    selectedPatient = patient;
    formData.InternalPID = patient.InternalPID;
    formData.PatVisitID = ''; // Reset visit when patient changes
    showPatientSearch = false;
    patientSearchQuery = '';
    patientSearchResults = [];
    loadPatientVisits(patient.InternalPID);
  }

  async function loadPatientVisits(internalPID) {
    if (!internalPID) {
      patientVisits = [];
      return;
    }
    
    visitsLoading = true;
    try {
      const response = await fetchVisitsByPatient(internalPID);
      patientVisits = response.data || [];
    } catch (err) {
      console.error('Failed to load patient visits:', err);
      patientVisits = [];
    } finally {
      visitsLoading = false;
    }
  }

  async function loadDisciplines() {
    try {
      const response = await fetchDisciplines();
      disciplines = response.data || [];
    } catch (err) {
      console.error('Failed to load disciplines:', err);
      disciplines = [];
    }
  }

  async function loadInitialTests() {
    testsLoading = true;
    try {
      const params = {
        perPage: testsPerPage,
        page: 1,
        Requestable: 1
      };

      if (selectedDiscipline) {
        params.DisciplineID = selectedDiscipline;
      }

      const response = await fetchTests(params);
      availableTests = response.data || [];
      testsPage = 1;
      const pagination = response.pagination || {};
      testsHasMore = pagination.currentPage < pagination.lastPage;
    } catch (err) {
      console.error('Failed to load tests:', err);
      availableTests = [];
      testsHasMore = false;
    } finally {
      testsLoading = false;
    }
  }

  async function loadMoreTests() {
    if (!testsHasMore || testsLoading) return;
    await searchTests(true);
  }

  async function searchTests(loadMore = false) {
    if (!loadMore && !testSearchQuery.trim()) {
      await loadInitialTests();
      return;
    }

    testsLoading = true;
    const currentPage = loadMore ? testsPage + 1 : 1;

    try {
      const params = {
        perPage: testsPerPage,
        page: currentPage,
        Requestable: 1
      };

      if (testSearchQuery.trim()) {
        params.search = testSearchQuery.trim();
      }

      if (selectedDiscipline) {
        params.DisciplineID = selectedDiscipline;
      }

      const response = await fetchTests(params);
      const newTests = response.data || [];
      const pagination = response.pagination || {};

      if (loadMore) {
        availableTests = [...availableTests, ...newTests];
        testsPage = currentPage;
      } else {
        availableTests = newTests;
        testsPage = 1;
      }

      testsHasMore = pagination.currentPage < pagination.lastPage;
    } catch (err) {
      toastError('Failed to search tests');
      if (!loadMore) {
        availableTests = [];
      }
    } finally {
      testsLoading = false;
    }
  }

  function addTest(test) {
    // Check for duplicates
    if (formData.Tests.some(t => t.TestSiteID === test.TestSiteID)) {
      return;
    }
    
    formData.Tests = [...formData.Tests, {
      TestSiteID: test.TestSiteID,
      TestSiteCode: test.TestSiteCode,
      TestSiteName: test.TestSiteName,
      DisciplineID: test.DisciplineID
    }];
    formError = '';
  }

  function removeTest(testSiteId) {
    formData.Tests = formData.Tests.filter(t => t.TestSiteID !== testSiteId);
  }

  function addAllTests() {
    const newTests = availableTests.filter(test => 
      !formData.Tests.some(t => t.TestSiteID === test.TestSiteID)
    );
    
    formData.Tests = [...formData.Tests, ...newTests.map(test => ({
      TestSiteID: test.TestSiteID,
      TestSiteCode: test.TestSiteCode,
      TestSiteName: test.TestSiteName,
      DisciplineID: test.DisciplineID
    }))];
    formError = '';
  }

  function removeAllTests() {
    formData.Tests = [];
  }

  function isTestSelected(testSiteId) {
    return formData.Tests.some(t => t.TestSiteID === testSiteId);
  }

  function toggleTest(test) {
    if (isTestSelected(test.TestSiteID)) {
      removeTest(test.TestSiteID);
    } else {
      addTest(test);
    }
  }

  async function handleDisciplineChange() {
    // Don't clear search query - apply filter with existing search
    await searchTests(false);
  }

  function validateForm() {
    formError = '';
    
    if (!formData.InternalPID) {
      formError = 'Please select a patient';
      return false;
    }
    
    if (formData.Tests.length === 0) {
      formError = 'Please add at least one test';
      return false;
    }
    
    return true;
  }

  async function handleSubmit() {
    if (!validateForm()) return;
    
    formLoading = true;
    try {
      // Prepare data for API
      const submitData = {
        ...formData,
        InternalPID: parseInt(formData.InternalPID),
        SiteID: parseInt(formData.SiteID) || 1
      };
      
      if (formData.PatVisitID) {
        submitData.PatVisitID = parseInt(formData.PatVisitID);
      }
      
      onSave(submitData);
    } catch (err) {
      formError = err.message || 'Failed to save order';
    } finally {
      formLoading = false;
    }
  }

  function handleClose() {
    onCancel();
  }

  const priorityOptions = Object.values(ORDER_PRIORITY);

  function getDisciplineName(disciplineId) {
    const discipline = disciplines.find(d => d.DisciplineID === disciplineId);
    return discipline ? discipline.DisciplineCode : '';
  }
</script>

<div class="tall-modal">
  <Modal 
    bind:open 
    title={order ? 'Edit Order' : 'Create Order'} 
    size="xl"
    onClose={handleClose}
  >
  <div class="space-y-4">
    <!-- Error Alert -->
    {#if formError}
      <div class="alert alert-error alert-sm">
        <AlertCircle class="w-4 h-4" />
        <span class="text-sm">{formError}</span>
      </div>
    {/if}

    <!-- Two Column Layout -->
    <div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
      
      <!-- LEFT COLUMN: Order Information -->
      <div class="space-y-4">
        
        <!-- Patient Card -->
        <div class="bg-base-200 rounded-lg p-4">
          <h4 class="text-sm font-semibold mb-3 flex items-center gap-2 text-gray-700">
            <User class="w-4 h-4" />
            Patient <span class="text-error">*</span>
          </h4>
          
          {#if selectedPatient}
            <div class="bg-base-100 rounded-lg p-3 border border-base-300">
              <div class="flex items-center justify-between">
                <div>
                  <p class="font-semibold text-sm">{selectedPatient.FullName || selectedPatient.PatientID}</p>
                  <p class="text-xs text-gray-500">ID: {selectedPatient.PatientID}</p>
                  <p class="text-xs text-gray-500">Internal PID: {selectedPatient.InternalPID}</p>
                </div>
                {#if !order && !patient}
                  <button 
                    class="btn btn-ghost btn-xs btn-square"
                    onclick={() => { selectedPatient = null; formData.InternalPID = ''; formData.PatVisitID = ''; patientVisits = []; }}
                  >
                    <X class="w-4 h-4" />
                  </button>
                {/if}
              </div>
              {#if patientVisits.length > 0}
                <div class="mt-2 pt-2 border-t border-base-200">
                  <p class="text-xs text-gray-500">
                    {patientVisits.length} visit{patientVisits.length === 1 ? '' : 's'} available
                  </p>
                </div>
              {/if}
            </div>
          {:else}
            <div class="space-y-2">
              <div class="flex gap-2">
                <div class="input input-sm input-bordered flex items-center gap-2 flex-1 focus-within:input-primary">
                  <Search class="w-4 h-4 text-gray-400" />
                  <input
                    type="text"
                    class="grow bg-transparent outline-none"
                    placeholder="Search patient by name..."
                    bind:value={patientSearchQuery}
                    onkeydown={(e) => e.key === 'Enter' && searchPatients()}
                  />
                </div>
                <button 
                  class="btn btn-primary btn-sm"
                  onclick={searchPatients}
                  disabled={formLoading || !patientSearchQuery.trim()}
                >
                  {#if formLoading}
                    <span class="loading loading-spinner loading-sm"></span>
                  {:else}
                    <Search class="w-4 h-4" />
                  {/if}
                </button>
              </div>
              
              {#if showPatientSearch && patientSearchResults.length > 0}
                <div class="border border-base-300 rounded-lg max-h-40 overflow-auto bg-base-100">
                  {#each patientSearchResults as patient (patient.InternalPID)}
                    <button
                      class="w-full text-left p-2 hover:bg-base-200 border-b border-base-200 last:border-b-0"
                      onclick={() => selectPatient(patient)}
                    >
                      <p class="text-sm font-medium">{patient.FullName || patient.PatientID}</p>
                      <p class="text-xs text-gray-500">ID: {patient.PatientID}</p>
                    </button>
                  {/each}
                </div>
              {:else if showPatientSearch}
                <p class="text-sm text-gray-500">No patients found</p>
              {/if}
            </div>
          {/if}
        </div>

        <!-- Order Details Card -->
        <div class="bg-base-200 rounded-lg p-4">
          <h4 class="text-sm font-semibold mb-3 flex items-center gap-2 text-gray-700">
            <FileText class="w-4 h-4" />
            Order Details
          </h4>
          
          <div class="space-y-3">
            <!-- Priority & Site ID -->
            <div class="grid grid-cols-2 gap-3">
              <div class="form-control">
                <label class="label py-0.5" for="orderPriority">
                  <span class="label-text text-xs text-gray-500">Priority</span>
                </label>
                <select
                  id="orderPriority"
                  class="select select-sm select-bordered w-full focus:select-primary"
                  bind:value={formData.Priority}
                >
                  {#each priorityOptions as priority (priority.code)}
                    <option value={priority.code}>{priority.label}</option>
                  {/each}
                </select>
              </div>

              <div class="form-control">
                <label class="label py-0.5" for="orderSiteId">
                  <span class="label-text text-xs text-gray-500">Site ID</span>
                </label>
                <input
                  id="orderSiteId"
                  type="number"
                  class="input input-sm input-bordered w-full focus:input-primary"
                  bind:value={formData.SiteID}
                />
              </div>
            </div>

            <!-- Visit ID & Placer ID -->
            <div class="grid grid-cols-2 gap-3">
              <div class="form-control">
                <label class="label py-0.5" for="orderVisitId">
                  <span class="label-text text-xs text-gray-500">Visit</span>
                </label>
                <select
                  id="orderVisitId"
                  class="select select-sm select-bordered w-full focus:select-primary"
                  bind:value={formData.PatVisitID}
                  disabled={!selectedPatient || visitsLoading || patientVisits.length === 0}
                >
                  <option value="">Select visit...</option>
                  {#if visitsLoading}
                    <option value="" disabled>Loading visits...</option>
                  {:else if patientVisits.length === 0}
                    <option value="" disabled>No visits found</option>
                  {:else}
                    {#each patientVisits as visit (visit.InternalPVID)}
                      <option value={visit.InternalPVID}>
                        {visit.PVID} - {visit.PVACreateDate ? new Date(visit.PVACreateDate).toLocaleDateString() : 'N/A'}{visit.ADTCode ? ` (${visit.ADTCode})` : ''}
                      </option>
                    {/each}
                  {/if}
                </select>
              </div>

              <div class="form-control">
                <label class="label py-0.5" for="orderPlacerId">
                  <span class="label-text text-xs text-gray-500">Placer ID</span>
                </label>
                <input
                  id="orderPlacerId"
                  type="text"
                  class="input input-sm input-bordered w-full focus:input-primary"
                  bind:value={formData.PlacerID}
                  placeholder="Optional"
                />
              </div>
            </div>

            <!-- Requesting App -->
            <div class="form-control">
              <label class="label py-0.5" for="orderReqApp">
                <span class="label-text text-xs text-gray-500">Requesting Application</span>
              </label>
              <div class="input input-sm input-bordered flex items-center gap-2 focus-within:input-primary">
                <Building2 class="w-3.5 h-3.5 text-gray-400" />
                <input
                  id="orderReqApp"
                  type="text"
                  class="grow bg-transparent outline-none"
                  bind:value={formData.ReqApp}
                  placeholder="Optional"
                />
              </div>
            </div>

            <!-- Comment -->
            <div class="form-control">
              <label class="label py-0.5" for="orderComment">
                <span class="label-text text-xs text-gray-500">Comment</span>
              </label>
              <textarea
                id="orderComment"
                class="textarea textarea-bordered textarea-sm w-full focus:textarea-primary"
                bind:value={formData.Comment}
                rows="2"
                placeholder="Optional comments..."
              ></textarea>
            </div>
          </div>
        </div>
      </div>

      <!-- RIGHT COLUMN: Tests (Dual-Column Transfer Layout) -->
      <div class="bg-base-200 rounded-lg p-4 flex flex-col h-full">
        <h4 class="text-sm font-semibold mb-3 flex items-center gap-2 text-gray-700">
          <Beaker class="w-4 h-4" />
          Tests <span class="text-error">*</span>
          {#if formData.Tests.length > 0}
            <span class="badge badge-sm badge-primary ml-auto">{formData.Tests.length}</span>
          {/if}
        </h4>

        <!-- Dual-Column Layout -->
        <div class="grid grid-cols-2 gap-3">
          <!-- LEFT COLUMN: Available Tests -->
          <div class="bg-base-100 rounded-lg border border-base-300 flex flex-col">
            <!-- Header -->
            <div class="p-2 border-b border-base-300 bg-base-200/50 rounded-t-lg">
              <div class="flex items-center justify-between mb-2">
                <span class="text-xs font-medium text-gray-600">Available Tests</span>
                <span class="text-xs text-gray-400">{availableTests.length}</span>
              </div>
              <!-- Search and Filter -->
              <div class="space-y-1.5">
                <div class="input input-xs input-bordered flex items-center gap-2 focus-within:input-primary bg-base-100">
                  <Search class="w-3 h-3 text-gray-400" />
                  <input
                    type="text"
                    class="grow bg-transparent outline-none text-xs"
                    placeholder="Press Enter to search..."
                    bind:value={testSearchQuery}
                    onkeydown={(e) => e.key === 'Enter' && searchTests()}
                  />
                </div>
                <div class="flex gap-1">
                  <select
                    class="select select-xs select-bordered flex-1 text-xs"
                    bind:value={selectedDiscipline}
                    onchange={handleDisciplineChange}
                  >
                    <option value="">All Disciplines</option>
                    {#each disciplines as discipline (discipline.DisciplineID)}
                      <option value={discipline.DisciplineID}>{discipline.DisciplineCode}</option>
                    {/each}
                  </select>
                  <button
                    class="btn btn-xs btn-ghost"
                    onclick={() => searchTests()}
                    disabled={testsLoading}
                    title="Search"
                  >
                    {#if testsLoading}
                      <span class="loading loading-spinner loading-xs"></span>
                    {:else}
                      <Search class="w-3 h-3" />
                    {/if}
                  </button>
                </div>
              </div>
            </div>

            <!-- Available Tests List - With Scroll -->
            <div class="p-1.5 max-h-[300px] overflow-y-auto">
              {#if testsLoading && availableTests.length === 0}
                <div class="flex items-center justify-center py-8">
                  <span class="loading loading-spinner loading-sm"></span>
                </div>
              {:else if availableTests.length === 0}
                <div class="flex flex-col items-center justify-center text-gray-400 py-8">
                  <Search class="w-6 h-6 mb-1 opacity-50" />
                  <p class="text-xs">No tests found</p>
                </div>
              {:else}
                <div class="space-y-0.5">
                  {#each availableTests as test (test.TestSiteID)}
                    {@const isSelected = isTestSelected(test.TestSiteID)}
                    <button
                      class="w-full text-left p-1.5 rounded hover:bg-base-200 border transition-all flex items-center gap-2 group"
                      class:bg-base-200="{!isSelected}"
                      class:border-transparent="{!isSelected}"
                      class:border-base-300="{!isSelected}"
                      class:bg-primary-50="{isSelected}"
                      class:border-primary="{isSelected}"
                      class:border-opacity-30="{isSelected}"
                      onclick={() => toggleTest(test)}
                    >
                      <div class="flex-1 min-w-0">
                        <div class="flex items-center gap-1.5">
                          {#if test.TestSiteCode}
                            <span class="text-xs font-mono bg-primary/10 text-primary px-1 py-0 rounded shrink-0">{test.TestSiteCode}</span>
                          {:else}
                            <span class="text-xs font-mono bg-base-200 px-1 py-0 rounded shrink-0">ID:{test.TestSiteID}</span>
                          {/if}
                          {#if test.DisciplineID}
                            <span class="text-[10px] text-gray-400 shrink-0">{getDisciplineName(test.DisciplineID)}</span>
                          {/if}
                        </div>
                        <p class="text-xs truncate text-gray-600 mt-0.5">{test.TestSiteName || `Test #${test.TestSiteID}`}</p>
                      </div>
                      {#if isTestSelected(test.TestSiteID)}
                        <ChevronRight class="w-3.5 h-3.5 text-primary shrink-0" />
                      {:else}
                        <Plus class="w-3.5 h-3.5 text-gray-400 group-hover:text-primary shrink-0" />
                      {/if}
                    </button>
                  {/each}
                </div>

                <!-- Show More Button -->
                {#if testsHasMore}
                  <div class="mt-2 pt-2 border-t border-base-200">
                    <button
                      class="btn btn-xs btn-ghost btn-block text-xs"
                      onclick={loadMoreTests}
                      disabled={testsLoading}
                    >
                      {#if testsLoading}
                        <span class="loading loading-spinner loading-xs"></span>
                        Loading...
                      {:else}
                        Show more tests
                      {/if}
                    </button>
                  </div>
                {/if}
              {/if}
            </div>
          </div>

          <!-- RIGHT COLUMN: Selected Tests -->
          <div class="bg-base-100 rounded-lg border border-base-300 flex flex-col">
            <!-- Header -->
            <div class="p-2 border-b border-base-300 bg-base-200/50 rounded-t-lg">
              <div class="flex items-center justify-between">
                <span class="text-xs font-medium text-gray-600">Selected</span>
                <span class="badge badge-xs badge-primary">{formData.Tests.length}</span>
              </div>
            </div>

            <!-- Selected Tests List - With Scroll -->
            <div class="p-1.5 max-h-[300px] overflow-y-auto flex-1">
              {#if formData.Tests.length === 0}
                <div class="flex flex-col items-center justify-center text-gray-400 py-8">
                  <Beaker class="w-6 h-6 mb-1 opacity-50" />
                  <p class="text-xs">No tests selected</p>
                  <p class="text-[10px] mt-0.5 text-gray-300">Click tests to add</p>
                </div>
              {:else}
                <div class="space-y-0.5">
                  {#each formData.Tests as test, index (test.TestSiteID)}
                    <div
                      class="flex items-center gap-2 p-1.5 bg-primary/5 rounded border border-primary/20"
                    >
                      <div class="flex-1 min-w-0">
                        <div class="flex items-center gap-1.5">
                          {#if test.TestSiteCode}
                            <span class="text-xs font-mono bg-primary/10 text-primary px-1 py-0 rounded shrink-0">{test.TestSiteCode}</span>
                          {:else}
                            <span class="text-xs font-mono bg-base-200 px-1 py-0 rounded shrink-0">ID:{test.TestSiteID}</span>
                          {/if}
                          <span class="text-[10px] text-gray-400">#{index + 1}</span>
                        </div>
                        <p class="text-xs truncate text-gray-700 mt-0.5">{test.TestSiteName || `Test #${test.TestSiteID}`}</p>
                      </div>
                      <button
                        class="btn btn-ghost btn-xs btn-square text-error hover:bg-error/10 shrink-0 p-0.5 h-auto min-h-0"
                        onclick={() => removeTest(test.TestSiteID)}
                        title="Remove"
                      >
                        <X class="w-3 h-3" />
                      </button>
                    </div>
                  {/each}
                </div>
              {/if}
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>

  {#snippet footer()}
    <button 
      class="btn btn-ghost btn-sm" 
      onclick={handleClose}
      disabled={formLoading}
    >
      Cancel
    </button>
    <button 
      class="btn btn-primary btn-sm" 
      onclick={handleSubmit}
      disabled={formLoading || !selectedPatient}
    >
      {#if formLoading}
        <span class="loading loading-spinner loading-sm mr-1"></span>
      {/if}
      {order ? 'Update Order' : 'Create Order'}
    </button>
  {/snippet}
</Modal>
</div>

<style>
  .tall-modal :global(.modal-box) {
    max-height: 90vh;
  }
</style>
