'use client';

import { Suspense, useEffect, useMemo, useState } from 'react';
import { useRouter, useSearchParams } from 'next/navigation';
import { ChevronLeft, Pencil, Plus, Save, Sprout, Trash2, X } from 'lucide-react';

import Navbar from '@/components/Navbar';
import { api } from '@/lib/api';
import {
  DeliveryPlan,
  FertilizationPlan,
  SpreadingCandidate,
  SpreadingSession,
} from '@/types';

const CURRENT_YEAR = new Date().getFullYear();
const YEAR_KEY = 'spreadingYear';

type SourceType = 'delivery' | 'plan' | 'year';

type FormState = {
  date: string;
  name: string;
  notes: string;
  itemValues: Record<string, string>;
};

type MatrixField = {
  id: number;
  name: string;
  area_tan: string;
};

type MatrixFertilizer = {
  id: number;
  name: string;
};

const candidateKey = (fieldId: number, fertilizerId: number) => `${fieldId}:${fertilizerId}`;

const toNumber = (value: string | number | null | undefined) => {
  const parsed = Number(value ?? 0);
  return Number.isFinite(parsed) ? parsed : 0;
};

const formatDisplay = (value: string | number | null | undefined) => {
  const num = toNumber(value);
  if (Number.isInteger(num)) {
    return String(num);
  }
  return num.toFixed(4).replace(/\.?0+$/, '');
};

const formatInputValue = (value: number) => {
  if (value <= 0) return '0';
  return value.toFixed(2).replace(/\.?0+$/, '');
};

const getDefaultDate = (year: number) => {
  const today = new Date();
  if (today.getFullYear() !== year) {
    return `${year}-01-01`;
  }
  const month = String(today.getMonth() + 1).padStart(2, '0');
  const day = String(today.getDate()).padStart(2, '0');
  return `${year}-${month}-${day}`;
};

const getSourceType = (deliveryPlanId: number | null, fertilizationPlanId: number | null): SourceType => {
  if (deliveryPlanId) return 'delivery';
  if (fertilizationPlanId) return 'plan';
  return 'year';
};

const buildCreateInitialValues = (rows: SpreadingCandidate[], sourceType: SourceType) => {
  const values: Record<string, string> = {};
  rows.forEach((candidate) => {
    let base = 0;
    if (sourceType === 'delivery') {
      base = toNumber(candidate.delivered_bags) - toNumber(candidate.spread_bags_other);
    } else if (sourceType === 'plan') {
      base = toNumber(candidate.planned_bags) - toNumber(candidate.spread_bags_other);
    } else {
      base = toNumber(candidate.delivered_bags) - toNumber(candidate.spread_bags_other);
    }
    values[candidateKey(candidate.field, candidate.fertilizer)] = formatInputValue(Math.max(base, 0));
  });
  return values;
};

export default function SpreadingPage() {
  return (
    <Suspense fallback={<div className="min-h-screen bg-gray-50"><Navbar /><div className="max-w-7xl mx-auto px-4 py-8 text-gray-500">読み込み中...</div></div>}>
      <SpreadingPageContent />
    </Suspense>
  );
}

function SpreadingPageContent() {
  const router = useRouter();
  const searchParams = useSearchParams();
  const queryYear = Number(searchParams.get('year') || '0') || null;
  const deliveryPlanId = Number(searchParams.get('delivery_plan') || '0') || null;
  const fertilizationPlanId = Number(searchParams.get('plan') || '0') || null;
  const sourceType = getSourceType(deliveryPlanId, fertilizationPlanId);

  const [year, setYear] = useState<number>(() => {
    if (typeof window !== 'undefined') {
      return parseInt(localStorage.getItem(YEAR_KEY) || String(CURRENT_YEAR), 10);
    }
    return CURRENT_YEAR;
  });
  const [sessions, setSessions] = useState<SpreadingSession[]>([]);
  const [candidates, setCandidates] = useState<SpreadingCandidate[]>([]);
  const [loading, setLoading] = useState(true);
  const [formLoading, setFormLoading] = useState(false);
  const [saving, setSaving] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [editingSessionId, setEditingSessionId] = useState<number | null>(null);
  const [form, setForm] = useState<FormState | null>(null);
  const [openedFromQuery, setOpenedFromQuery] = useState(false);
  const [openedFromSource, setOpenedFromSource] = useState(false);
  const [sourceName, setSourceName] = useState<string | null>(null);

  useEffect(() => {
    if (queryYear && queryYear !== year) {
      setYear(queryYear);
    }
  }, [queryYear, year]);

  useEffect(() => {
    localStorage.setItem(YEAR_KEY, String(year));
    void fetchSessions();
    setForm(null);
    setEditingSessionId(null);
    setOpenedFromQuery(false);
    setOpenedFromSource(false);
  }, [year]);

  useEffect(() => {
    const loadSource = async () => {
      if (deliveryPlanId) {
        try {
          const res = await api.get(`/fertilizer/delivery/${deliveryPlanId}/`);
          const plan: DeliveryPlan = res.data;
          setSourceName(plan.name);
          return;
        } catch (e) {
          console.error(e);
          setSourceName(`運搬計画 #${deliveryPlanId}`);
          return;
        }
      }
      if (fertilizationPlanId) {
        try {
          const res = await api.get(`/fertilizer/plans/${fertilizationPlanId}/`);
          const plan: FertilizationPlan = res.data;
          setSourceName(plan.name);
          return;
        } catch (e) {
          console.error(e);
          setSourceName(`施肥計画 #${fertilizationPlanId}`);
          return;
        }
      }
      setSourceName(null);
    };
    void loadSource();
  }, [deliveryPlanId, fertilizationPlanId]);

  useEffect(() => {
    const sessionParam = searchParams.get('session');
    if (!sessionParam || openedFromQuery || sessions.length === 0) {
      return;
    }
    const targetId = Number(sessionParam);
    if (!targetId) {
      return;
    }
    const target = sessions.find((session) => session.id === targetId);
    if (target) {
      void openEditor(target);
      setOpenedFromQuery(true);
    }
  }, [openedFromQuery, searchParams, sessions]);

  useEffect(() => {
    const sessionParam = searchParams.get('session');
    if (sessionParam || sourceType === 'year' || openedFromSource || form || formLoading) {
      return;
    }
    void startCreate();
    setOpenedFromSource(true);
  }, [form, formLoading, openedFromSource, searchParams, sourceType]);

  const fetchSessions = async () => {
    setLoading(true);
    setError(null);
    try {
      const res = await api.get(`/fertilizer/spreading/?year=${year}`);
      setSessions(res.data);
    } catch (e) {
      console.error(e);
      setError('散布実績の読み込みに失敗しました。');
    } finally {
      setLoading(false);
    }
  };

  const loadCandidates = async (sessionId?: number) => {
    const params = new URLSearchParams({ year: String(year) });
    if (sessionId) {
      params.set('session_id', String(sessionId));
    }
    if (deliveryPlanId) {
      params.set('delivery_plan_id', String(deliveryPlanId));
    }
    if (fertilizationPlanId) {
      params.set('plan_id', String(fertilizationPlanId));
    }
    const res = await api.get(`/fertilizer/spreading/candidates/?${params.toString()}`);
    setCandidates(res.data);
    return res.data as SpreadingCandidate[];
  };

  const startCreate = async () => {
    setFormLoading(true);
    setError(null);
    try {
      const loaded = await loadCandidates();
      setEditingSessionId(null);
      setForm({
        date: getDefaultDate(year),
        name: '',
        notes: '',
        itemValues: buildCreateInitialValues(loaded, sourceType),
      });
    } catch (e) {
      console.error(e);
      setError('散布候補の読み込みに失敗しました。');
    } finally {
      setFormLoading(false);
    }
  };

  const openEditor = async (session: SpreadingSession) => {
    setFormLoading(true);
    setError(null);
    try {
      await loadCandidates(session.id);
      const itemValues = session.items.reduce<Record<string, string>>((acc, item) => {
        acc[candidateKey(item.field, item.fertilizer)] = String(item.actual_bags);
        return acc;
      }, {});
      setEditingSessionId(session.id);
      setForm({
        date: session.date,
        name: session.name,
        notes: session.notes,
        itemValues,
      });
    } catch (e) {
      console.error(e);
      setError('散布候補の読み込みに失敗しました。');
    } finally {
      setFormLoading(false);
    }
  };

  const closeEditor = () => {
    setEditingSessionId(null);
    setForm(null);
    setCandidates([]);
  };

  const candidateMap = useMemo(() => {
    const map = new Map<string, SpreadingCandidate>();
    candidates.forEach((candidate) => {
      map.set(candidateKey(candidate.field, candidate.fertilizer), candidate);
    });
    return map;
  }, [candidates]);

  const matrixFields = useMemo<MatrixField[]>(() => {
    const map = new Map<number, MatrixField>();
    candidates.forEach((candidate) => {
      if (!map.has(candidate.field)) {
        map.set(candidate.field, {
          id: candidate.field,
          name: candidate.field_name,
          area_tan: candidate.field_area_tan,
        });
      }
    });
    return Array.from(map.values()).sort((a, b) => a.name.localeCompare(b.name, 'ja'));
  }, [candidates]);

  const matrixFertilizers = useMemo<MatrixFertilizer[]>(() => {
    const map = new Map<number, MatrixFertilizer>();
    candidates.forEach((candidate) => {
      if (!map.has(candidate.fertilizer)) {
        map.set(candidate.fertilizer, {
          id: candidate.fertilizer,
          name: candidate.fertilizer_name,
        });
      }
    });
    return Array.from(map.values()).sort((a, b) => a.name.localeCompare(b.name, 'ja'));
  }, [candidates]);

  const handleItemChange = (fieldId: number, fertilizerId: number, value: string) => {
    if (!form) return;
    const key = candidateKey(fieldId, fertilizerId);
    setForm({
      ...form,
      itemValues: {
        ...form.itemValues,
        [key]: value,
      },
    });
  };

  const getCellValue = (fieldId: number, fertilizerId: number) => {
    if (!form) return '';
    return form.itemValues[candidateKey(fieldId, fertilizerId)] ?? '0';
  };

  const selectedRows = useMemo(() => {
    if (!form) return [];
    return candidates.filter((candidate) => {
      const value = toNumber(form.itemValues[candidateKey(candidate.field, candidate.fertilizer)] || '0');
      return value > 0;
    });
  }, [candidates, form]);

  const getRowTotal = (fieldId: number) => {
    if (!form) return 0;
    return matrixFertilizers.reduce((sum, fertilizer) => {
      const candidate = candidateMap.get(candidateKey(fieldId, fertilizer.id));
      if (!candidate) return sum;
      return sum + toNumber(getCellValue(fieldId, fertilizer.id));
    }, 0);
  };

  const getColumnTotal = (fertilizerId: number) => {
    if (!form) return 0;
    return matrixFields.reduce((sum, field) => {
      const candidate = candidateMap.get(candidateKey(field.id, fertilizerId));
      if (!candidate) return sum;
      return sum + toNumber(getCellValue(field.id, fertilizerId));
    }, 0);
  };

  const totalInputBags = selectedRows.reduce((sum, candidate) => {
    return sum + toNumber(form?.itemValues[candidateKey(candidate.field, candidate.fertilizer)] || '0');
  }, 0);

  const handleSave = async () => {
    if (!form) return;
    setError(null);
    if (!form.name.trim()) {
      setError('名称を入力してください。');
      return;
    }
    if (!form.date) {
      setError('散布日を入力してください。');
      return;
    }

    const items = selectedRows.map((candidate) => ({
      field_id: candidate.field,
      fertilizer_id: candidate.fertilizer,
      actual_bags: toNumber(form.itemValues[candidateKey(candidate.field, candidate.fertilizer)] || '0'),
      planned_bags_snapshot: toNumber(candidate.planned_bags),
      delivered_bags_snapshot: toNumber(candidate.delivered_bags),
    }));

    if (items.length === 0) {
      setError('散布実績を1件以上入力してください。');
      return;
    }

    setSaving(true);
    try {
      const payload = {
        year,
        date: form.date,
        name: form.name,
        notes: form.notes,
        items,
      };
      if (editingSessionId) {
        await api.put(`/fertilizer/spreading/${editingSessionId}/`, payload);
      } else {
        await api.post('/fertilizer/spreading/', payload);
      }
      await fetchSessions();
      closeEditor();
    } catch (e) {
      console.error(e);
      setError('散布実績の保存に失敗しました。');
    } finally {
      setSaving(false);
    }
  };

  const handleDelete = async (sessionId: number) => {
    setError(null);
    try {
      await api.delete(`/fertilizer/spreading/${sessionId}/`);
      await fetchSessions();
      if (editingSessionId === sessionId) {
        closeEditor();
      }
    } catch (e) {
      console.error(e);
      setError('散布実績の削除に失敗しました。');
    }
  };

  const years = Array.from({ length: 5 }, (_, i) => CURRENT_YEAR + 1 - i);

  const sourceSummary =
    sourceType === 'delivery'
      ? '初期値は運搬計画値から散布済を引いた値です。'
      : sourceType === 'plan'
        ? '初期値は施肥計画値から散布済を引いた値です。'
        : '初期値は運搬済みから散布済を引いた値です。';

  const sourceLabel =
    sourceType === 'delivery'
      ? '運搬計画を選択した状態です'
      : sourceType === 'plan'
        ? '施肥計画を選択した状態です'
        : null;

  const clearFilterHref = `/fertilizer/spreading?year=${year}`;

  return (
    <div className="min-h-screen bg-gray-50">
      <Navbar />
      <main className="mx-auto max-w-7xl px-4 py-8">
        <div className="mb-6 flex items-center justify-between">
          <div className="flex items-center gap-3">
            <button onClick={() => router.push('/fertilizer')} className="text-gray-500 hover:text-gray-700">
              <ChevronLeft className="h-5 w-5" />
            </button>
            <Sprout className="h-6 w-6 text-green-700" />
            <h1 className="text-2xl font-bold text-gray-900">散布実績</h1>
          </div>
          <button
            onClick={() => void startCreate()}
            className="flex items-center gap-2 rounded-lg bg-green-600 px-4 py-2 text-sm font-medium text-white hover:bg-green-700"
          >
            <Plus className="h-4 w-4" />
            新規記録
          </button>
        </div>

        <div className="mb-6 flex items-center gap-3">
          <label className="text-sm font-medium text-gray-700">年度:</label>
          <select
            value={year}
            onChange={(e) => setYear(Number(e.target.value))}
            className="rounded-lg border border-gray-300 px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-green-500"
          >
            {years.map((y) => (
              <option key={y} value={y}>
                {y}年度
              </option>
            ))}
          </select>
        </div>

        {sourceLabel && (
          <div className="mb-6 flex items-center justify-between rounded-lg border border-emerald-200 bg-emerald-50 px-4 py-3">
            <div>
              <div className="text-sm font-medium text-emerald-900">{sourceLabel}</div>
              <div className="mt-1 text-sm text-emerald-700">
                {sourceName ?? (sourceType === 'delivery' ? `運搬計画 #${deliveryPlanId}` : `施肥計画 #${fertilizationPlanId}`)}
                {' '}を起点に散布候補を絞り込んでいます。
              </div>
              <div className="mt-1 text-xs text-emerald-700">{sourceSummary}</div>
            </div>
            <button
              onClick={() => router.push(clearFilterHref)}
              className="flex items-center gap-1 rounded border border-emerald-300 px-3 py-1.5 text-xs text-emerald-700 hover:bg-emerald-100"
            >
              <X className="h-3.5 w-3.5" />
              絞り込み解除
            </button>
          </div>
        )}

        {error && (
          <div className="mb-4 rounded-lg border border-red-300 bg-red-50 px-4 py-3 text-sm text-red-700">
            {error}
          </div>
        )}

        {(form || formLoading) && (
          <section className="mb-8 rounded-lg border border-emerald-200 bg-white shadow-sm">
            <div className="border-b border-emerald-100 px-5 py-4">
              <h2 className="text-lg font-semibold text-gray-900">
                {editingSessionId ? '散布実績を編集' : '散布実績を登録'}
              </h2>
              <p className="mt-1 text-sm text-gray-500">
                施肥計画と同じ感覚で、圃場 × 肥料のマトリックスで実績を入力します。
              </p>
              <p className="mt-1 text-xs text-gray-500">{sourceSummary}</p>
            </div>

            {formLoading || !form ? (
              <div className="px-5 py-8 text-sm text-gray-500">候補を読み込み中...</div>
            ) : (
              <div className="space-y-5 px-5 py-5">
                <div className="grid gap-4 md:grid-cols-3">
                  <div>
                    <label className="mb-1 block text-xs font-medium text-gray-600">散布日</label>
                    <input
                      type="date"
                      value={form.date}
                      onChange={(e) => setForm({ ...form, date: e.target.value })}
                      className="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-green-500"
                    />
                  </div>
                  <div>
                    <label className="mb-1 block text-xs font-medium text-gray-600">名称</label>
                    <input
                      value={form.name}
                      onChange={(e) => setForm({ ...form, name: e.target.value })}
                      placeholder="例: 3/17 元肥散布"
                      className="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-green-500"
                    />
                  </div>
                  <div>
                    <label className="mb-1 block text-xs font-medium text-gray-600">備考</label>
                    <input
                      value={form.notes}
                      onChange={(e) => setForm({ ...form, notes: e.target.value })}
                      placeholder="任意"
                      className="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-green-500"
                    />
                  </div>
                </div>

                <div className="overflow-x-auto rounded-lg border border-gray-200">
                  <table className="min-w-full border-collapse text-sm">
                    <thead className="bg-gray-50">
                      <tr>
                        <th className="w-48 border border-gray-200 px-4 py-3 text-left font-medium text-gray-700">
                          圃場
                        </th>
                        {matrixFertilizers.map((fertilizer) => (
                          <th
                            key={fertilizer.id}
                            className="min-w-[220px] border border-gray-200 px-3 py-3 text-center font-medium text-gray-700"
                          >
                            <div>{fertilizer.name}</div>
                            <div className="mt-1 text-[11px] font-normal text-gray-400">
                              入力計 {formatDisplay(getColumnTotal(fertilizer.id))}袋
                            </div>
                          </th>
                        ))}
                        <th className="w-28 border border-gray-200 px-3 py-3 text-right font-medium text-gray-700">
                          行合計
                        </th>
                      </tr>
                    </thead>
                    <tbody>
                      {matrixFields.length === 0 ? (
                        <tr>
                          <td
                            colSpan={matrixFertilizers.length + 2}
                            className="border border-gray-200 px-4 py-8 text-center text-gray-400"
                          >
                            散布対象の候補がありません。
                          </td>
                        </tr>
                      ) : (
                        matrixFields.map((field) => (
                          <tr key={field.id} className="hover:bg-gray-50">
                            <td className="border border-gray-200 px-4 py-3 align-top">
                              <div className="font-medium text-gray-900">{field.name}</div>
                              <div className="text-xs text-gray-400">{field.area_tan}反</div>
                            </td>
                            {matrixFertilizers.map((fertilizer) => {
                              const candidate = candidateMap.get(candidateKey(field.id, fertilizer.id));
                              if (!candidate) {
                                return (
                                  <td
                                    key={fertilizer.id}
                                    className="border border-gray-200 bg-gray-50 px-3 py-3 text-center text-xs text-gray-300"
                                  >
                                    -
                                  </td>
                                );
                              }

                              return (
                                <td key={fertilizer.id} className="border border-gray-200 px-3 py-3 align-top">
                                  <div className="flex items-center justify-between gap-3">
                                    <div className="grid flex-1 grid-cols-2 gap-x-3 gap-y-1 text-[11px] leading-5 text-gray-500">
                                      <div className="whitespace-nowrap">
                                        <span className="mr-1 text-gray-400">計画</span>
                                        <span>{formatDisplay(candidate.planned_bags)}</span>
                                      </div>
                                      <div className="whitespace-nowrap">
                                        <span className="mr-1 text-gray-400">
                                          {sourceType === 'plan' ? '計画残' : '未散布'}
                                        </span>
                                        <span>
                                          {formatDisplay(
                                            sourceType === 'plan'
                                              ? Math.max(toNumber(candidate.planned_bags) - toNumber(candidate.spread_bags_other), 0)
                                              : Math.max(toNumber(candidate.delivered_bags) - toNumber(candidate.spread_bags_other), 0)
                                          )}
                                        </span>
                                      </div>
                                      <div className="whitespace-nowrap">
                                        <span className="mr-1 text-gray-400">運搬</span>
                                        <span>{formatDisplay(candidate.delivered_bags)}</span>
                                      </div>
                                      <div className="whitespace-nowrap">
                                        <span className="mr-1 text-gray-400">散布済</span>
                                        <span>{formatDisplay(candidate.spread_bags_other)}</span>
                                      </div>
                                    </div>
                                    <input
                                      type="number"
                                      step="0.1"
                                      value={getCellValue(field.id, fertilizer.id)}
                                      onChange={(e) => handleItemChange(field.id, fertilizer.id, e.target.value)}
                                      className="w-20 shrink-0 rounded border border-gray-300 px-2 py-1.5 text-right text-sm focus:outline-none focus:ring-2 focus:ring-green-500"
                                    />
                                  </div>
                                </td>
                              );
                            })}
                            <td className="border border-gray-200 px-3 py-3 text-right font-medium text-gray-700">
                              {formatDisplay(getRowTotal(field.id))}
                            </td>
                          </tr>
                        ))
                      )}
                    </tbody>
                    {matrixFields.length > 0 && (
                      <tfoot className="bg-gray-50">
                        <tr>
                          <td className="border border-gray-200 px-4 py-3 font-medium text-gray-700">合計</td>
                          {matrixFertilizers.map((fertilizer) => (
                            <td
                              key={fertilizer.id}
                              className="border border-gray-200 px-3 py-3 text-right font-medium text-gray-700"
                            >
                              {formatDisplay(getColumnTotal(fertilizer.id))}
                            </td>
                          ))}
                          <td className="border border-gray-200 px-3 py-3 text-right font-bold text-green-700">
                            {formatDisplay(totalInputBags)}
                          </td>
                        </tr>
                      </tfoot>
                    )}
                  </table>
                </div>

                <div className="flex items-center justify-between">
                  <p className="text-sm text-gray-500">
                    入力中 {selectedRows.length}件 / 合計 {formatDisplay(totalInputBags)}袋
                  </p>
                  <div className="flex items-center gap-3">
                    <button
                      onClick={closeEditor}
                      className="rounded-lg border border-gray-300 px-4 py-2 text-sm text-gray-700 hover:bg-gray-100"
                    >
                      キャンセル
                    </button>
                    <button
                      onClick={() => void handleSave()}
                      disabled={saving}
                      className="flex items-center gap-2 rounded-lg bg-green-600 px-4 py-2 text-sm font-medium text-white hover:bg-green-700 disabled:cursor-not-allowed disabled:opacity-50"
                    >
                      <Save className="h-4 w-4" />
                      {saving ? '保存中...' : '保存'}
                    </button>
                  </div>
                </div>
              </div>
            )}
          </section>
        )}

        <section className="rounded-lg bg-white shadow-sm">
          <div className="border-b px-5 py-4">
            <h2 className="text-lg font-semibold text-gray-900">登録済み散布実績</h2>
          </div>
          {loading ? (
            <div className="px-5 py-8 text-sm text-gray-500">読み込み中...</div>
          ) : sessions.length === 0 ? (
            <div className="px-5 py-8 text-sm text-gray-400">この年度の散布実績はまだありません。</div>
          ) : (
            <div className="overflow-x-auto">
              <table className="w-full text-sm">
                <thead className="bg-gray-50">
                  <tr>
                    <th className="px-4 py-3 text-left font-medium text-gray-700">散布日</th>
                    <th className="px-4 py-3 text-left font-medium text-gray-700">名称</th>
                    <th className="px-4 py-3 text-right font-medium text-gray-700">明細数</th>
                    <th className="px-4 py-3 text-right font-medium text-gray-700">合計袋数</th>
                    <th className="px-4 py-3 text-right font-medium text-gray-700">作業記録</th>
                    <th className="px-4 py-3" />
                  </tr>
                </thead>
                <tbody className="divide-y divide-gray-100">
                  {sessions.map((session) => {
                    const totalBags = session.items.reduce((sum, item) => sum + toNumber(item.actual_bags), 0);
                    return (
                      <tr key={session.id} className="hover:bg-gray-50">
                        <td className="px-4 py-3 text-gray-700">{session.date}</td>
                        <td className="px-4 py-3">
                          <div className="font-medium text-gray-900">{session.name || '名称なし'}</div>
                          {session.notes && <div className="text-xs text-gray-400">{session.notes}</div>}
                        </td>
                        <td className="px-4 py-3 text-right text-gray-600">{session.items.length}</td>
                        <td className="px-4 py-3 text-right tabular-nums text-gray-600">{formatDisplay(totalBags)}</td>
                        <td className="px-4 py-3 text-right text-gray-600">
                          {session.work_record_id ? `#${session.work_record_id}` : '-'}
                        </td>
                        <td className="px-4 py-3">
                          <div className="flex items-center justify-end gap-2">
                            <button
                              onClick={() => void openEditor(session)}
                              className="flex items-center gap-1 rounded border border-blue-300 px-2.5 py-1.5 text-xs text-blue-700 hover:bg-blue-50"
                            >
                              <Pencil className="h-3.5 w-3.5" />
                              編集
                            </button>
                            <button
                              onClick={() => void handleDelete(session.id)}
                              className="flex items-center gap-1 rounded border border-red-300 px-2.5 py-1.5 text-xs text-red-600 hover:bg-red-50"
                            >
                              <Trash2 className="h-3.5 w-3.5" />
                              削除
                            </button>
                          </div>
                        </td>
                      </tr>
                    );
                  })}
                </tbody>
              </table>
            </div>
          )}
        </section>
      </main>
    </div>
  );
}
