<script>
  import { onMount } from 'svelte';
  import { fetchTests, fetchTest, createTest, updateTest, deleteTest } from '$lib/api/tests.js';
  import { fetchDisciplines, fetchDepartments } from '$lib/api/organization.js';
  import { success as toastSuccess, error as toastError } from '$lib/utils/toast.js';
  import DataTable from '$lib/components/DataTable.svelte';
  import Modal from '$lib/components/Modal.svelte';
  import TestFormModal from './test-modal/TestFormModal.svelte';
  import TestTypePickerModal from './test-modal/modals/TestTypePickerModal.svelte';
  import { Plus, Edit2, Trash2, ArrowLeft, Search, Microscope, Variable, Calculator, Box, Layers, Loader2, Users, ChevronLeft, ChevronRight, Hash, Type } from 'lucide-svelte';

  // Pagination and search state
  let loading = $state(false);
  let tests = $state([]);
  let disciplines = $state([]);
  let departments = $state([]);
  let searchCode = $state('');
  let searchName = $state('');
  let currentPage = $state(1);
  let perPage = $state(25);
  let totalItems = $state(0);
  let totalPages = $state(0);
  let hasMore = $state(false);
  let modalOpen = $state(false);
  let modalMode = $state('create');
  let selectedTestId = $state(null);
  let selectedTestType = $state('TEST');
  let deleteConfirmOpen = $state(false);
  let deleteItem = $state(null);
  let deleting = $state(false);
  let testTypePickerOpen = $state(false);
  let searchDebounceTimer = $state(null);

  const testTypeConfig = {
    TEST: { label: 'Test', badgeClass: 'badge-primary', icon: Microscope, color: '#0066CC', bgColor: '#E6F2FF' },
    PARAM: { label: 'Parameter', badgeClass: 'badge-secondary', icon: Variable, color: '#3399FF', bgColor: '#F0F8FF' },
    CALC: { label: 'Calculated', badgeClass: 'badge-accent', icon: Calculator, color: '#9933CC', bgColor: '#F5E6FF' },
    GROUP: { label: 'Panel', badgeClass: 'badge-info', icon: Box, color: '#00AA44', bgColor: '#E6F9EE' },
    TITLE: { label: 'Header', badgeClass: 'badge-ghost', icon: Layers, color: '#666666', bgColor: '#F5F5F5' }
  };

  const columns = [
    { key: 'TestSiteCode', label: 'Code', class: 'font-medium w-24' },
    { key: 'TestSiteName', label: 'Name', class: 'min-w-[200px]' },
    { key: 'TestType', label: 'Type', class: 'w-28' },
    { key: 'DisciplineName', label: 'Discipline', class: 'w-32' },
    { key: 'DepartmentName', label: 'Department', class: 'w-32' },
    { key: 'Visible', label: 'Visible', class: 'w-24 text-center' },
    { key: 'actions', label: 'Actions', class: 'w-24 text-center' }
  ];

  // Client-side filter for already loaded data (secondary filter)
  const filteredTests = $derived.by(() => {
    return tests;
  });

  function getSearchParams() {
    const params = { page: currentPage, perPage };
    const testCode = searchCode.trim();
    const testName = searchName.trim();
    if (testCode) {
      params.TestSiteCode = testCode;
    }
    if (testName) {
      params.TestSiteName = testName;
    }
    return params;
  }

  function handleSearch() {
    if (searchDebounceTimer) {
      clearTimeout(searchDebounceTimer);
    }
    searchDebounceTimer = setTimeout(() => {
      currentPage = 1;
      loadTests();
    }, 300);
  }

  onMount(async () => {
    await Promise.all([loadDisciplines(), loadDepartments()]);
  });

  function handleSearchTypeChange(newType) {
    searchType = newType;
  }

  function clearSearch() {
    searchCode = '';
    searchName = '';
    currentPage = 1;
    tests = [];
    totalItems = 0;
    totalPages = 0;
    hasMore = false;
  }

  function hasSearchQuery() {
    return searchCode.trim() || searchName.trim();
  }

  async function loadTests(reset = false) {
    if (reset) {
      currentPage = 1;
    }
    loading = true;
    try {
      const params = getSearchParams();
      const response = await fetchTests(params);
      if (response.data && Array.isArray(response.data.data)) {
        tests = response.data.data.filter(t => t.IsActive !== '0' && t.IsActive !== 0);
        totalItems = response.data.total || 0;
        totalPages = Math.ceil(totalItems / perPage);
        hasMore = currentPage < totalPages;
      } else if (Array.isArray(response.data)) {
        // Fallback for old API format
        tests = response.data.filter(t => t.IsActive !== '0' && t.IsActive !== 0);
        totalItems = tests.length;
        totalPages = 1;
        hasMore = false;
      } else {
        tests = [];
        totalItems = 0;
        totalPages = 0;
        hasMore = false;
      }
    } catch (err) {
      toastError(err.message || 'Failed to load tests');
      tests = [];
      totalItems = 0;
      totalPages = 0;
      hasMore = false;
    } finally {
      loading = false;
    }
  }

  async function loadNextPage() {
    if (currentPage < totalPages && !loading) {
      currentPage++;
      loading = true;
      try {
        const params = getSearchParams();
        const response = await fetchTests(params);
        if (response.data && Array.isArray(response.data.data)) {
          const newTests = response.data.data.filter(t => t.IsActive !== '0' && t.IsActive !== 0);
          tests = [...tests, ...newTests];
          totalItems = response.data.total || 0;
          totalPages = Math.ceil(totalItems / perPage);
          hasMore = currentPage < totalPages;
        }
      } catch (err) {
        toastError(err.message || 'Failed to load more tests');
        currentPage--;
      } finally {
        loading = false;
      }
    }
  }

  function goToPage(page) {
    if (page >= 1 && page <= totalPages && page !== currentPage) {
      currentPage = page;
      loadTests();
    }
  }

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

  async function loadDepartments() {
    try {
      const response = await fetchDepartments();
      departments = Array.isArray(response.data) ? response.data : [];
    } catch (err) {
      console.error('Failed to load departments:', err);
      departments = [];
    }
  }

  function openCreateModal() {
    testTypePickerOpen = true;
  }

  function handleTestTypeSelect(type) {
    selectedTestType = type;
    modalMode = 'create';
    selectedTestId = null;
    modalOpen = true;
  }

  async function openEditModal(row) {
    modalMode = 'edit';
    selectedTestId = row.TestSiteID;
    modalOpen = true;
  }

  function getTestTypeConfig(type) {
    return testTypeConfig[type] || testTypeConfig.TEST;
  }

  function confirmDelete(row) {
    deleteItem = row;
    deleteConfirmOpen = true;
  }

  async function handleDelete() {
    deleting = true;
    try {
      await deleteTest(deleteItem.TestSiteID);
      toastSuccess('Test deleted successfully');
      deleteConfirmOpen = false;
      await loadTests();
    } catch (err) {
      toastError(err.message || 'Failed to delete test');
    } finally {
      deleting = false;
    }
  }
</script>

<div class="p-4">
  <div class="flex items-center gap-4 mb-6">
    <a href="/master-data" class="btn btn-ghost btn-circle">
      <ArrowLeft class="w-5 h-5" />
    </a>
    <div class="flex-1">
      <h1 class="text-xl font-bold text-gray-800">Test Definitions</h1>
      <p class="text-sm text-gray-600">Manage laboratory tests, panels, and calculated values</p>
    </div>
    <button class="btn btn-primary" onclick={openCreateModal}>
      <Plus class="w-4 h-4 mr-2" />
      Add Test
    </button>
  </div>

  <div class="mb-4 flex flex-col sm:flex-row gap-3 items-start sm:items-center">
    <div class="flex-1 max-w-2xl flex gap-2">
      <label class="input input-sm input-bordered w-1/2 flex items-center gap-2">
        <Hash class="w-4 h-4 text-gray-400" />
        <input
          type="text"
          class="grow"
          placeholder="Test code..."
          bind:value={searchCode}
          onkeydown={(e) => e.key === 'Enter' && handleSearch()}
        />
        {#if searchCode}
          <button 
            class="btn btn-ghost btn-xs btn-circle"
            onclick={() => searchCode = ''}
          >
            ×
          </button>
        {/if}
      </label>
      <label class="input input-sm input-bordered w-1/2 flex items-center gap-2">
        <Type class="w-4 h-4 text-gray-400" />
        <input
          type="text"
          class="grow"
          placeholder="Test name..."
          bind:value={searchName}
          onkeydown={(e) => e.key === 'Enter' && handleSearch()}
        />
        {#if searchName}
          <button 
            class="btn btn-ghost btn-xs btn-circle"
            onclick={() => searchName = ''}
          >
            ×
          </button>
        {/if}
      </label>
      <button 
        class="btn btn-primary btn-sm"
        onclick={handleSearch}
        disabled={loading}
      >
        {#if loading}
          <Loader2 class="w-4 h-4 animate-spin mr-2" />
        {:else}
          <Search class="w-4 h-4 mr-2" />
        {/if}
        Search
      </button>
    </div>
    <div class="text-sm text-gray-600">
      {totalItems} total
    </div>
  </div>

  <div class="bg-base-100 rounded-lg shadow border border-base-200">
    {#if loading}
      <div class="flex items-center justify-center py-16">
        <Loader2 class="w-8 h-8 animate-spin text-primary mr-3" />
        <span class="text-gray-600">Loading tests...</span>
      </div>
    {:else if filteredTests.length === 0}
      <div class="flex flex-col items-center justify-center py-16 px-4">
        <div class="bg-base-200 rounded-full p-6 mb-4">
          <Microscope class="w-12 h-12 text-gray-400" />
        </div>
        <h3 class="text-base font-semibold text-gray-700 mb-1">
          {hasSearchQuery() ? 'No tests found' : 'Search for tests'}
        </h3>
        <p class="text-xs text-gray-500 text-center max-w-sm mb-4">
          {hasSearchQuery() 
            ? `No tests matching your search. Try a different search term.` 
            : 'Enter a search term above and click Search to find laboratory tests.'}
        </p>
      </div>
    {:else}
      <DataTable
        {columns}
        data={filteredTests}
        loading={loading}
        emptyMessage={hasSearchQuery() ? 'No tests found matching your search' : 'No tests yet'}
        hover={true}
        bordered={false}
      >
        {#snippet cell({ column, row, value })}
          {@const typeConfig = getTestTypeConfig(row.TestType)}
          {@const IconComponent = typeConfig.icon}
          {#if column.key === 'TestType'}
            <span class="badge gap-1" style="background-color: {typeConfig.bgColor}; color: {typeConfig.color}; border-color: {typeConfig.color};">
              <IconComponent class="w-3 h-3" />
              {typeConfig.label}
            </span>
          {:else if column.key === 'Visible'}
            <div class="flex justify-center gap-2">
              <span class="badge {row.VisibleScr === '1' || row.VisibleScr === 1 ? 'badge-success' : 'badge-ghost'} badge-sm">S</span>
              <span class="badge {row.VisibleRpt === '1' || row.VisibleRpt === 1 ? 'badge-success' : 'badge-ghost'} badge-sm">R</span>
            </div>
          {:else if column.key === 'actions'}
            <div class="flex justify-center gap-2">
              <button class="btn btn-sm btn-ghost" onclick={() => openEditModal(row)} title="Edit test">
                <Edit2 class="w-4 h-4" />
              </button>
              <button class="btn btn-sm btn-ghost text-error" onclick={() => confirmDelete(row)} title="Delete test">
                <Trash2 class="w-4 h-4" />
              </button>
            </div>
          {:else}
            {value || '-'}
          {/if}
        {/snippet}
      </DataTable>

      <!-- Pagination Controls -->
      {#if totalPages > 1}
        <div class="flex items-center justify-between px-4 py-3 border-t border-base-200">
          <div class="text-sm text-gray-600">
            Showing {(currentPage - 1) * perPage + 1} - {Math.min(currentPage * perPage, totalItems)} of {totalItems}
          </div>
          <div class="flex items-center gap-2">
            <button
              class="btn btn-sm btn-ghost"
              onclick={() => goToPage(currentPage - 1)}
              disabled={currentPage === 1 || loading}
            >
              <ChevronLeft class="w-4 h-4" />
            </button>
            <div class="flex gap-1">
              {#each Array(Math.min(5, totalPages)) as _, i (i)}
                {@const pageNum = currentPage <= 3
                  ? i + 1
                  : currentPage >= totalPages - 2
                    ? totalPages - 4 + i
                    : currentPage - 2 + i}
                {#if pageNum <= totalPages}
                  <button
                    class="btn btn-sm {pageNum === currentPage ? 'btn-primary' : 'btn-ghost'}"
                    onclick={() => goToPage(pageNum)}
                    disabled={loading}
                  >
                    {pageNum}
                  </button>
                {/if}
              {/each}
            </div>
            <button
              class="btn btn-sm btn-ghost"
              onclick={() => goToPage(currentPage + 1)}
              disabled={currentPage === totalPages || loading}
            >
              <ChevronRight class="w-4 h-4" />
            </button>
          </div>
        </div>
      {:else if hasMore}
        <div class="flex justify-center py-4 border-t border-base-200">
          <button
            class="btn btn-outline"
            onclick={loadNextPage}
            disabled={loading}
          >
            {#if loading}
              <Loader2 class="w-4 h-4 animate-spin mr-2" />
              Loading...
            {:else}
              Load More
            {/if}
          </button>
        </div>
      {/if}
    {/if}
  </div>
</div>

<TestTypePickerModal
  bind:open={testTypePickerOpen}
  onselect={handleTestTypeSelect}
/>

<TestFormModal
  bind:open={modalOpen}
  mode={modalMode}
  testId={selectedTestId}
  initialTestType={selectedTestType}
  {disciplines}
  {departments}
  {tests}
  onsave={async () => {
    modalOpen = false;
    await loadTests();
  }}
/>

<Modal bind:open={deleteConfirmOpen} title="Confirm Delete" size="sm">
  <div class="py-2">
    <p class="text-base-content/80">
      Are you sure you want to delete <strong class="text-base-content">{deleteItem?.TestSiteName}</strong>?
    </p>
    {#if deleteItem?.TestSiteCode}
      <p class="text-sm text-gray-500 mt-1">Code: {deleteItem.TestSiteCode}</p>
    {/if}
    <p class="text-sm text-error mt-3">This action cannot be undone.</p>
  </div>
  {#snippet footer()}
    <button class="btn btn-ghost" onclick={() => (deleteConfirmOpen = false)} type="button" disabled={deleting}>Cancel</button>
    <button class="btn btn-error" onclick={handleDelete} disabled={deleting} type="button">
      {#if deleting}
        <span class="loading loading-spinner loading-sm mr-2"></span>
      {/if}
      {deleting ? 'Deleting...' : 'Delete'}
    </button>
  {/snippet}
</Modal>
