'use client';

import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { useSearchParams } from 'next/navigation';
import { useTranslations } from 'next-intl';
import { Button } from '@/components/ui/shared/Button';
import { Checkbox } from '@/components/ui/shared/Checkbox';
import { FORM_SELECT_CLASS, FORM_SELECT_COMPACT_CLASS } from '@/components/shared/formSelectStyles';
import { SearchBar } from '@/components/ui/shared/SearchBar';
import { TaskCaseGroupHeader } from '@/components/ui/lab/TaskCaseGroupHeader';
import { TaskProsthesisGroupHeader } from '@/components/ui/lab/TaskProsthesisGroupHeader';
import { TaskRow } from '@/components/ui/lab/TaskRow';
import { LabCaseCommentsPanel } from '@/components/ui/lab/LabCaseCommentsPanel';
import { groupTasksForDisplay } from '@/components/lab/taskListGrouping';
import { isLabGeneratedCase } from '@/components/lab/labCaseOrigin';
import {
  buildDefaultLocateParams,
  DEFAULT_TASKS_VIEW,
  isDefaultTasksView,
  TASK_COMPLETE_EXIT_MS,
} from '@/components/lab/tasksViewDefaults';
import { parseTasksSearchParams } from '@/components/lab/parseTasksSearchParams';
import { useMarkTabReadOnVisit } from '@/lib/hooks/useTabBadgeCounts';
import { notifyTabBadgesChanged, tabBadgesChangedEventName } from '@/lib/tabBadgeUtils';
import { scrollWithinMainScrollContainer } from '@/components/shared/scrollWithinMain';
import { getUserFacingError } from '@/components/shared/formatApiError';
import { canEditTasks, canViewTasks } from '@/components/shared/permissions';
import { useAuth } from '@/lib/hooks/useAuth';
import { useToast } from '@/lib/hooks/useToast';
import { prosthesisCatalogApi } from '@/lib/api/prosthesis-catalog';
import { tasksApi } from '@/lib/api/tasks';
import type {
  LabTaskListItem,
  LabTaskStatus,
  ListLabTasksParams,
  PaginatedLabTasks,
  TaskFilterOptions,
  TaskSortField,
} from '@/types/cases';
import type { ProsthesisCatalogEntry } from '@/types/treatment-catalog';

const PAGE_SIZE = 50;

export function TasksPage() {
  const t = useTranslations('tasks');
  const tErrors = useTranslations('errors');
  const searchParams = useSearchParams();
  const { currentOrganization, user, isAuthReady } = useAuth();
  const { showError, showSuccess, setError } = useToast();

  const [tasks, setTasks] = useState<LabTaskListItem[]>([]);
  const [pagination, setPagination] = useState<PaginatedLabTasks['pagination']>({
    page: 1,
    limit: PAGE_SIZE,
    total: 0,
    totalPages: 1,
  });
  const [filterOptions, setFilterOptions] = useState<TaskFilterOptions>({
    clinics: [],
    workflowSteps: [],
  });
  const [prosthesisCatalog, setProsthesisCatalog] = useState<ProsthesisCatalogEntry[]>([]);
  const [page, setPage] = useState(DEFAULT_TASKS_VIEW.page);
  const [loading, setLoading] = useState(false);
  const [locatingCase, setLocatingCase] = useState(false);
  const [updatingTaskId, setUpdatingTaskId] = useState<string | null>(null);
  const [exitingTaskIds, setExitingTaskIds] = useState<Set<string>>(() => new Set());
  const [expandedCommentsTaskId, setExpandedCommentsTaskId] = useState<string | null>(null);
  const [expandedCommentsCaseId, setExpandedCommentsCaseId] = useState<string | null>(null);

  const [search, setSearch] = useState(DEFAULT_TASKS_VIEW.search);
  const [clinicId, setClinicId] = useState(DEFAULT_TASKS_VIEW.clinicId);
  const [statusFilter, setStatusFilter] = useState<'' | LabTaskStatus>(
    DEFAULT_TASKS_VIEW.statusFilter,
  );
  const [stepCompleted, setStepCompleted] = useState(DEFAULT_TASKS_VIEW.stepCompleted);
  const [importantOnly, setImportantOnly] = useState(DEFAULT_TASKS_VIEW.importantOnly);
  const [assignedToMe, setAssignedToMe] = useState(DEFAULT_TASKS_VIEW.assignedToMe);
  const [overdueOnly, setOverdueOnly] = useState(DEFAULT_TASKS_VIEW.overdueOnly);
  const [unassignedOnly, setUnassignedOnly] = useState(DEFAULT_TASKS_VIEW.unassignedOnly);
  const [originFilter, setOriginFilter] = useState(DEFAULT_TASKS_VIEW.origin);
  const [prosthesisTypeCode, setProsthesisTypeCode] = useState(
    DEFAULT_TASKS_VIEW.prosthesisTypeCode,
  );
  const [sortBy, setSortBy] = useState<TaskSortField>(DEFAULT_TASKS_VIEW.sortBy);
  const [sortDir, setSortDir] = useState<'asc' | 'desc'>(DEFAULT_TASKS_VIEW.sortDir);
  const [highlightTaskId, setHighlightTaskId] = useState<string | null>(
    DEFAULT_TASKS_VIEW.highlightTaskId,
  );

  const canView = canViewTasks(currentOrganization);
  const canEdit = canEditTasks(currentOrganization);
  const locale = user?.language ?? 'en';
  useMarkTabReadOnVisit();

  const tRef = useRef(t);
  tRef.current = t;
  const loadTasksRef = useRef<() => Promise<void>>(async () => {});

  const statusOptions: { value: LabTaskStatus; label: string }[] = useMemo(
    () => [
      { value: 'IN_PROGRESS', label: t('statusInProgress') },
      { value: 'COMPLETED', label: t('statusCompleted') },
    ],
    [t],
  );

  const listParams = useMemo((): ListLabTasksParams => {
    const params: ListLabTasksParams = {
      page,
      limit: PAGE_SIZE,
      sortBy,
      sortDir,
    };
    if (search.trim()) params.q = search.trim();
    if (clinicId) params.clinicOrganizationId = clinicId;
    if (statusFilter) params.status = statusFilter;
    if (stepCompleted) params.stepCompleted = stepCompleted;
    if (importantOnly) params.pinImportant = true;
    if (assignedToMe) params.assignedToMe = true;
    if (overdueOnly) params.overdue = true;
    if (unassignedOnly) params.unassignedOnly = true;
    if (originFilter) params.origin = originFilter;
    if (prosthesisTypeCode) params.prosthesisTypeCode = prosthesisTypeCode;
    return params;
  }, [page, search, clinicId, statusFilter, stepCompleted, importantOnly, assignedToMe, overdueOnly, unassignedOnly, originFilter, prosthesisTypeCode, sortBy, sortDir]);

  const displayModel = useMemo(() => groupTasksForDisplay(tasks, sortBy), [tasks, sortBy]);

  const groupingDisabled = sortBy !== 'date';

  const viewState = useMemo(
    () => ({
      search,
      clinicId,
      statusFilter,
      stepCompleted,
      sortBy,
      sortDir,
      importantOnly,
      assignedToMe,
      overdueOnly,
      unassignedOnly,
      origin: originFilter,
      prosthesisTypeCode,
      page,
      highlightTaskId,
    }),
    [
      search,
      clinicId,
      statusFilter,
      stepCompleted,
      sortBy,
      sortDir,
      importantOnly,
      assignedToMe,
      overdueOnly,
      unassignedOnly,
      originFilter,
      prosthesisTypeCode,
      page,
      highlightTaskId,
    ],
  );

  const showReset = !isDefaultTasksView(viewState);

  useEffect(() => {
    const fromUrl = parseTasksSearchParams(searchParams);
    if (fromUrl.importantOnly !== undefined) setImportantOnly(fromUrl.importantOnly);
    if (fromUrl.overdueOnly !== undefined) setOverdueOnly(fromUrl.overdueOnly);
    if (fromUrl.unassignedOnly !== undefined) setUnassignedOnly(fromUrl.unassignedOnly);
    if (fromUrl.origin !== undefined) setOriginFilter(fromUrl.origin);
    if (fromUrl.statusFilter !== undefined) setStatusFilter(fromUrl.statusFilter);
    if (fromUrl.prosthesisTypeCode !== undefined) setProsthesisTypeCode(fromUrl.prosthesisTypeCode);
    if (fromUrl.sortBy !== undefined) setSortBy(fromUrl.sortBy);
    if (fromUrl.sortDir !== undefined) setSortDir(fromUrl.sortDir);
    setPage(1);
  }, [searchParams]);

  useEffect(() => {
    const taskId = searchParams.get('taskId')?.trim();
    if (!taskId || !canView) return;
    let cancelled = false;
    void (async () => {
      try {
        const response = await tasksApi.locatePage(buildDefaultLocateParams(taskId, PAGE_SIZE));
        if (cancelled || !response.data.found) return;
        setStatusFilter('');
        setImportantOnly(false);
        setOverdueOnly(false);
        setUnassignedOnly(false);
        setProsthesisTypeCode('');
        setSortBy('date');
        setSortDir('desc');
        setPage(response.data.page);
        setHighlightTaskId(taskId);
      } catch {
        /* ignore deep-link locate failures */
      }
    })();
    return () => {
      cancelled = true;
    };
  }, [searchParams, canView]);

  const loadTasks = useCallback(async (options?: { silent?: boolean }) => {
    const silent = options?.silent ?? false;
    if (!silent) {
      setLoading(true);
      setError('');
    }
    try {
      const response = await tasksApi.list(listParams);
      setTasks(response.data.items);
      setPagination(response.data.pagination);
    } catch (error: unknown) {
      if (!silent) {
        showError(getUserFacingError(error, tErrors, tRef.current('errorLoadList')));
      }
    } finally {
      if (!silent) setLoading(false);
    }
  }, [listParams, showError, setError, tErrors]);

  loadTasksRef.current = loadTasks;

  useEffect(() => {
    if (!canView) return;
    const timeout = setTimeout(() => void loadTasks(), search ? 300 : 0);
    return () => clearTimeout(timeout);
  }, [canView, loadTasks, search]);

  useEffect(() => {
    if (!canView) return;
    const onBadgesChanged = () => {
      void loadTasks({ silent: true });
    };
    window.addEventListener(tabBadgesChangedEventName(), onBadgesChanged);
    return () => window.removeEventListener(tabBadgesChangedEventName(), onBadgesChanged);
  }, [canView, loadTasks]);

  useEffect(() => {
    if (!canView) return;
    void (async () => {
      try {
        const [optionsRes, catalogRes] = await Promise.all([
          tasksApi.filterOptions(),
          prosthesisCatalogApi.list(),
        ]);
        setFilterOptions(optionsRes.data);
        setProsthesisCatalog(catalogRes.data);
      } catch {
        // Non-blocking — filters fall back to empty options.
      }
    })();
  }, [canView]);

  useEffect(() => {
    if (!highlightTaskId || loading || locatingCase) return;
    const frame = requestAnimationFrame(() => {
      const el = document.getElementById(`task-row-${highlightTaskId}`);
      scrollWithinMainScrollContainer(el, { padding: 24 });
    });
    return () => cancelAnimationFrame(frame);
  }, [highlightTaskId, loading, locatingCase, tasks, displayModel]);

  const clearFocus = useCallback(() => {
    setHighlightTaskId(null);
  }, []);

  const resetView = useCallback(() => {
    setSearch(DEFAULT_TASKS_VIEW.search);
    setClinicId(DEFAULT_TASKS_VIEW.clinicId);
    setStatusFilter(DEFAULT_TASKS_VIEW.statusFilter);
    setStepCompleted(DEFAULT_TASKS_VIEW.stepCompleted);
    setImportantOnly(DEFAULT_TASKS_VIEW.importantOnly);
    setAssignedToMe(DEFAULT_TASKS_VIEW.assignedToMe);
    setOverdueOnly(DEFAULT_TASKS_VIEW.overdueOnly);
    setUnassignedOnly(DEFAULT_TASKS_VIEW.unassignedOnly);
    setOriginFilter(DEFAULT_TASKS_VIEW.origin);
    setProsthesisTypeCode(DEFAULT_TASKS_VIEW.prosthesisTypeCode);
    setSortBy(DEFAULT_TASKS_VIEW.sortBy);
    setSortDir(DEFAULT_TASKS_VIEW.sortDir);
    setPage(DEFAULT_TASKS_VIEW.page);
    setHighlightTaskId(DEFAULT_TASKS_VIEW.highlightTaskId);
    setExpandedCommentsTaskId(null);
  }, []);

  const handleShowInCase = useCallback(
    async (task: LabTaskListItem) => {
      setLocatingCase(true);
      setError('');
      setSearch(DEFAULT_TASKS_VIEW.search);
      setClinicId(DEFAULT_TASKS_VIEW.clinicId);
      setStatusFilter(DEFAULT_TASKS_VIEW.statusFilter);
      setStepCompleted(DEFAULT_TASKS_VIEW.stepCompleted);
      setImportantOnly(DEFAULT_TASKS_VIEW.importantOnly);
      setAssignedToMe(DEFAULT_TASKS_VIEW.assignedToMe);
      setOverdueOnly(DEFAULT_TASKS_VIEW.overdueOnly);
      setUnassignedOnly(DEFAULT_TASKS_VIEW.unassignedOnly);
      setOriginFilter(DEFAULT_TASKS_VIEW.origin);
      setProsthesisTypeCode(DEFAULT_TASKS_VIEW.prosthesisTypeCode);
      setSortBy(DEFAULT_TASKS_VIEW.sortBy);
      setSortDir(DEFAULT_TASKS_VIEW.sortDir);
      setExpandedCommentsTaskId(null);
      setExpandedCommentsCaseId(null);
      setHighlightTaskId(task.id);

      try {
        const response = await tasksApi.locatePage(buildDefaultLocateParams(task.id, PAGE_SIZE));
        if (!response.data.found) {
          showError(t('showInCaseNotFound'));
          setHighlightTaskId(null);
          setPage(1);
          return;
        }
        setPage(response.data.page);
      } catch (error: unknown) {
        showError(getUserFacingError(error, tErrors, t('showInCaseError')));
        setHighlightTaskId(null);
        setPage(1);
      } finally {
        setLocatingCase(false);
      }
    },
    [setError, showError, t, tErrors],
  );

  const handleStatusUpdate = useCallback(
    async (taskId: string, status: LabTaskStatus) => {
      if (!canEdit) return;
      setUpdatingTaskId(taskId);
      setError('');
      try {
        await tasksApi.updateStatus(taskId, status);

        const willLeaveList = status === 'COMPLETED' && statusFilter === 'IN_PROGRESS';

        if (willLeaveList) {
          setTasks((prev) =>
            prev.map((task) => (task.id === taskId ? { ...task, status: 'COMPLETED' } : task)),
          );
          setExitingTaskIds((prev) => new Set(prev).add(taskId));
          showSuccess(t('taskCompletedToast'));

          window.setTimeout(() => {
            setExitingTaskIds((prev) => {
              const next = new Set(prev);
              next.delete(taskId);
              return next;
            });
            void loadTasksRef.current();
          }, TASK_COMPLETE_EXIT_MS);
        } else {
          await loadTasks();
        }
        notifyTabBadgesChanged();
      } catch (error: unknown) {
        showError(getUserFacingError(error, tErrors, t('errorUpdateTask')));
      } finally {
        setUpdatingTaskId(null);
      }
    },
    [canEdit, loadTasks, setError, showError, showSuccess, statusFilter, t, tErrors],
  );

  const filterSelectClass = `${FORM_SELECT_CLASS} w-full min-w-0 rounded-md py-1.5 text-xs sm:py-2 sm:text-sm`;

  const sortHintKey = useMemo(() => {
    switch (sortBy) {
      case 'clinic':
        return 'groupingOffClinic';
      case 'patient':
        return 'groupingOffPatient';
      case 'prosthesis':
        return 'groupingOffProsthesis';
      case 'taskType':
        return 'groupingOffTaskType';
      case 'status':
        return 'groupingOffStatus';
      case 'dueDate':
        return 'groupingOffDueDate';
      default:
        return null;
    }
  }, [sortBy]);

  const applyFilterChange = useCallback(
    (apply: () => void) => {
      apply();
      setPage(1);
      clearFocus();
    },
    [clearFocus],
  );

  const renderTaskRow = (task: LabTaskListItem, flatMode: boolean) => (
    <TaskRow
      key={task.id}
      task={task}
      locale={locale}
      flatMode={flatMode}
      highlighted={highlightTaskId === task.id}
      exiting={exitingTaskIds.has(task.id)}
      canEdit={canEdit}
      currentUserId={user?.id}
      statusOptions={statusOptions}
      updatingTaskId={updatingTaskId}
      commentsOpen={flatMode && expandedCommentsTaskId === task.id}
      showCommentsButton={flatMode}
      prosthesisCatalog={prosthesisCatalog}
      onStatusUpdate={(id, status) => void handleStatusUpdate(id, status)}
      onToggleComments={(id) =>
        setExpandedCommentsTaskId((prev) => (prev === id ? null : id))
      }
      onCommentError={showError}
      onShowInCase={flatMode ? (row) => handleShowInCase(row) : undefined}
    />
  );

  if (!isAuthReady) {
    return <div className="text-sm text-text-muted">{t('loading')}</div>;
  }

  if (!canView) {
    return (
      <div className="surface-card p-6 max-w-xl">
        <h2 className="text-lg font-semibold text-text-primary">{t('noPermissionTitle')}</h2>
        <p className="text-sm text-text-secondary mt-2">{t('noPermissionBody')}</p>
      </div>
    );
  }

  return (
    <div className="space-y-4">
      <header className="space-y-1">
        <h1 className="text-xl sm:text-2xl font-semibold text-text-primary">{t('title')}</h1>
        <p className="text-sm text-text-secondary">{t('subtitle')}</p>
      </header>

      <section className="surface-card p-3 space-y-3">
        <SearchBar
          embedded
          value={search}
          onChange={(v) => applyFilterChange(() => setSearch(v))}
          placeholder={t('searchPlaceholder')}
        />
        <div className="overflow-x-auto">
          <div className="grid min-w-[54rem] grid-cols-5 gap-2">
          <label className="space-y-1">
            <span className="text-xs text-text-muted">{t('filterClinic')}</span>
            <select
              value={clinicId}
              onChange={(e) => applyFilterChange(() => setClinicId(e.target.value))}
              className={filterSelectClass}
            >
              <option value="">{t('filterClinicAll')}</option>
              {filterOptions.clinics.map((c) => (
                <option key={c.id} value={c.id}>
                  {c.name}
                </option>
              ))}
            </select>
          </label>
          <label className="space-y-1">
            <span className="text-xs text-text-muted">{t('filterOrigin')}</span>
            <select
              value={originFilter}
              onChange={(e) =>
                applyFilterChange(() =>
                  setOriginFilter(e.target.value as '' | 'CLINIC_DISPATCH' | 'LAB_INTERNAL'),
                )
              }
              className={filterSelectClass}
            >
              <option value="">{t('filterOriginAll')}</option>
              <option value="CLINIC_DISPATCH">{t('filterOriginReceived')}</option>
              <option value="LAB_INTERNAL">{t('filterOriginGenerated')}</option>
            </select>
          </label>
          <label className="space-y-1">
            <span className="text-xs text-text-muted">{t('filterStatus')}</span>
            <select
              value={statusFilter}
              onChange={(e) =>
                applyFilterChange(() => setStatusFilter(e.target.value as '' | LabTaskStatus))
              }
              className={filterSelectClass}
            >
              <option value="IN_PROGRESS">{t('statusInProgress')}</option>
              <option value="COMPLETED">{t('statusCompleted')}</option>
              <option value="">{t('filterStatusAll')}</option>
            </select>
          </label>
          <label className="space-y-1">
            <span className="text-xs text-text-muted">{t('filterStepCompleted')}</span>
            <select
              value={stepCompleted}
              onChange={(e) => applyFilterChange(() => setStepCompleted(e.target.value))}
              className={filterSelectClass}
            >
              <option value="">{t('filterStepCompletedAll')}</option>
              {filterOptions.workflowSteps.map((step) => (
                <option key={step.code} value={step.code}>
                  {step.label}
                </option>
              ))}
            </select>
          </label>
          <label className="space-y-1 min-w-0">
            <span className="text-xs text-text-muted">{t('sortBy')}</span>
            <div className="grid grid-cols-[minmax(0,1fr)_auto] gap-1">
              <select
                value={sortBy}
                onChange={(e) => {
                  setSortBy(e.target.value as TaskSortField);
                  clearFocus();
                }}
                className={`${filterSelectClass} min-w-0`}
              >
                <option value="date">{t('sortDate')}</option>
                <option value="dueDate">{t('sortDueDate')}</option>
                <option value="clinic">{t('sortClinic')}</option>
                <option value="patient">{t('sortPatient')}</option>
                <option value="prosthesis">{t('sortProsthesis')}</option>
                <option value="taskType">{t('sortTaskType')}</option>
              </select>
              <select
                value={sortDir}
                onChange={(e) => setSortDir(e.target.value as 'asc' | 'desc')}
                className={`${FORM_SELECT_COMPACT_CLASS} w-11 shrink-0 rounded-md py-1.5 text-sm`}
                aria-label={t('sortDirection')}
              >
                <option value="desc">↓</option>
                <option value="asc">↑</option>
              </select>
            </div>
          </label>
          </div>
        </div>
        <div className="flex flex-wrap items-center gap-x-4 gap-y-2">
          <Checkbox
            checked={importantOnly}
            onChange={(checked) => applyFilterChange(() => setImportantOnly(checked))}
            label={t('importantOnly')}
            className="text-xs [&_span:last-child]:text-xs"
          />
          <Checkbox
            checked={assignedToMe}
            onChange={(checked) => applyFilterChange(() => setAssignedToMe(checked))}
            label={t('assignedToMe')}
            className="text-xs [&_span:last-child]:text-xs"
          />
          <Checkbox
            checked={overdueOnly}
            onChange={(checked) => applyFilterChange(() => setOverdueOnly(checked))}
            label={t('overdueOnly')}
            className="text-xs [&_span:last-child]:text-xs"
          />
          <Checkbox
            checked={unassignedOnly}
            onChange={(checked) => applyFilterChange(() => setUnassignedOnly(checked))}
            label={t('unassignedOnly')}
            className="text-xs [&_span:last-child]:text-xs"
          />
          {showReset ? (
            <Button type="button" variant="ghost" size="sm" onClick={resetView}>
              {t('resetView')}
            </Button>
          ) : null}
        </div>
        {groupingDisabled && sortHintKey ? (
          <p className="text-[11px] text-text-muted">{t(sortHintKey)}</p>
        ) : null}
      </section>

      <section className="surface-card min-h-[280px] overflow-x-hidden">
        {(loading || locatingCase) && tasks.length === 0 ? (
          <p className="p-3 text-sm text-text-muted">
            {locatingCase ? t('locatingCase') : t('loading')}
          </p>
        ) : tasks.length === 0 ? (
          <p className="p-3 text-sm text-text-muted">{t('emptyList')}</p>
        ) : displayModel.mode === 'grouped' ? (
          <div className="divide-y divide-border">
            {displayModel.cases.map((caseGroup) => (
              <section key={caseGroup.labCaseId} className="border-b border-border last:border-b-0">
                <TaskCaseGroupHeader
                  caseGroup={caseGroup}
                  locale={locale}
                  showCommentsButton={canEdit}
                  commentsOpen={expandedCommentsCaseId === caseGroup.labCaseId}
                  onToggleComments={() =>
                    setExpandedCommentsCaseId((prev) =>
                      prev === caseGroup.labCaseId ? null : caseGroup.labCaseId,
                    )
                  }
                />
                {expandedCommentsCaseId === caseGroup.labCaseId && canEdit ? (
                  <div className="border-b border-border/50 px-3 pb-3">
                    <LabCaseCommentsPanel
                      caseId={caseGroup.labCaseId}
                      viewerSide="LAB"
                      canPost
                      canToggleVisibility
                      clinicVisibility={!isLabGeneratedCase(caseGroup.origin)}
                      loadComments={async () => {
                        const r = await tasksApi.listComments(caseGroup.labCaseId);
                        return r.data;
                      }}
                      onPost={async (body, visibleToClinic) => {
                        const r = await tasksApi.addComment(caseGroup.labCaseId, {
                          body,
                          visibleToClinic,
                        });
                        notifyTabBadgesChanged();
                        return r.data;
                      }}
                      onToggleVisibility={async (commentId, visible) => {
                        const r = await tasksApi.setCommentVisibility(commentId, visible);
                        return r.data;
                      }}
                      onError={showError}
                    />
                  </div>
                ) : null}
                {caseGroup.prosthesisGroups.map((prosthesisGroup) => (
                  <div
                    key={prosthesisGroup.key}
                    className="border-t border-border/50 first:border-t-0"
                  >
                    <TaskProsthesisGroupHeader
                      group={prosthesisGroup}
                      prosthesisCatalog={prosthesisCatalog}
                    />
                    <ul>
                      {prosthesisGroup.tasks.map((task) => renderTaskRow(task, false))}
                    </ul>
                  </div>
                ))}
              </section>
            ))}
          </div>
        ) : (
          <ul className="divide-y divide-border">
            {displayModel.tasks.map((task) => renderTaskRow(task, true))}
          </ul>
        )}
      </section>

      {pagination.totalPages > 1 ? (
        <div className="flex items-center justify-between gap-3 flex-wrap">
          <p className="text-sm text-text-muted">
            {t('pageSummary', {
              page: pagination.page,
              totalPages: pagination.totalPages,
              total: pagination.total,
            })}
          </p>
          <div className="flex gap-2">
            <Button
              type="button"
              variant="secondary"
              disabled={page <= 1 || loading}
              onClick={() => {
                setPage((p) => Math.max(1, p - 1));
                clearFocus();
              }}
            >
              ←
            </Button>
            <Button
              type="button"
              variant="secondary"
              disabled={page >= pagination.totalPages || loading}
              onClick={() => {
                setPage((p) => p + 1);
                clearFocus();
              }}
            >
              →
            </Button>
          </div>
        </div>
      ) : null}
    </div>
  );
}
