'use client';

import { useEffect, useMemo, useState } from 'react';
import { useRouter } from 'next/navigation';
import { ChevronLeft, Save } from 'lucide-react';

import Navbar from '@/components/Navbar';
import { api } from '@/lib/api';
import { Crop, Field, RiceTransplantPlan, StockSummary, Variety } from '@/types';

type BoxMap = Record<number, string>;

const currentYear = new Date().getFullYear();

export default function RiceTransplantEditPage({ planId }: { planId?: number }) {
  const router = useRouter();
  const isNew = !planId;

  const [name, setName] = useState('');
  const [year, setYear] = useState(currentYear);
  const [seedMaterialId, setSeedMaterialId] = useState<number | ''>('');
  const [seedlingBoxesPerTan, setSeedlingBoxesPerTan] = useState('');
  const [defaultSeedGramsPerBox, setDefaultSeedGramsPerBox] = useState('200');
  const [notes, setNotes] = useState('');

  const [crops, setCrops] = useState<Crop[]>([]);
  const [allFields, setAllFields] = useState<Field[]>([]);
  const [candidateFields, setCandidateFields] = useState<Field[]>([]);
  const [selectedFields, setSelectedFields] = useState<Field[]>([]);
  const [seedStocks, setSeedStocks] = useState<StockSummary[]>([]);

  const [calcBoxes, setCalcBoxes] = useState<BoxMap>({});
  const [adjustedBoxes, setAdjustedBoxes] = useState<BoxMap>({});
  const [boxesRounded, setBoxesRounded] = useState(false);

  const [loading, setLoading] = useState(!isNew);
  const [saving, setSaving] = useState(false);
  const [error, setError] = useState<string | null>(null);

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

  const allVarieties = crops.flatMap((crop: Crop) => crop.varieties);
  const getVarietyBySeedMaterial = (id: number) =>
    allVarieties.find((variety: Variety) => variety.seed_material === id) ?? null;

  const calculateDefaultBoxes = (field: Field, perTan: string) => {
    const areaTan = parseFloat(field.area_tan || '0');
    const boxesPerTan = parseFloat(perTan || '0');
    return Number.isNaN(areaTan * boxesPerTan) ? '' : (areaTan * boxesPerTan).toFixed(1);
  };

  useEffect(() => {
    const init = async () => {
      setError(null);
      try {
        const [cropsRes, fieldsRes, seedStockRes] = await Promise.all([
          api.get('/plans/crops/'),
          api.get('/fields/?ordering=display_order,id'),
          api.get('/materials/stock-summary/?material_type=seed'),
        ]);
        setCrops(cropsRes.data);
        setAllFields(fieldsRes.data);
        setSeedStocks(seedStockRes.data);

        if (!isNew && planId) {
          const planRes = await api.get(`/plans/rice-transplant-plans/${planId}/`);
          const plan: RiceTransplantPlan = planRes.data;
          const fetchedVarieties = cropsRes.data.flatMap((crop: Crop) => crop.varieties);
          const linkedVariety =
            fetchedVarieties.find((variety: Variety) => variety.id === plan.variety) ?? null;
          setName(plan.name);
          setYear(plan.year);
          setSeedMaterialId(linkedVariety?.seed_material ?? '');
          setSeedlingBoxesPerTan(plan.seedling_boxes_per_tan);
          setDefaultSeedGramsPerBox(plan.default_seed_grams_per_box);
          setNotes(plan.notes);

          const fieldIds = new Set(plan.entries.map((entry) => entry.field));
          const planFields = fieldsRes.data.filter((field: Field) => fieldIds.has(field.id));
          setSelectedFields(planFields);
          setCandidateFields(planFields);

          const nextAdjusted: BoxMap = {};
          const nextCalc: BoxMap = {};
          plan.entries.forEach((entry) => {
            nextAdjusted[entry.field] = Number(entry.installed_seedling_boxes).toFixed(1);
            nextCalc[entry.field] = Number(entry.default_seedling_boxes).toFixed(1);
          });
          setAdjustedBoxes(nextAdjusted);
          setCalcBoxes(nextCalc);
        }
      } catch (e) {
        console.error(e);
        setError('データの読み込みに失敗しました。');
      } finally {
        setLoading(false);
      }
    };
    init();
  }, [isNew, planId]);

  useEffect(() => {
    const fetchCandidates = async () => {
      const selectedVariety = seedMaterialId ? getVarietyBySeedMaterial(seedMaterialId) : null;
      if (!selectedVariety || !year || (!isNew && loading)) return;
      try {
        const res = await api.get(
          `/plans/rice-transplant-plans/candidate_fields/?year=${year}&variety_id=${selectedVariety.id}`
        );
        const nextCandidates: Field[] = res.data;
        setCandidateFields(nextCandidates);
        if (isNew) {
          setSelectedFields(nextCandidates);
        }
      } catch (e) {
        console.error(e);
        setError('候補圃場の取得に失敗しました。');
      }
    };
    fetchCandidates();
  }, [seedMaterialId, year, isNew, loading]);

  useEffect(() => {
    if (!seedMaterialId) return;
    const variety = getVarietyBySeedMaterial(seedMaterialId);
    if (!variety) return;
    if (seedlingBoxesPerTan === '') {
      setSeedlingBoxesPerTan(variety.default_seedling_boxes_per_tan);
    }
  }, [seedMaterialId, crops, seedlingBoxesPerTan]);

  useEffect(() => {
    const nextCalc: BoxMap = {};
    selectedFields.forEach((field) => {
      nextCalc[field.id] = calculateDefaultBoxes(field, seedlingBoxesPerTan);
    });
    setCalcBoxes(nextCalc);
    setBoxesRounded(false);
  }, [selectedFields, seedlingBoxesPerTan]);

  const addField = (field: Field) => {
    if (selectedFields.some((selected) => selected.id === field.id)) return;
    setSelectedFields((prev) => [...prev, field]);
  };

  const removeField = (fieldId: number) => {
    setSelectedFields((prev) => prev.filter((field) => field.id !== fieldId));
    setCalcBoxes((prev) => {
      const next = { ...prev };
      delete next[fieldId];
      return next;
    });
    setAdjustedBoxes((prev) => {
      const next = { ...prev };
      delete next[fieldId];
      return next;
    });
  };

  const updateBoxCount = (fieldId: number, value: string) => {
    setAdjustedBoxes((prev) => ({
      ...prev,
      [fieldId]: value,
    }));
  };

  const applyColumnDefaults = () => {
    setAdjustedBoxes((prev) => {
      const next = { ...prev };
      selectedFields.forEach((field) => {
        next[field.id] = calcBoxes[field.id] ?? '';
      });
      return next;
    });
    setBoxesRounded(false);
  };

  const toggleRoundColumn = () => {
    if (boxesRounded) {
      setAdjustedBoxes((prev) => {
        const next = { ...prev };
        selectedFields.forEach((field) => {
          delete next[field.id];
        });
        return next;
      });
      setBoxesRounded(false);
      return;
    }

    setAdjustedBoxes((prev) => {
      const next = { ...prev };
      selectedFields.forEach((field) => {
        const raw = calcBoxes[field.id] ?? prev[field.id];
        if (!raw) return;
        const value = parseFloat(raw);
        if (Number.isNaN(value)) return;
        next[field.id] = String(Math.round(value));
      });
      return next;
    });
    setBoxesRounded(true);
  };

  const effectiveBoxes = (fieldId: number) => {
    const raw =
      adjustedBoxes[fieldId] !== undefined && adjustedBoxes[fieldId] !== ''
        ? adjustedBoxes[fieldId]
        : calcBoxes[fieldId];
    const value = parseFloat(raw ?? '0');
    return Number.isNaN(value) ? 0 : value;
  };

  const selectedSeedStock = seedMaterialId
    ? seedStocks.find((item) => item.material_id === seedMaterialId) ?? null
    : null;
  const selectedVariety = seedMaterialId ? getVarietyBySeedMaterial(seedMaterialId) : null;

  const totalBoxes = selectedFields.reduce((sum, field) => sum + effectiveBoxes(field.id), 0);
  const seedGrams = parseFloat(defaultSeedGramsPerBox || '0');
  const totalSeedKg = seedGrams > 0 ? (totalBoxes * seedGrams) / 1000 : 0;
  const seedInventoryKg = parseFloat(selectedSeedStock?.current_stock ?? '0');
  const remainingSeedKg = seedInventoryKg - totalSeedKg;

  const handleSave = async () => {
    setError(null);
    if (!name.trim()) {
      setError('計画名を入力してください。');
      return;
    }
    if (!seedMaterialId) {
      setError('種子資材を選択してください。');
      return;
    }
    if (!selectedVariety) {
      setError('選択した種子資材に対応する品種が未設定です。資材マスタで紐付けてください。');
      return;
    }
    if (selectedFields.length === 0) {
      setError('圃場を1つ以上選択してください。');
      return;
    }

    const entries = selectedFields.map((field) => ({
      field_id: field.id,
      installed_seedling_boxes: effectiveBoxes(field.id).toFixed(2),
    }));

    const payload = {
      name,
      year,
      variety: selectedVariety.id,
      seedling_boxes_per_tan: seedlingBoxesPerTan || '0',
      default_seed_grams_per_box: defaultSeedGramsPerBox || '0',
      notes,
      entries,
    };

    setSaving(true);
    try {
      if (isNew) {
        await api.post('/plans/rice-transplant-plans/', payload);
      } else {
        await api.put(`/plans/rice-transplant-plans/${planId}/`, payload);
      }
      router.push('/rice-transplant');
    } catch (e) {
      console.error(e);
      setError('保存に失敗しました。');
    } finally {
      setSaving(false);
    }
  };

  const unselectedFields = (candidateFields.length > 0 ? candidateFields : allFields).filter(
    (field) => !selectedFields.some((selected) => selected.id === field.id)
  );

  const fieldRows = useMemo(
    () =>
      selectedFields.map((field) => ({
        field,
        defaultBoxes: calcBoxes[field.id] ?? '',
        boxCount:
          adjustedBoxes[field.id] !== undefined && adjustedBoxes[field.id] !== ''
            ? adjustedBoxes[field.id]
            : calcBoxes[field.id] ?? '',
      })),
    [selectedFields, calcBoxes, adjustedBoxes]
  );

  if (loading) {
    return (
      <div className="min-h-screen bg-gray-50">
        <Navbar />
        <div className="mx-auto max-w-6xl px-4 py-8 text-gray-500">読み込み中...</div>
      </div>
    );
  }

  return (
    <div className="min-h-screen bg-gray-50">
      <Navbar />
      <div className="mx-auto max-w-6xl px-4 py-8">
        <div className="mb-6 flex items-center justify-between">
          <div className="flex items-center gap-3">
            <button
              onClick={() => router.push('/rice-transplant')}
              className="text-gray-500 hover:text-gray-700"
            >
              <ChevronLeft className="h-5 w-5" />
            </button>
            <h1 className="text-2xl font-bold text-gray-800">
              {isNew ? '田植え計画 新規作成' : '田植え計画 編集'}
            </h1>
          </div>
          <button
            onClick={handleSave}
            disabled={saving}
            className="flex items-center gap-2 rounded-lg bg-green-600 px-4 py-2 text-white hover:bg-green-700 disabled:cursor-not-allowed disabled:opacity-50"
          >
            <Save className="h-4 w-4" />
            {saving ? '保存中...' : '保存'}
          </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>
        )}

        <div className="mb-4 grid gap-4 rounded-lg bg-white p-4 shadow md:grid-cols-2 xl:grid-cols-5">
          <div className="xl:col-span-2">
            <label className="mb-1 block text-xs font-medium text-gray-600">計画名</label>
            <input
              value={name}
              onChange={(e) => setName(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"
              placeholder="例: 2026年度 にこまる 第1回"
            />
            <p className="mt-1 text-xs text-gray-500">
              同じ年度・同じ品種でも、第1回や播種日ごとに複数計画を作れます。
            </p>
          </div>
          <div>
            <label className="mb-1 block text-xs font-medium text-gray-600">年度</label>
            <select
              value={year}
              onChange={(e) => setYear(parseInt(e.target.value, 10))}
              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"
            >
              {years.map((value) => (
                <option key={value} value={value}>
                  {value}年度
                </option>
              ))}
            </select>
          </div>
          <div>
            <label className="mb-1 block text-xs font-medium text-gray-600">種子資材</label>
            <select
              value={seedMaterialId}
              onChange={(e) =>
                setSeedMaterialId(e.target.value ? parseInt(e.target.value, 10) : '')
              }
              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"
            >
              <option value="">選択してください</option>
              {seedStocks.map((stock) => (
                <option key={stock.material_id} value={stock.material_id}>
                  {stock.name}
                </option>
              ))}
            </select>
          </div>
          <div>
            <label className="mb-1 block text-xs font-medium text-gray-600">
              苗箱1枚あたり種もみ(g)
            </label>
            <input
              value={defaultSeedGramsPerBox}
              onChange={(e) => setDefaultSeedGramsPerBox(e.target.value)}
              className="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm text-right focus:outline-none focus:ring-2 focus:ring-green-500"
              inputMode="decimal"
            />
          </div>
        </div>

        <div className="mb-4 rounded-lg bg-white p-4 shadow">
          <div className="mb-3 flex items-center justify-between">
            <h2 className="text-sm font-semibold text-gray-800">対象圃場</h2>
          </div>

          <div className="mb-3 flex flex-wrap gap-2">
            {selectedFields.map((field) => (
              <button
                key={field.id}
                onClick={() => removeField(field.id)}
                className="rounded-full border border-green-200 bg-green-50 px-3 py-1 text-xs text-green-800"
              >
                {field.name} ×
              </button>
            ))}
            {selectedFields.length === 0 && (
              <p className="text-sm text-gray-500">圃場が選択されていません。</p>
            )}
          </div>

          {unselectedFields.length > 0 && (
            <div>
              <p className="mb-2 text-xs font-medium text-gray-500">追加可能</p>
              <div className="flex flex-wrap gap-2">
                {unselectedFields.map((field) => (
                  <button
                    key={field.id}
                    onClick={() => addField(field)}
                    className="rounded-full border border-gray-200 bg-gray-50 px-3 py-1 text-xs text-gray-700 hover:bg-gray-100"
                  >
                    {field.name}
                  </button>
                ))}
              </div>
            </div>
          )}
        </div>

        <div className="mb-4 grid gap-4 md:grid-cols-[2fr,1fr]">
          <div className="rounded-lg bg-white p-4 shadow">
            <label className="mb-1 block text-xs font-medium text-gray-600">備考</label>
            <textarea
              value={notes}
              onChange={(e) => setNotes(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-green-500"
            />
          </div>

          <div className="rounded-lg bg-white p-4 shadow">
            <h2 className="mb-3 text-sm font-semibold text-gray-800">集計</h2>
            <div className="space-y-2 text-sm">
              <div className="flex justify-between text-gray-600">
                <span>対象圃場</span>
                <span>{selectedFields.length}筆</span>
              </div>
              <div className="flex justify-between text-gray-600">
                <span>苗箱合計</span>
                <span>{totalBoxes.toFixed(1)}枚</span>
              </div>
              <div className="flex justify-between text-gray-600">
                <span>必要種もみ量</span>
                <span>{totalSeedKg.toFixed(3)}kg</span>
              </div>
              <div className="flex justify-between text-gray-600">
                <span>{selectedSeedStock?.name || '種子在庫未設定'}</span>
                <span>{seedInventoryKg.toFixed(3)}kg</span>
              </div>
              <div
                className={`flex justify-between font-semibold ${
                  remainingSeedKg < 0 ? 'text-red-600' : 'text-emerald-700'
                }`}
              >
                <span>残在庫見込み</span>
                <span>{remainingSeedKg.toFixed(3)}kg</span>
              </div>
            </div>
          </div>
        </div>

        <div className="overflow-hidden rounded-lg bg-white shadow">
          <table className="w-full text-sm">
            <thead className="border-b 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-right font-medium text-gray-700">面積(反)</th>
                <th className="px-4 py-3 text-center font-medium text-gray-700">
                  <div>苗箱数</div>
                  <div className="mt-1 space-y-0.5 text-[11px] font-normal leading-4">
                    <div className="text-gray-500">反当 {seedlingBoxesPerTan || '0'}枚</div>
                    <div className="text-gray-500">合計 {totalBoxes.toFixed(1)}枚</div>
                  </div>
                  <span className="mt-1 flex items-center justify-center gap-1.5 text-xs font-normal text-gray-400">
                    （枚）
                    <button
                      onClick={toggleRoundColumn}
                      className={`inline-flex h-5 w-5 items-center justify-center rounded font-bold leading-none ${
                        boxesRounded
                          ? 'bg-amber-100 text-amber-600 hover:bg-amber-200'
                          : 'bg-blue-100 text-blue-500 hover:bg-blue-200'
                      }`}
                      title={boxesRounded ? '元の計算値に戻す' : '四捨五入して整数に丸める'}
                    >
                      {boxesRounded ? '↩' : '≈'}
                    </button>
                  </span>
                </th>
              </tr>
              <tr>
                <th className="border-t border-gray-200 px-4 py-2 text-left text-xs font-medium text-gray-500">
                  反当苗箱枚数
                </th>
                <th className="border-t border-gray-200 px-4 py-2" />
                <th className="border-t border-gray-200 px-4 py-2 text-right">
                  <div className="flex items-center justify-end gap-2">
                    <input
                      value={seedlingBoxesPerTan}
                      onChange={(e) => setSeedlingBoxesPerTan(e.target.value)}
                      className="w-24 rounded border border-gray-300 px-2 py-1 text-right text-sm focus:outline-none focus:ring-1 focus:ring-green-400"
                      inputMode="decimal"
                    />
                    <button
                      type="button"
                      onClick={applyColumnDefaults}
                      className="rounded border border-blue-300 px-3 py-1 text-xs text-blue-700 hover:bg-blue-50"
                    >
                      反映
                    </button>
                  </div>
                </th>
              </tr>
            </thead>
            <tbody className="divide-y divide-gray-100">
              {fieldRows.map(({ field, defaultBoxes, boxCount }) => (
                <tr key={field.id} className="hover:bg-gray-50">
                  <td className="px-4 py-3 font-medium text-gray-900">{field.name}</td>
                  <td className="px-4 py-3 text-right tabular-nums text-gray-600">
                    {Number(field.area_tan).toFixed(2)}
                  </td>
                  <td className="px-4 py-3">
                    <div className="flex items-center justify-end gap-3">
                      <span className="text-xs tabular-nums text-gray-500">
                        既定 {defaultBoxes || '0.0'}枚
                      </span>
                      <input
                        value={boxCount}
                        onChange={(e) => updateBoxCount(field.id, e.target.value)}
                        className="w-24 rounded-md border border-gray-300 px-2 py-1 text-right focus:outline-none focus:ring-2 focus:ring-green-500"
                        inputMode="decimal"
                      />
                    </div>
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      </div>
    </div>
  );
}
