import { useState, useMemo, useRef } from 'react';
import { useStore } from '../store';
import type { BackupData } from '../store';
import { ACCOUNT_TYPE_LABELS } from '../utils/accounts';

type Tab = 'category' | 'institution' | 'backup';

export default function SettingsPage() {
  const {
    accounts, categoryMappings, institutionMappings,
    upsertCategoryMapping, upsertInstitutionMapping,
    mergeDefaultMappings, mergeDefaultAccounts,
    transactions, openingBalances, importedIds, rawRecords, transferOverrides,
    restoreFromBackup,
  } = useStore();

  const [tab, setTab] = useState<Tab>('category');
  const [editCategory, setEditCategory] = useState('');
  const [editSubCategory, setEditSubCategory] = useState('');
  const [editAccountId, setEditAccountId] = useState('');
  const [editInstitution, setEditInstitution] = useState('');
  const [editInstAccountId, setEditInstAccountId] = useState('');
  const [saved, setSaved] = useState(false);
  const [restoreError, setRestoreError] = useState('');
  const [restoreSuccess, setRestoreSuccess] = useState(false);
  const fileInputRef = useRef<HTMLInputElement>(null);

  // データ内に登場する全カテゴリを抽出（マッピング未設定のものを強調）
  const allCategories = useMemo(() => {
    const cats = new Map<string, Set<string>>();
    for (const tx of transactions) {
      if (!tx.mfCategory) continue;
      if (!cats.has(tx.mfCategory)) cats.set(tx.mfCategory, new Set());
      if (tx.mfSubCategory) cats.get(tx.mfCategory)!.add(tx.mfSubCategory);
    }
    return cats;
  }, [transactions]);

  const allInstitutions = useMemo(() => {
    return [...new Set(transactions.map(tx => tx.mfInstitution ?? '').filter(Boolean))];
  }, [transactions]);

  const expenseIncomeAccounts = accounts.filter(
    a => a.type === 'expense' || a.type === 'income'
  );
  const flash = () => {
    setSaved(true);
    setTimeout(() => setSaved(false), 1500);
  };

  const handleExport = () => {
    const backup: BackupData = {
      version: 1,
      exportedAt: new Date().toISOString(),
      accounts,
      transactions,
      categoryMappings,
      institutionMappings,
      openingBalances,
      importedIds,
      rawRecords,
      transferOverrides,
    };
    const json = JSON.stringify(backup, null, 2);
    const blob = new Blob([json], { type: 'application/json' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    const dateStr = new Date().toISOString().slice(0, 10);
    a.href = url;
    a.download = `household-backup-${dateStr}.json`;
    a.click();
    URL.revokeObjectURL(url);
  };

  const handleImport = (e: React.ChangeEvent<HTMLInputElement>) => {
    setRestoreError('');
    setRestoreSuccess(false);
    const file = e.target.files?.[0];
    if (!file) return;
    const reader = new FileReader();
    reader.onload = (ev) => {
      try {
        const data = JSON.parse(ev.target?.result as string) as BackupData;
        if (data.version !== 1) throw new Error('バージョンが異なります');
        if (!Array.isArray(data.transactions)) throw new Error('データ形式が不正です');
        if (!window.confirm(
          `このバックアップを復元しますか？\n` +
          `日時: ${new Date(data.exportedAt).toLocaleString()}\n` +
          `仕訳件数: ${data.transactions.length}件\n\n` +
          `現在のデータはすべて上書きされます。`
        )) return;
        restoreFromBackup(data);
        setRestoreSuccess(true);
        setTimeout(() => setRestoreSuccess(false), 3000);
      } catch (err) {
        setRestoreError(err instanceof Error ? err.message : '読み込みに失敗しました');
      } finally {
        if (fileInputRef.current) fileInputRef.current.value = '';
      }
    };
    reader.readAsText(file, 'utf-8');
  };

  const handleSaveCategory = () => {
    if (!editCategory || !editAccountId) return;
    upsertCategoryMapping({
      mfCategory: editCategory,
      mfSubCategory: editSubCategory,
      accountId: editAccountId,
    });
    setEditCategory('');
    setEditSubCategory('');
    setEditAccountId('');
    flash();
  };

  const handleSaveInstitution = () => {
    if (!editInstitution || !editInstAccountId) return;
    upsertInstitutionMapping({
      institution: editInstitution,
      accountId: editInstAccountId,
    });
    setEditInstitution('');
    setEditInstAccountId('');
    flash();
  };

  const findCurrentMapping = (cat: string, sub: string) => {
    const m = categoryMappings.find(
      m => m.mfCategory === cat && m.mfSubCategory === sub
    ) ?? categoryMappings.find(
      m => m.mfCategory === cat && m.mfSubCategory === ''
    );
    if (!m) return null;
    if (m.accountId === '_skip_') return 'スキップ（資産間移動）';
    return accounts.find(a => a.id === m.accountId)?.name ?? m.accountId;
  };

  return (
    <div className="p-6 space-y-6">
      <div className="flex items-center justify-between">
        <h2 className="text-xl font-bold text-slate-100">設定・マッピング</h2>
        <div className="flex items-center gap-3">
          {saved && (
            <span className="text-sm text-emerald-400 font-medium">✅ 保存しました</span>
          )}
          <button
            onClick={() => {
              mergeDefaultAccounts();
              mergeDefaultMappings();
              flash();
            }}
            className="px-3 py-1.5 text-sm bg-indigo-900/50 text-indigo-300 border border-indigo-700 rounded-md hover:bg-indigo-800"
          >
            デフォルトを再適用
          </button>
        </div>
      </div>

      {/* タブ */}
      <div className="flex gap-1 border-b border-slate-700">
        {([['category', 'カテゴリ → 勘定科目'], ['institution', '金融機関 → 資産勘定'], ['backup', 'バックアップ']] as [Tab, string][]).map(
          ([t, label]) => (
            <button
              key={t}
              onClick={() => setTab(t)}
              className={`px-4 py-2 text-sm font-medium border-b-2 transition-colors ${
                tab === t
                  ? 'border-indigo-500 text-indigo-400'
                  : 'border-transparent text-slate-500 hover:text-slate-300'
              }`}
            >
              {label}
            </button>
          )
        )}
      </div>

      {tab === 'category' && (
        <div className="space-y-4">
          <p className="text-sm text-slate-400">
            MoneyForwardの大項目・中項目を費用/収益の勘定科目に対応付けます。
          </p>

          {/* 新規追加フォーム */}
          <div className="card">
            <h3 className="text-sm font-semibold text-slate-400 mb-3">マッピングを追加・上書き</h3>
            <div className="flex gap-2 items-end flex-wrap">
              <div>
                <label className="block text-xs text-slate-500 mb-1">大項目</label>
                <input
                  type="text"
                  value={editCategory}
                  onChange={e => setEditCategory(e.target.value)}
                  list="category-list"
                  className="border rounded px-2 py-1.5 text-sm w-36"
                  placeholder="食費"
                />
                <datalist id="category-list">
                  {[...allCategories.keys()].map(c => (
                    <option key={c} value={c} />
                  ))}
                </datalist>
              </div>
              <div>
                <label className="block text-xs text-slate-500 mb-1">中項目（空=大項目全体）</label>
                <input
                  type="text"
                  value={editSubCategory}
                  onChange={e => setEditSubCategory(e.target.value)}
                  list="subcategory-list"
                  className="border rounded px-2 py-1.5 text-sm w-36"
                  placeholder="外食（任意）"
                />
                <datalist id="subcategory-list">
                  {editCategory && allCategories.get(editCategory)
                    ? [...allCategories.get(editCategory)!].map(s => (
                        <option key={s} value={s} />
                      ))
                    : null}
                </datalist>
              </div>
              <div>
                <label className="block text-xs text-slate-500 mb-1">勘定科目</label>
                <select
                  value={editAccountId}
                  onChange={e => setEditAccountId(e.target.value)}
                  className="border rounded px-2 py-1.5 text-sm w-44"
                >
                  <option value="">選択してください</option>
                  <option value="_skip_">⏭ スキップ（資産間移動）</option>
                  {(['income', 'expense'] as const).map(type => (
                    <optgroup key={type} label={ACCOUNT_TYPE_LABELS[type]}>
                      {expenseIncomeAccounts
                        .filter(a => a.type === type)
                        .map(a => (
                          <option key={a.id} value={a.id}>{a.name}</option>
                        ))}
                    </optgroup>
                  ))}
                </select>
              </div>
              <button
                onClick={handleSaveCategory}
                disabled={!editCategory || !editAccountId}
                className="px-4 py-1.5 bg-indigo-600 text-white text-sm rounded-md hover:bg-indigo-700 disabled:opacity-40"
              >
                保存
              </button>
            </div>
          </div>

          {/* データ内カテゴリ一覧 */}
          {allCategories.size > 0 && (
            <div className="card">
              <h3 className="text-sm font-semibold text-slate-400 mb-3">
                データ内のカテゴリ（クリックで編集欄へ）
              </h3>
              <div className="space-y-2">
                {[...allCategories.entries()].map(([cat, subs]) => {
                  const subList = ['', ...[...subs]];
                  return subList.map(sub => {
                    const mapped = findCurrentMapping(cat, sub);
                    return (
                      <div
                        key={`${cat}-${sub}`}
                        onClick={() => { setEditCategory(cat); setEditSubCategory(sub); }}
                        className="flex items-center justify-between py-1 px-2 rounded hover:bg-slate-700 cursor-pointer"
                      >
                        <div className="flex items-center gap-2">
                          <span className="text-sm text-slate-300">{cat}</span>
                          {sub && (
                            <>
                              <span className="text-slate-600">/</span>
                              <span className="text-sm text-slate-400">{sub}</span>
                            </>
                          )}
                          {!sub && <span className="text-xs text-slate-600">（大項目全体）</span>}
                        </div>
                        <span className={`text-xs px-2 py-0.5 rounded-full ${
                          mapped ? 'bg-emerald-900/50 text-emerald-400' : 'bg-amber-900/50 text-amber-400'
                        }`}>
                          {mapped ?? '未設定'}
                        </span>
                      </div>
                    );
                  });
                })}
              </div>
            </div>
          )}

          {/* 現在のマッピング一覧 */}
          <div className="card">
            <h3 className="text-sm font-semibold text-slate-400 mb-3">現在のマッピング（全件）</h3>
            <div className="max-h-64 overflow-y-auto">
              <table className="w-full text-sm">
                <thead className="sticky top-0 bg-slate-800">
                  <tr className="border-b border-slate-700">
                    <th className="table-th">大項目</th>
                    <th className="table-th">中項目</th>
                    <th className="table-th">勘定科目</th>
                  </tr>
                </thead>
                <tbody>
                  {categoryMappings.map((m, i) => (
                    <tr
                      key={i}
                      className="border-b border-slate-700/50 hover:bg-slate-700 cursor-pointer"
                      onClick={() => {
                        setEditCategory(m.mfCategory);
                        setEditSubCategory(m.mfSubCategory);
                        setEditAccountId(m.accountId);
                      }}
                    >
                      <td className="table-td">{m.mfCategory}</td>
                      <td className="table-td text-slate-500">{m.mfSubCategory || '（全体）'}</td>
                      <td className={`table-td ${m.accountId === '_skip_' ? 'text-slate-500 italic' : 'text-indigo-400'}`}>
                        {m.accountId === '_skip_'
                          ? 'スキップ（資産間移動）'
                          : accounts.find(a => a.id === m.accountId)?.name ?? m.accountId}
                      </td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
          </div>
        </div>
      )}

      {tab === 'backup' && (
        <div className="space-y-4">
          <p className="text-sm text-slate-400">
            全データをJSONファイルに保存・復元します。ブラウザのデータが消えた場合の備えとして定期的にエクスポートしてください。
          </p>

          {/* エクスポート */}
          <div className="card space-y-3">
            <h3 className="text-sm font-semibold text-slate-300">エクスポート（バックアップ作成）</h3>
            <div className="text-sm text-slate-400 space-y-1">
              <div>仕訳件数: <span className="text-slate-200">{transactions.length.toLocaleString()} 件</span></div>
              <div>勘定科目: <span className="text-slate-200">{accounts.length} 件</span></div>
              <div>カテゴリマッピング: <span className="text-slate-200">{categoryMappings.length} 件</span></div>
            </div>
            <button
              onClick={handleExport}
              className="px-4 py-2 bg-indigo-600 text-white text-sm rounded-md hover:bg-indigo-700"
            >
              JSONをダウンロード
            </button>
          </div>

          {/* インポート（復元） */}
          <div className="card space-y-3">
            <h3 className="text-sm font-semibold text-slate-300">インポート（バックアップから復元）</h3>
            <p className="text-xs text-amber-400">
              現在のデータはすべて上書きされます。復元前に必ずエクスポートで保存してください。
            </p>
            <input
              ref={fileInputRef}
              type="file"
              accept=".json"
              onChange={handleImport}
              className="block text-sm text-slate-400 file:mr-3 file:py-1.5 file:px-3 file:rounded file:border-0 file:text-sm file:bg-slate-700 file:text-slate-200 hover:file:bg-slate-600 cursor-pointer"
            />
            {restoreError && (
              <p className="text-sm text-red-400">エラー: {restoreError}</p>
            )}
            {restoreSuccess && (
              <p className="text-sm text-emerald-400">復元しました</p>
            )}
          </div>
        </div>
      )}

      {tab === 'institution' && (
        <div className="space-y-4">
          <p className="text-sm text-slate-400">
            MoneyForwardの保有金融機関を資産勘定科目に対応付けます。
          </p>

          {/* 新規追加フォーム */}
          <div className="card">
            <h3 className="text-sm font-semibold text-slate-400 mb-3">マッピングを追加・上書き</h3>
            <div className="flex gap-2 items-end">
              <div>
                <label className="block text-xs text-slate-500 mb-1">保有金融機関</label>
                <input
                  type="text"
                  value={editInstitution}
                  onChange={e => setEditInstitution(e.target.value)}
                  list="institution-list"
                  className="border rounded px-2 py-1.5 text-sm w-52"
                  placeholder="SBI銀行"
                />
                <datalist id="institution-list">
                  {allInstitutions.map(inst => (
                    <option key={inst} value={inst} />
                  ))}
                </datalist>
              </div>
              <div>
                <label className="block text-xs text-slate-500 mb-1">資産勘定科目</label>
                <select
                  value={editInstAccountId}
                  onChange={e => setEditInstAccountId(e.target.value)}
                  className="border rounded px-2 py-1.5 text-sm w-44"
                >
                  <option value="">選択してください</option>
                  {(['asset', 'liability'] as const).map(type => (
                    <optgroup key={type} label={ACCOUNT_TYPE_LABELS[type]}>
                      {accounts.filter(a => a.type === type).map(a => (
                        <option key={a.id} value={a.id}>{a.name}</option>
                      ))}
                    </optgroup>
                  ))}
                </select>
              </div>
              <button
                onClick={handleSaveInstitution}
                disabled={!editInstitution || !editInstAccountId}
                className="px-4 py-1.5 bg-indigo-600 text-white text-sm rounded-md hover:bg-indigo-700 disabled:opacity-40"
              >
                保存
              </button>
            </div>
          </div>

          {/* データ内金融機関 */}
          {allInstitutions.length > 0 && (
            <div className="card">
              <h3 className="text-sm font-semibold text-slate-400 mb-3">データ内の金融機関</h3>
              <div className="space-y-1">
                {allInstitutions.map(inst => {
                  const m = institutionMappings.find(im => im.institution === inst);
                  const accName = m ? accounts.find(a => a.id === m.accountId)?.name : null;
                  return (
                    <div
                      key={inst}
                      onClick={() => setEditInstitution(inst)}
                      className="flex items-center justify-between py-1 px-2 rounded hover:bg-slate-700 cursor-pointer"
                    >
                      <span className="text-sm text-slate-300">{inst}</span>
                      <span className={`text-xs px-2 py-0.5 rounded-full ${
                        accName ? 'bg-emerald-900/50 text-emerald-400' : 'bg-amber-900/50 text-amber-400'
                      }`}>
                        {accName ?? '未設定'}
                      </span>
                    </div>
                  );
                })}
              </div>
            </div>
          )}

          {/* 現在のマッピング */}
          <div className="card">
            <h3 className="text-sm font-semibold text-slate-400 mb-3">現在のマッピング</h3>
            <table className="w-full text-sm">
              <thead>
                <tr className="border-b border-slate-700">
                  <th className="table-th">保有金融機関</th>
                  <th className="table-th">勘定科目</th>
                </tr>
              </thead>
              <tbody>
                {institutionMappings.map((m, i) => (
                  <tr key={i} className="border-b border-slate-700/50 hover:bg-slate-700">
                    <td className="table-td">{m.institution}</td>
                    <td className="table-td text-indigo-400">
                      {accounts.find(a => a.id === m.accountId)?.name ?? m.accountId}
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        </div>
      )}
    </div>
  );
}
