'use client';

import { Suspense, useEffect, useMemo, useState } from 'react';
import { useRouter, useSearchParams } from 'next/navigation';
import { ArrowDown, ArrowUp, ChevronLeft, PencilLine, Plus, Save, Trash2 } from 'lucide-react';

import Navbar from '@/components/Navbar';
import { api } from '@/lib/api';
import { LeveeWorkCandidate, LeveeWorkSession } from '@/types';

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

type FormState = {
  date: string;
  title: string;
  notes: string;
  selectedFieldIds: Set<number>;
};

type SortKey = 'field_name' | 'field_area_tan' | 'group_name' | 'variety_name';
type SortDirection = 'asc' | 'desc';

const extractErrorMessage = (error: any) => {
  const data = error?.response?.data;
  if (!data) return '保存に失敗しました。';
  if (typeof data.detail === 'string') return data.detail;
  if (Array.isArray(data.year) && data.year[0]) return data.year[0];
  if (Array.isArray(data.items) && data.items[0]) return data.items[0];
  if (typeof data.items === 'string') return data.items;
  return '保存に失敗しました。';
};

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}`;
};

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

function LeveeWorkPageContent() {
  const router = useRouter();
  const searchParams = useSearchParams();
  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<LeveeWorkSession[]>([]);
  const [candidates, setCandidates] = useState<LeveeWorkCandidate[]>([]);
  const [form, setForm] = useState<FormState | null>(null);
  const [editingSessionId, setEditingSessionId] = useState<number | null>(null);
  const [loading, setLoading] = useState(true);
  const [formLoading, setFormLoading] = useState(false);
  const [saving, setSaving] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [openedFromQuery, setOpenedFromQuery] = useState(false);
  const [sortKey, setSortKey] = useState<SortKey>('field_name');
  const [sortDirection, setSortDirection] = useState<SortDirection>('asc');

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

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

  const fetchSessions = async () => {
    setLoading(true);
    setError(null);
    try {
      const res = await api.get(`/levee-work/sessions/?year=${year}`);
      setSessions(res.data);
    } catch (e) {
      console.error(e);
      setError('畔塗記録の読み込みに失敗しました。');
    } finally {
      setLoading(false);
    }
  };

  const loadCandidates = async () => {
    const res = await api.get(`/levee-work/candidates/?year=${year}`);
    setCandidates(res.data);
    return res.data as LeveeWorkCandidate[];
  };

  const startCreate = async () => {
    setFormLoading(true);
    setError(null);
    try {
      const loaded = await loadCandidates();
      setEditingSessionId(null);
      setForm({
        date: getDefaultDate(year),
        title: '水稲畔塗',
        notes: '',
        selectedFieldIds: new Set(loaded.filter((candidate) => candidate.selected).map((candidate) => candidate.field_id)),
      });
    } catch (e) {
      console.error(e);
      setError('候補圃場の読み込みに失敗しました。');
    } finally {
      setFormLoading(false);
    }
  };

  const openEditor = async (session: LeveeWorkSession) => {
    setFormLoading(true);
    setError(null);
    try {
      const loaded = await loadCandidates();
      const selectedIds = new Set(session.items.map((item) => item.field));
      const fallbackSelected = loaded.filter((candidate) => candidate.selected).map((candidate) => candidate.field_id);
      setEditingSessionId(session.id);
      setForm({
        date: session.date,
        title: session.title,
        notes: session.notes,
        selectedFieldIds: selectedIds.size > 0 ? selectedIds : new Set(fallbackSelected),
      });
    } catch (e) {
      console.error(e);
      setError('編集用データの読み込みに失敗しました。');
    } finally {
      setFormLoading(false);
    }
  };

  const handleToggleField = (fieldId: number) => {
    if (!form) return;
    const next = new Set(form.selectedFieldIds);
    if (next.has(fieldId)) {
      next.delete(fieldId);
    } else {
      next.add(fieldId);
    }
    setForm({ ...form, selectedFieldIds: next });
  };

  const handleSelectAll = () => {
    if (!form) return;
    setForm({
      ...form,
      selectedFieldIds: new Set(candidates.map((candidate) => candidate.field_id)),
    });
  };

  const handleClearAll = () => {
    if (!form) return;
    setForm({ ...form, selectedFieldIds: new Set() });
  };

  const selectedCount = form?.selectedFieldIds.size ?? 0;

  const sortedCandidates = useMemo(() => {
    const rows = [...candidates];
    rows.sort((a, b) => {
      let result = 0;

      if (sortKey === 'field_area_tan') {
        result = Number(a.field_area_tan) - Number(b.field_area_tan);
      } else {
        result = (a[sortKey] || '').toString().localeCompare((b[sortKey] || '').toString(), 'ja');
      }

      if (result === 0) {
        result = a.field_name.localeCompare(b.field_name, 'ja');
      }

      return sortDirection === 'asc' ? result : -result;
    });
    return rows;
  }, [candidates, sortDirection, sortKey]);

  const selectedCandidates = useMemo(() => {
    if (!form) return [];
    return sortedCandidates.filter((candidate) => form.selectedFieldIds.has(candidate.field_id));
  }, [form, sortedCandidates]);

  const selectedAreaTan = useMemo(() => {
    return selectedCandidates.reduce((sum, candidate) => sum + Number(candidate.field_area_tan || '0'), 0);
  }, [selectedCandidates]);

  const handleSort = (nextKey: SortKey) => {
    if (sortKey === nextKey) {
      setSortDirection((current) => (current === 'asc' ? 'desc' : 'asc'));
      return;
    }
    setSortKey(nextKey);
    setSortDirection('asc');
  };

  const renderSortIcon = (key: SortKey) => {
    if (sortKey !== key) return null;
    return sortDirection === 'asc' ? (
      <ArrowUp className="h-3.5 w-3.5" />
    ) : (
      <ArrowDown className="h-3.5 w-3.5" />
    );
  };

  const handleSave = async () => {
    if (!form) return;
    if (selectedCount === 0) {
      setError('対象圃場を1件以上選択してください。');
      return;
    }
    setSaving(true);
    setError(null);
    try {
      const payload = {
        year,
        date: form.date,
        title: form.title,
        notes: form.notes,
        items: selectedCandidates.map((candidate) => ({
          field: candidate.field_id,
          plan: candidate.plan_id,
        })),
      };
      if (editingSessionId) {
        await api.put(`/levee-work/sessions/${editingSessionId}/`, payload);
      } else {
        await api.post('/levee-work/sessions/', payload);
      }
      await fetchSessions();
      await startCreate();
    } catch (e: any) {
      console.error(e);
      setError(extractErrorMessage(e));
    } finally {
      setSaving(false);
    }
  };

  const handleDelete = async () => {
    if (!editingSessionId) return;
    if (!window.confirm('この畔塗記録を削除しますか？')) return;
    setSaving(true);
    setError(null);
    try {
      await api.delete(`/levee-work/sessions/${editingSessionId}/`);
      await fetchSessions();
      setEditingSessionId(null);
      setForm(null);
    } catch (e) {
      console.error(e);
      setError('削除に失敗しました。');
    } finally {
      setSaving(false);
    }
  };

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

  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 gap-4">
          <div className="flex items-center gap-3">
            <button onClick={() => router.push('/workrecords')} className="text-gray-500 hover:text-gray-700">
              <ChevronLeft className="h-5 w-5" />
            </button>
            <PencilLine className="h-6 w-6 text-amber-700" />
            <h1 className="text-2xl font-bold text-gray-900">畔塗記録</h1>
          </div>
          <div className="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-amber-500"
            >
              {years.map((y) => (
                <option key={y} value={y}>
                  {y}年度
                </option>
              ))}
            </select>
            <button
              onClick={() => void startCreate()}
              className="inline-flex items-center gap-2 rounded-lg bg-amber-600 px-4 py-2 text-sm font-medium text-white hover:bg-amber-700"
            >
              <Plus className="h-4 w-4" />
              新規作成
            </button>
          </div>
        </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>
        )}

        <div className="grid gap-6 lg:grid-cols-[360px_minmax(0,1fr)]">
          <section className="overflow-hidden rounded-lg bg-white shadow-sm">
            <div className="border-b bg-gray-50 px-4 py-3 text-sm font-medium text-gray-700">記録一覧</div>
            {loading ? (
              <div className="px-4 py-8 text-sm text-gray-500">読み込み中...</div>
            ) : sessions.length === 0 ? (
              <div className="px-4 py-8 text-sm text-gray-400">この年度の畔塗記録はまだありません。</div>
            ) : (
              <div className="divide-y divide-gray-100">
                {sessions.map((session) => (
                  <button
                    key={session.id}
                    onClick={() => void openEditor(session)}
                    className={`block w-full px-4 py-4 text-left hover:bg-amber-50 ${
                      editingSessionId === session.id ? 'bg-amber-50' : ''
                    }`}
                  >
                    <div className="text-sm font-medium text-gray-900">{session.title}</div>
                    <div className="mt-1 text-sm text-gray-600">{session.date}</div>
                    <div className="mt-1 text-xs text-gray-500">
                      {session.item_count}圃場 / {Number(session.total_area_tan).toFixed(2)}反
                    </div>
                  </button>
                ))}
              </div>
            )}
          </section>

          <section className="rounded-lg bg-white shadow-sm">
            <div className="border-b bg-gray-50 px-5 py-3 text-sm font-medium text-gray-700">
              {editingSessionId ? '畔塗記録を編集' : '畔塗記録を作成'}
            </div>

            {!form ? (
              <div className="px-5 py-10 text-sm text-gray-500">
                {formLoading ? 'フォームを準備中...' : '「新規作成」または既存記録の選択で編集を始められます。'}
              </div>
            ) : (
              <div className="space-y-6 px-5 py-5">
                <div className="grid gap-4 md:grid-cols-2">
                  <label className="block">
                    <div className="mb-1 text-sm font-medium text-gray-700">日付</div>
                    <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-amber-500"
                    />
                  </label>
                  <label className="block">
                    <div className="mb-1 text-sm font-medium text-gray-700">タイトル</div>
                    <input
                      type="text"
                      value={form.title}
                      onChange={(e) => setForm({ ...form, title: 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-amber-500"
                    />
                  </label>
                </div>

                <label className="block">
                  <div className="mb-1 text-sm font-medium text-gray-700">備考</div>
                  <textarea
                    value={form.notes}
                    onChange={(e) => setForm({ ...form, notes: e.target.value })}
                    rows={3}
                    className="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-amber-500"
                  />
                </label>

                <div>
                  <div className="mb-3 flex flex-wrap items-center justify-between gap-3">
                    <div>
                      <h2 className="text-sm font-medium text-gray-900">対象圃場一覧</h2>
                      <p className="text-xs text-gray-500">
                        {selectedCount} / {candidates.length} 圃場を選択中 / 合計 {selectedAreaTan.toFixed(2)}反
                      </p>
                    </div>
                    <div className="flex gap-2">
                      <button
                        onClick={handleSelectAll}
                        className="rounded border border-gray-300 px-3 py-1.5 text-xs text-gray-700 hover:bg-gray-100"
                      >
                        全選択
                      </button>
                      <button
                        onClick={handleClearAll}
                        className="rounded border border-gray-300 px-3 py-1.5 text-xs text-gray-700 hover:bg-gray-100"
                      >
                        全解除
                      </button>
                    </div>
                  </div>

                  {formLoading ? (
                    <div className="rounded-lg border border-dashed border-gray-300 px-4 py-8 text-sm text-gray-500">
                      候補圃場を読み込み中...
                    </div>
                  ) : candidates.length === 0 ? (
                    <div className="rounded-lg border border-dashed border-gray-300 px-4 py-8 text-sm text-gray-400">
                      この年度の水稲作付け圃場がありません。
                    </div>
                  ) : (
                    <div className="overflow-hidden rounded-lg border border-gray-200">
                      <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">
                              <button
                                type="button"
                                onClick={() => handleSort('field_name')}
                                className="inline-flex items-center gap-1 hover:text-gray-900"
                              >
                                圃場
                                {renderSortIcon('field_name')}
                              </button>
                            </th>
                            <th className="px-4 py-3 text-left font-medium text-gray-700">
                              <button
                                type="button"
                                onClick={() => handleSort('field_area_tan')}
                                className="inline-flex items-center gap-1 hover:text-gray-900"
                              >
                                面積
                                {renderSortIcon('field_area_tan')}
                              </button>
                            </th>
                            <th className="px-4 py-3 text-left font-medium text-gray-700">
                              <button
                                type="button"
                                onClick={() => handleSort('group_name')}
                                className="inline-flex items-center gap-1 hover:text-gray-900"
                              >
                                グループ
                                {renderSortIcon('group_name')}
                              </button>
                            </th>
                            <th className="px-4 py-3 text-left font-medium text-gray-700">
                              <button
                                type="button"
                                onClick={() => handleSort('variety_name')}
                                className="inline-flex items-center gap-1 hover:text-gray-900"
                              >
                                品種
                                {renderSortIcon('variety_name')}
                              </button>
                            </th>
                          </tr>
                        </thead>
                        <tbody className="divide-y divide-gray-100">
                          {sortedCandidates.map((candidate) => {
                            const checked = form.selectedFieldIds.has(candidate.field_id);
                            return (
                              <tr key={candidate.field_id} className={checked ? 'bg-amber-50/40' : ''}>
                                <td className="px-4 py-3">
                                  <input
                                    type="checkbox"
                                    checked={checked}
                                    onChange={() => handleToggleField(candidate.field_id)}
                                    className="h-4 w-4 rounded border-gray-300 text-amber-600 focus:ring-amber-500"
                                  />
                                </td>
                                <td className="px-4 py-3 font-medium text-gray-900">{candidate.field_name}</td>
                                <td className="px-4 py-3 text-gray-700">{candidate.field_area_tan}反</td>
                                <td className="px-4 py-3 text-gray-700">{candidate.group_name || '-'}</td>
                                <td className="px-4 py-3 text-gray-700">{candidate.variety_name || '（未設定）'}</td>
                              </tr>
                            );
                          })}
                        </tbody>
                      </table>
                    </div>
                  )}
                </div>

                <div className="flex flex-wrap items-center gap-3">
                  <button
                    onClick={() => void handleSave()}
                    disabled={saving || formLoading}
                    className="inline-flex items-center gap-2 rounded-lg bg-amber-600 px-4 py-2 text-sm font-medium text-white hover:bg-amber-700 disabled:cursor-not-allowed disabled:opacity-60"
                  >
                    <Save className="h-4 w-4" />
                    保存
                  </button>
                  {editingSessionId && (
                    <button
                      onClick={() => void handleDelete()}
                      disabled={saving}
                      className="inline-flex items-center gap-2 rounded-lg border border-red-300 px-4 py-2 text-sm font-medium text-red-700 hover:bg-red-50 disabled:cursor-not-allowed disabled:opacity-60"
                    >
                      <Trash2 className="h-4 w-4" />
                      削除
                    </button>
                  )}
                </div>
              </div>
            )}
          </section>
        </div>
      </main>
    </div>
  );
}
