import 'dart:async';

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:uuid/uuid.dart';

import '../models/customer_model.dart';
import '../models/invoice_models.dart';
import '../models/sales_entry_models.dart';
import '../services/app_settings_repository.dart';
import '../services/edit_log_repository.dart';
import '../services/sales_entry_service.dart';
import '../widgets/line_item_editor.dart';
import '../widgets/modal_utils.dart';
import '../widgets/screen_id_title.dart';
import 'customer_picker_modal.dart';
import 'settings_screen.dart';
import 'product_picker_modal.dart';

class SalesEntriesScreen extends StatefulWidget {
  const SalesEntriesScreen({super.key});

  @override
  State<SalesEntriesScreen> createState() => _SalesEntriesScreenState();
}

class _SalesEntriesScreenState extends State<SalesEntriesScreen> {
  final SalesEntryService _service = SalesEntryService();
  final NumberFormat _currencyFormat = NumberFormat.currency(locale: 'ja_JP', symbol: '¥');

  bool _isLoading = true;
  bool _isRefreshing = false;
  List<SalesEntry> _entries = const [];
  SalesEntryStatus? _filterStatus;

  @override
  void initState() {
    super.initState();
    _loadEntries();
  }

  Future<void> _loadEntries() async {
    if (!_isRefreshing) {
      setState(() => _isLoading = true);
    }
    try {
      final entries = await _service.fetchEntries(status: _filterStatus);
      if (!mounted) return;
      setState(() {
        _entries = entries;
        _isLoading = false;
        _isRefreshing = false;
      });
    } catch (e) {
      if (!mounted) return;
      setState(() {
        _isLoading = false;
        _isRefreshing = false;
      });
      ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('売上伝票の取得に失敗しました: $e')));
    }
  }

  

  Future<void> _handleRefresh() async {
    setState(() => _isRefreshing = true);
    await _loadEntries();
  }

  Future<void> _openEditor({SalesEntry? entry}) async {
    final updated = await Navigator.of(context).push<SalesEntry>(
      MaterialPageRoute(builder: (_) => _SalesEntryEditorPage(service: _service, entry: entry)),
    );
    if (updated != null) {
      await _loadEntries();
      if (!mounted) return;
      ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('売上伝票を保存しました')));
    }
  }

  Future<void> _openImportSheet() async {
    final imported = await SalesEntryImportSheet.show(context, _service);
    if (imported != null) {
      await _loadEntries();
      if (!mounted) return;
      ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('伝票をインポートしました: ${imported.subject ?? '売上伝票'}')));
    }
  }

  Future<void> _handleReimport(SalesEntry entry) async {
    try {
      final updated = await _service.reimportEntry(entry.id);
      if (!mounted) return;
      setState(() {
        final index = _entries.indexWhere((e) => e.id == entry.id);
        if (index != -1) {
          _entries = List.of(_entries)..[index] = updated;
        }
      });
      ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('再インポートが完了しました')));
    } catch (e) {
      if (!mounted) return;
      ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('再インポートに失敗しました: $e')));
    }
  }

  Future<void> _confirmDelete(SalesEntry entry) async {
    final confirmed = await showDialog<bool>(
      context: context,
      builder: (context) => AlertDialog(
        title: const Text('伝票を削除'),
        content: Text('${entry.subject ?? '無題'}を削除しますか？'),
        actions: [
          TextButton(onPressed: () => Navigator.pop(context, false), child: const Text('キャンセル')),
          TextButton(onPressed: () => Navigator.pop(context, true), child: const Text('削除')),
        ],
      ),
    );
    if (confirmed != true) return;
    try {
      await _service.deleteEntry(entry.id);
      if (!mounted) return;
      setState(() {
        _entries = _entries.where((e) => e.id != entry.id).toList();
      });
      ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('伝票を削除しました')));
    } catch (e) {
      if (!mounted) return;
      ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('削除に失敗しました: $e')));
    }
  }

  @override
  Widget build(BuildContext context) {
    final body = _isLoading
        ? const Center(child: CircularProgressIndicator())
        : RefreshIndicator(
            onRefresh: _handleRefresh,
            child: _entries.isEmpty
                ? ListView(
                    children: const [
                      SizedBox(height: 120),
                      Icon(Icons.description_outlined, size: 64, color: Colors.grey),
                      SizedBox(height: 12),
                      Center(child: Text('売上伝票がありません。インポートまたは新規作成してください。')),
                    ],
                  )
                : ListView.separated(
                    padding: const EdgeInsets.fromLTRB(16, 16, 16, 120),
                    itemCount: _entries.length,
                    separatorBuilder: (_, index) => const SizedBox(height: 12),
                    itemBuilder: (context, index) => _buildEntryCard(_entries[index]),
                  ),
          );

    return Scaffold(
      backgroundColor: Colors.grey.shade200,
      appBar: AppBar(
        leading: const BackButton(),
        title: const ScreenAppBarTitle(screenId: 'U1', title: '売上伝票'),
        actions: [
          IconButton(onPressed: _openImportSheet, tooltip: 'インポート', icon: const Icon(Icons.download)),
          IconButton(onPressed: () => _openEditor(), tooltip: '新規作成', icon: const Icon(Icons.add)),
          PopupMenuButton<SalesEntryStatus?>(
            tooltip: 'ステータス絞り込み',
            icon: const Icon(Icons.filter_alt),
            onSelected: (value) {
              setState(() => _filterStatus = value);
              _loadEntries();
            },
            itemBuilder: (context) => [
              const PopupMenuItem(value: null, child: Text('すべて表示')),
              ...SalesEntryStatus.values.map(
                (status) => PopupMenuItem(value: status, child: Text(status.displayName)),
              ),
            ],
          ),
        ],
      ),
      body: body,
      floatingActionButton: FloatingActionButton.extended(
        onPressed: _openImportSheet,
        icon: const Icon(Icons.receipt_long),
        label: const Text('伝票インポート'),
      ),
    );
  }

  Widget _buildEntryCard(SalesEntry entry) {
    final amountLabel = _currencyFormat.format(entry.amountTaxIncl);
    final dateLabel = DateFormat('yyyy/MM/dd').format(entry.issueDate);
    final subject = entry.subject?.trim().isNotEmpty == true ? entry.subject!.trim() : '売上伝票';
    final customer = entry.customerNameSnapshot ?? '取引先未設定';

    Color statusColor(SalesEntryStatus status) {
      switch (status) {
        case SalesEntryStatus.draft:
          return Colors.orange;
        case SalesEntryStatus.confirmed:
          return Colors.blue;
        case SalesEntryStatus.settled:
          return Colors.green;
      }
    }

    final baseColor = statusColor(entry.status);
    final statusChip = Container(
      padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 4),
      decoration: BoxDecoration(
        color: baseColor.withAlpha((0.15 * 255).round()),
        borderRadius: BorderRadius.circular(999),
      ),
      child: Text(entry.status.displayName, style: TextStyle(color: baseColor, fontSize: 12)),
    );

    return Card(
      color: Colors.white,
      child: InkWell(
        onTap: () => _openEditor(entry: entry),
        child: Padding(
          padding: const EdgeInsets.all(16),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Row(
                children: [
                  Expanded(
                    child: Text(
                      subject,
                      style: Theme.of(context).textTheme.titleMedium?.copyWith(fontWeight: FontWeight.bold),
                    ),
                  ),
                  statusChip,
                  PopupMenuButton<String>(
                    onSelected: (value) {
                      switch (value) {
                        case 'edit':
                          _openEditor(entry: entry);
                          break;
                        case 'reimport':
                          _handleReimport(entry);
                          break;
                        case 'delete':
                          _confirmDelete(entry);
                          break;
                      }
                    },
                    itemBuilder: (context) => const [
                      PopupMenuItem(value: 'edit', child: Text('編集')),
                      PopupMenuItem(value: 'reimport', child: Text('再インポート')),
                      PopupMenuItem(value: 'delete', child: Text('削除')),
                    ],
                  ),
                ],
              ),
              const SizedBox(height: 8),
              Text(customer, style: Theme.of(context).textTheme.bodyMedium),
              const SizedBox(height: 4),
              Row(
                children: [
                  Text('計上日: $dateLabel'),
                  const Spacer(),
                  Text(amountLabel, style: Theme.of(context).textTheme.titleMedium?.copyWith(fontWeight: FontWeight.bold)),
                ],
              ),
              if (entry.notes?.isNotEmpty == true) ...[
                const SizedBox(height: 8),
                Text(entry.notes!, style: Theme.of(context).textTheme.bodySmall),
              ],
            ],
          ),
        ),
      ),
    );
  }
}

class _EntrySnapshot {
  const _EntrySnapshot({
    required this.customer,
    required this.customerSnapshot,
    required this.subject,
    required this.notes,
    required this.issueDate,
    required this.status,
    required this.cashSaleMode,
    required this.settlementMethod,
    required this.settlementCardCompany,
    required this.settlementDueDate,
    required this.lines,
  });

  final Customer? customer;
  final String? customerSnapshot;
  final String subject;
  final String notes;
  final DateTime issueDate;
  final SalesEntryStatus status;
  final bool cashSaleMode;
  final SettlementMethod? settlementMethod;
  final String settlementCardCompany;
  final DateTime? settlementDueDate;
  final List<_LineDraft> lines;

  bool isSame(_EntrySnapshot other) {
    return customer == other.customer &&
        customerSnapshot == other.customerSnapshot &&
        subject == other.subject &&
        notes == other.notes &&
        issueDate == other.issueDate &&
        status == other.status &&
        cashSaleMode == other.cashSaleMode &&
        settlementMethod == other.settlementMethod &&
        settlementCardCompany == other.settlementCardCompany &&
        settlementDueDate == other.settlementDueDate &&
        listEquals(lines, other.lines);
  }
}

class _LineDraft {
  const _LineDraft({
    this.id,
    this.productId,
    required this.description,
    required this.quantity,
    required this.unitPrice,
    this.taxRate,
    required this.costAmount,
    required this.costIsProvisional,
  });

  final String? id;
  final String? productId;
  final String description;
  final int quantity;
  final int unitPrice;
  final double? taxRate;
  final int costAmount;
  final bool costIsProvisional;

  factory _LineDraft.fromForm(LineItemFormData form) {
    return _LineDraft(
      id: form.id,
      productId: form.productId,
      description: form.description,
      quantity: form.quantityValue,
      unitPrice: form.unitPriceValue,
      taxRate: form.taxRate,
      costAmount: form.costAmount,
      costIsProvisional: form.costIsProvisional,
    );
  }

  LineItemFormData toFormData() {
    return LineItemFormData(
      id: id,
      productId: productId,
      productName: description,
      quantity: quantity,
      unitPrice: unitPrice,
      taxRate: taxRate,
      costAmount: costAmount,
      costIsProvisional: costIsProvisional,
    );
  }

  @override
  bool operator ==(Object other) {
    if (identical(this, other)) return true;
    return other is _LineDraft &&
        other.id == id &&
        other.productId == productId &&
        other.description == description &&
        other.quantity == quantity &&
        other.unitPrice == unitPrice &&
        other.taxRate == taxRate &&
        other.costAmount == costAmount &&
        other.costIsProvisional == costIsProvisional;
  }

  @override
  int get hashCode => Object.hash(id, productId, description, quantity, unitPrice, taxRate, costAmount, costIsProvisional);
}

class _SalesEntryEditorPage extends StatefulWidget {
  const _SalesEntryEditorPage({required this.service, this.entry});

  final SalesEntryService service;
  final SalesEntry? entry;

  @override
  State<_SalesEntryEditorPage> createState() => _SalesEntryEditorPageState();
}

class _SalesEntryEditorPageState extends State<_SalesEntryEditorPage> {
  final _subjectController = TextEditingController();
  final _notesController = TextEditingController();
  final Uuid _uuid = const Uuid();
  final DateFormat _dateFormat = DateFormat('yyyy/MM/dd');
  final NumberFormat _currencyFormat = NumberFormat.currency(locale: 'ja_JP', symbol: '¥');
  final EditLogRepository _editLogRepo = EditLogRepository();
  final AppSettingsRepository _settingsRepo = AppSettingsRepository();

  late DateTime _issueDate;
  Customer? _selectedCustomer;
  String? _customerSnapshot;
  SettlementMethod? _settlementMethod;
  final TextEditingController _cardCompanyController = TextEditingController();
  DateTime? _settlementDueDate;
  SalesEntryStatus _status = SalesEntryStatus.draft;
  bool _isSaving = false;
  final List<LineItemFormData> _lines = [];
  List<EditLogEntry> _editLogs = const [];
  String? _entryId;
  bool _isLoadingLogs = false;
  bool _grossEnabled = true;
  bool _grossToggleVisible = true;
  bool _grossIncludeProvisional = false;
  bool _showGross = true;
  bool _cashSaleMode = false;
  final String _cashSaleLabel = '現金売上';
  bool _cashSaleModeUserOverride = false;
  bool _showGrossUserOverride = false;
  bool _isQuickSettingsDrawerOpen = false;
  static final RegExp _honorificPattern = RegExp(r'(様|さま|御中|殿|貴社|先生|氏)$');

  final List<_EntrySnapshot> _undoStack = [];
  final List<_EntrySnapshot> _redoStack = [];
  bool _isApplyingSnapshot = false;
  Timer? _historyDebounce;

  @override
  void initState() {
    super.initState();
    final entry = widget.entry;
    _cashSaleModeUserOverride = entry != null;
    _issueDate = entry?.issueDate ?? DateTime.now();
    _status = entry?.status ?? SalesEntryStatus.draft;
    _customerSnapshot = _withHonorific(entry?.customerNameSnapshot);
    _settlementMethod = entry?.settlementMethod;
    _cardCompanyController.text = entry?.settlementCardCompany ?? '';
    _settlementDueDate = entry?.settlementDueDate;
    _subjectController.text = entry?.subject ?? '';
    _notesController.text = entry?.notes ?? '';
    _entryId = entry?.id;
    _cashSaleMode = entry == null
        ? false
        : (entry.customerId == null && entry.customerNameSnapshot == _cashSaleLabel);

    if (entry != null) {
      for (final item in entry.items) {
        final form = LineItemFormData(
          id: item.id,
          productId: item.productId,
          productName: item.description,
          quantity: item.quantity,
          unitPrice: item.unitPrice,
          taxRate: item.taxRate,
          costAmount: item.costAmount,
          costIsProvisional: item.costIsProvisional,
        );
        _attachLineListeners(form);
        _lines.add(form);
      }
    }
    if (_lines.isEmpty) {
      final form = LineItemFormData();
      _attachLineListeners(form);
      _lines.add(form);
    }
    if (_entryId != null) {
      _loadEditLogs();
    }
    _loadEditorPreferences();
    _subjectController.addListener(_scheduleHistorySnapshot);
    _notesController.addListener(_scheduleHistorySnapshot);
    _cardCompanyController.addListener(_scheduleHistorySnapshot);
    WidgetsBinding.instance.addPostFrameCallback((_) => _initializeHistory());
  }

  @override
  void dispose() {
    _historyDebounce?.cancel();
    _subjectController.removeListener(_scheduleHistorySnapshot);
    _notesController.removeListener(_scheduleHistorySnapshot);
    _cardCompanyController.removeListener(_scheduleHistorySnapshot);
    _subjectController.dispose();
    _notesController.dispose();
    _cardCompanyController.dispose();
    for (final line in _lines) {
      line.removeChangeListener(_scheduleHistorySnapshot);
      line.dispose();
    }
    super.dispose();
  }

  Widget _buildBackButton() {
    return Tooltip(
      message: '戻る / 長押しで表示モード設定',
      child: SizedBox(
        width: kToolbarHeight,
        height: kToolbarHeight,
        child: InkResponse(
          radius: 28,
          containedInkWell: true,
          highlightShape: BoxShape.circle,
          onTap: () => Navigator.of(context).maybePop(),
          onLongPress: _openQuickSettingsDrawer,
          child: const Center(child: Icon(Icons.arrow_back)),
        ),
      ),
    );
  }

  String? _withHonorific(String? value, {String? fallbackHonorific}) {
    if (value == null) return null;
    final trimmed = value.trimRight();
    if (trimmed.isEmpty) return value;
    if (_honorificPattern.hasMatch(trimmed)) {
      return trimmed;
    }
    final candidate = (fallbackHonorific ?? _selectedCustomer?.title ?? '様').trim();
    if (candidate.isEmpty) {
      return trimmed;
    }
    return '$trimmed $candidate';
  }


  String _ensureEntryId() {
    return _entryId ??= widget.entry?.id ?? _uuid.v4();
  }

  void _logEdit(String message) {
    final id = _ensureEntryId();
    _editLogRepo.addLog(id, message).then((_) => _loadEditLogs());
  }

  void _initializeHistory() {
    _undoStack
      ..clear()
      ..add(_captureSnapshot());
    _redoStack.clear();
  }

  void _attachLineListeners(LineItemFormData line) {
    line.registerChangeListener(_scheduleHistorySnapshot);
  }

  void _scheduleHistorySnapshot() {
    if (_isApplyingSnapshot) return;
    _historyDebounce?.cancel();
    _historyDebounce = Timer(const Duration(milliseconds: 500), () {
      _pushHistory(clearRedo: true);
    });
  }

  void _pushHistory({bool clearRedo = false}) {
    if (_isApplyingSnapshot) return;
    final snapshot = _captureSnapshot();
    if (_undoStack.isNotEmpty && _undoStack.last.isSame(snapshot)) {
      return;
    }
    setState(() {
      if (_undoStack.length >= 50) {
        _undoStack.removeAt(0);
      }
      _undoStack.add(snapshot);
      if (clearRedo) {
        _redoStack.clear();
      }
    });
  }

  _EntrySnapshot _captureSnapshot() {
    return _EntrySnapshot(
      customer: _selectedCustomer,
      customerSnapshot: _customerSnapshot,
      subject: _subjectController.text,
      notes: _notesController.text,
      issueDate: _issueDate,
      status: _status,
      cashSaleMode: _cashSaleMode,
      settlementMethod: _settlementMethod,
      settlementCardCompany: _cardCompanyController.text,
      settlementDueDate: _settlementDueDate,
      lines: _lines.map(_LineDraft.fromForm).toList(growable: false),
    );
  }

  void _applySnapshot(_EntrySnapshot snapshot) {
    _isApplyingSnapshot = true;
    _historyDebounce?.cancel();
    for (final line in _lines) {
      line.removeChangeListener(_scheduleHistorySnapshot);
      line.dispose();
    }
    _lines
      ..clear()
      ..addAll(snapshot.lines.map((draft) {
        final form = draft.toFormData();
        _attachLineListeners(form);
        return form;
      }));
    _selectedCustomer = snapshot.customer;
    _customerSnapshot = _withHonorific(snapshot.customerSnapshot, fallbackHonorific: snapshot.customer?.title);
    _subjectController.text = snapshot.subject;
    _notesController.text = snapshot.notes;
    _issueDate = snapshot.issueDate;
    _status = snapshot.status;
    _cashSaleMode = snapshot.cashSaleMode;
    _settlementMethod = snapshot.settlementMethod;
    _cardCompanyController.text = snapshot.settlementCardCompany;
    _settlementDueDate = snapshot.settlementDueDate;
    _isApplyingSnapshot = false;
    setState(() {});
  }

  bool get _canUndo => _undoStack.length > 1;
  bool get _canRedo => _redoStack.isNotEmpty;

  void _undo() {
    if (!_canUndo) return;
    final current = _captureSnapshot();
    setState(() {
      _redoStack.add(current);
      _undoStack.removeLast();
      final snapshot = _undoStack.last;
      _applySnapshot(snapshot);
    });
  }

  void _redo() {
    if (!_canRedo) return;
    final snapshot = _redoStack.removeLast();
    setState(() {
      _undoStack.add(snapshot);
      _applySnapshot(snapshot);
    });
  }

  Future<void> _loadEditorPreferences() async {
    final enabled = await _settingsRepo.getGrossProfitEnabled();
    final toggleVisible = await _settingsRepo.getGrossProfitToggleVisible();
    final includeProvisional = await _settingsRepo.getGrossProfitIncludeProvisional();
    final defaultCash = await _settingsRepo.getSalesEntryCashModeDefault();
    final showGross = await _settingsRepo.getSalesEntryShowGross();
    if (!mounted) return;
    setState(() {
      _grossEnabled = enabled;
      _grossToggleVisible = toggleVisible;
      _grossIncludeProvisional = includeProvisional;
      if (!_cashSaleModeUserOverride && widget.entry == null) {
        _toggleCashSaleMode(defaultCash, userAction: false);
      }
      if (!_showGrossUserOverride) {
        _showGross = enabled && showGross;
      } else if (!enabled) {
        _showGross = false;
      }
    });
  }

  Future<void> _loadEditLogs() async {
    final id = _entryId;
    if (id == null) return;
    setState(() => _isLoadingLogs = true);
    final logs = await _editLogRepo.getLogs(id);
    if (!mounted) return;
    setState(() {
      _editLogs = logs;
      _isLoadingLogs = false;
    });
  }

  Widget _buildEditLogPanel() {
    final hasEntryId = _entryId != null;
    return Card(
      color: Colors.grey.shade100,
      margin: const EdgeInsets.only(top: 24),
      shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
      child: Padding(
        padding: const EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Row(
              children: [
                const Expanded(
                  child: Text(
                    '編集ログ',
                    style: TextStyle(fontWeight: FontWeight.bold),
                  ),
                ),
                IconButton(
                  tooltip: '再読込',
                  icon: const Icon(Icons.refresh),
                  onPressed: hasEntryId ? _loadEditLogs : null,
                ),
              ],
            ),
            const SizedBox(height: 8),
            if (!hasEntryId)
              const Text(
                '保存すると編集ログが表示されます。',
                style: TextStyle(color: Colors.grey),
              )
            else if (_isLoadingLogs)
              const SizedBox(
                height: 48,
                child: Center(child: CircularProgressIndicator(strokeWidth: 2)),
              )
            else if (_editLogs.isEmpty)
              const Text(
                '編集ログはまだありません。',
                style: TextStyle(color: Colors.grey),
              )
            else ...[
              ..._editLogs.take(10).map((log) {
                final timestamp = DateFormat('yyyy/MM/dd HH:mm').format(log.createdAt);
                return Padding(
                  padding: const EdgeInsets.symmetric(vertical: 4),
                  child: Row(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      const Icon(Icons.circle, size: 6, color: Colors.grey),
                      const SizedBox(width: 8),
                      Expanded(
                        child: Column(
                          crossAxisAlignment: CrossAxisAlignment.start,
                          children: [
                            Text(
                              timestamp,
                              style: const TextStyle(fontSize: 11, color: Colors.black54),
                            ),
                            Text(log.message),
                          ],
                        ),
                      ),
                    ],
                  ),
                );
              }),
              if (_editLogs.length > 10)
                const Padding(
                  padding: EdgeInsets.only(top: 8),
                  child: Text(
                    '最新10件を表示しています。',
                    style: TextStyle(fontSize: 11, color: Colors.grey),
                  ),
                ),
            ],
          ],
        ),
      ),
    );
  }

  Future<void> _pickCustomer() async {
    final selected = await showFeatureModalBottomSheet<Customer?>(
      context: context,
      builder: (ctx) => CustomerPickerModal(
        onCustomerSelected: (customer) {
          Navigator.pop(ctx, customer);
        },
      ),
    );
    if (selected == null) return;
    setState(() {
      _selectedCustomer = selected;
      _customerSnapshot = _withHonorific(selected.invoiceName, fallbackHonorific: selected.title);
    });
    _logEdit('取引先を「${selected.invoiceName}」に設定');
  }

  Future<void> _pickDate() async {
    final picked = await showDatePicker(
      context: context,
      initialDate: _issueDate,
      firstDate: DateTime(2015),
      lastDate: DateTime(2100),
    );
    if (picked == null) return;
    setState(() => _issueDate = picked);
    _logEdit('計上日を${_dateFormat.format(picked)}に更新');
  }

  Future<void> _pickSettlementDueDate() async {
    final picked = await showDatePicker(
      context: context,
      initialDate: _settlementDueDate ?? DateTime.now(),
      firstDate: DateTime(2015),
      lastDate: DateTime(2100),
    );
    if (picked == null) return;
    setState(() => _settlementDueDate = picked);
    _scheduleHistorySnapshot();
  }

  void _addLine() {
    setState(() {
      final form = LineItemFormData(quantity: 1);
      _attachLineListeners(form);
      _lines.add(form);
    });
    _pushHistory(clearRedo: true);
    _logEdit('明細行を追加しました');
  }

  void _removeLine(int index) {
    if (_lines.length <= 1) return;
    final removed = _lines[index].descriptionController.text;
    final target = _lines.removeAt(index);
    target.removeChangeListener(_scheduleHistorySnapshot);
    target.dispose();
    setState(() {});
    _pushHistory(clearRedo: true);
    _logEdit(removed.isEmpty ? '明細行を削除しました' : '明細「$removed」を削除しました');
  }

  Future<void> _save() async {
    if (_isSaving) return;
    for (var i = 0; i < _lines.length; i++) {
      if (!_lines[i].hasProduct) {
        ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('明細${i + 1}の商品を選択してください')));
        return;
      }
    }
    final subject = _subjectController.text.trim();
    final notes = _notesController.text.trim();
    if (_cashSaleMode && (_customerSnapshot == null || _customerSnapshot!.isEmpty)) {
      _customerSnapshot = _cashSaleLabel;
    } else if (!_cashSaleMode) {
      _customerSnapshot = _withHonorific(_customerSnapshot);
    }
    final entryId = _ensureEntryId();
    final lines = <SalesLineItem>[];
    for (final line in _lines) {
      final desc = line.descriptionController.text.trim();
      final qty = int.tryParse(line.quantityController.text) ?? 0;
      final price = int.tryParse(line.unitPriceController.text) ?? 0;
      if (desc.isEmpty || qty <= 0) continue;
      final id = line.id ?? _uuid.v4();
      lines.add(
        SalesLineItem(
          id: id,
          salesEntryId: entryId,
          productId: line.productId,
          description: desc,
          quantity: qty,
          unitPrice: price,
          lineTotal: qty * price,
          taxRate: line.taxRate ?? 0.1,
          costAmount: line.costAmount,
          costIsProvisional: line.costIsProvisional,
        ),
      );
    }
    if (lines.isEmpty) {
      ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('明細を1件以上入力してください')));
      return;
    }

    final base = widget.entry ??
        SalesEntry(
          id: entryId,
          customerId: _selectedCustomer?.id,
          customerNameSnapshot: _customerSnapshot,
          subject: subject.isEmpty ? null : subject,
          issueDate: _issueDate,
          status: _status,
          notes: notes.isEmpty ? null : notes,
          settlementMethod: _settlementMethod,
          settlementCardCompany: _cardCompanyController.text.trim().isEmpty ? null : _cardCompanyController.text.trim(),
          settlementDueDate: _settlementDueDate,
          createdAt: DateTime.now(),
          updatedAt: DateTime.now(),
          items: lines,
        );

    final updated = base.copyWith(
      customerId: _selectedCustomer?.id ?? base.customerId,
      customerNameSnapshot: _customerSnapshot ?? base.customerNameSnapshot,
      subject: subject.isEmpty ? null : subject,
      issueDate: _issueDate,
      notes: notes.isEmpty ? null : notes,
      status: _status,
      items: lines,
      updatedAt: DateTime.now(),
      settlementMethod: _settlementMethod,
      settlementCardCompany: _settlementMethod == SettlementMethod.card
          ? (_cardCompanyController.text.trim().isEmpty ? null : _cardCompanyController.text.trim())
          : null,
      settlementDueDate: _settlementMethod == SettlementMethod.accountsReceivable ? _settlementDueDate : null,
    );

    setState(() => _isSaving = true);
    try {
      final saved = await widget.service.saveEntry(updated);
      if (!mounted) return;
      _entryId = saved.id;
      _logEdit('売上伝票を保存しました');
      Navigator.pop(context, saved);
    } catch (e) {
      if (!mounted) return;
      setState(() => _isSaving = false);
      ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('保存に失敗しました: $e')));
    }
  }

  @override
  Widget build(BuildContext context) {
    final mediaQuery = MediaQuery.of(context);
    final keyboardInset = mediaQuery.viewInsets.bottom;
    final safeBottom = mediaQuery.padding.bottom;
    final scrollPadding = (keyboardInset > 0 ? keyboardInset : 0) + 48.0;

    return Scaffold(
      backgroundColor: Colors.grey.shade200,
      resizeToAvoidBottomInset: false,
      appBar: AppBar(
        leading: _buildBackButton(),
        title: Tooltip(
          message: '長押しで表示モード設定ドロワーを開きます',
          child: InkWell(
            onLongPress: _openQuickSettingsDrawer,
            borderRadius: BorderRadius.circular(8),
            child: ScreenAppBarTitle(
              screenId: 'U2',
              title: widget.entry == null ? '売上伝票作成' : '売上伝票編集',
            ),
          ),
        ),
        actions: [
          IconButton(
            icon: const Icon(Icons.undo),
            tooltip: '元に戻す',
            onPressed: _canUndo ? _undo : null,
          ),
          IconButton(
            icon: const Icon(Icons.redo),
            tooltip: 'やり直す',
            onPressed: _canRedo ? _redo : null,
          ),
          IconButton(
            icon: const Icon(Icons.save_outlined),
            tooltip: '保存',
            onPressed: _isSaving ? null : _save,
          ),
          TextButton(onPressed: _isSaving ? null : _save, child: const Text('保存')),
        ],
      ),
      body: SafeArea(
        top: true,
        bottom: false,
        child: AnimatedPadding(
          duration: const Duration(milliseconds: 200),
          curve: Curves.easeOut,
          padding: EdgeInsets.fromLTRB(16, 16, 16, 32 + safeBottom),
          child: LayoutBuilder(
            builder: (context, constraints) {
              return SingleChildScrollView(
                keyboardDismissBehavior: ScrollViewKeyboardDismissBehavior.onDrag,
                padding: EdgeInsets.only(bottom: scrollPadding),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  mainAxisSize: MainAxisSize.min,
                  children: [
                    Card(
                      color: Colors.white,
                      child: Padding(
                        padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 4),
                        child: TextField(
                          controller: _subjectController,
                          decoration: const InputDecoration(labelText: '件名', border: InputBorder.none),
                        ),
                      ),
                    ),
                    const SizedBox(height: 12),
                    Card(
                      color: Colors.white,
                      child: Padding(
                        padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
                        child: Row(
                          children: [
                            Expanded(
                              child: InkWell(
                                onTap: _pickDate,
                                borderRadius: BorderRadius.circular(8),
                                child: Padding(
                                  padding: const EdgeInsets.symmetric(vertical: 8),
                                  child: Text('計上日: ${_dateFormat.format(_issueDate)}'),
                                ),
                              ),
                            ),
                            TextButton(onPressed: _pickDate, child: const Text('日付を選択')),
                          ],
                        ),
                      ),
                    ),
                    const SizedBox(height: 12),
                    Card(
                      color: Colors.white,
                      child: ListTile(
                        contentPadding: const EdgeInsets.symmetric(horizontal: 12),
                        title: Text(_customerSnapshot ?? '顧客を選択'),
                        trailing: const Icon(Icons.chevron_right),
                        onTap: _cashSaleMode ? null : _pickCustomer,
                      ),
                    ),
                    const SizedBox(height: 12),
                    _buildSettlementCard(),
                    const Divider(height: 32),
                    Text('明細', style: Theme.of(context).textTheme.titleMedium),
                    const SizedBox(height: 8),
                    if (_grossEnabled && _grossToggleVisible)
                      Padding(
                        padding: const EdgeInsets.only(bottom: 8),
                        child: Text(
                          '粗利の表示・非表示はタイトル長押しの表示モードドロワーから切り替えられます。',
                          style: Theme.of(context).textTheme.bodySmall,
                        ),
                      ),
                    for (var i = 0; i < _lines.length; i++)
                      LineItemCard(
                        data: _lines[i],
                        onRemove: () => _removeLine(i),
                        onPickProduct: () => _pickProductForLine(i),
                        meta: _shouldShowGross ? _buildLineMeta(_lines[i]) : null,
                        footer: _shouldShowGross ? _buildLineFooter(_lines[i]) : null,
                      ),
                    Align(
                      alignment: Alignment.centerLeft,
                      child: TextButton.icon(
                        onPressed: _addLine,
                        icon: const Icon(Icons.add),
                        label: const Text('明細を追加'),
                      ),
                    ),
                    const Divider(height: 32),
                    if (_shouldShowGross) _buildGrossSummary(),
                    if (_shouldShowGross) const Divider(height: 32),
                    Card(
                      color: Colors.white,
                      child: Padding(
                        padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
                        child: TextField(
                          controller: _notesController,
                          decoration: const InputDecoration(labelText: 'メモ', border: InputBorder.none),
                          maxLines: 3,
                        ),
                      ),
                    ),
                    _buildEditLogPanel(),
                    const SizedBox(height: 80),
                  ],
                ),
              );
            },
          ),
        ),
      ),
    );
  }

  void _pickProductForLine(int index) {
    showModalBottomSheet(
      context: context,
      isScrollControlled: true,
      backgroundColor: Colors.transparent,
      builder: (context) => FractionallySizedBox(
        heightFactor: 0.9,
        child: ProductPickerModal(
          onProductSelected: (product) {
            setState(() {
              final line = _lines[index];
              line.applyProduct(product);
            });
            _logEdit('明細${index + 1}を商品「${product.name}」に設定');
            _pushHistory(clearRedo: true);
          },
          onItemSelected: (item) {},
        ),
      ),
    );
  }

  void _toggleCashSaleMode(bool enabled, {bool userAction = true}) {
    if (_cashSaleMode == enabled) return;
    setState(() {
      _cashSaleMode = enabled;
      if (enabled) {
        _selectedCustomer = null;
        _customerSnapshot = _cashSaleLabel;
      } else {
        _customerSnapshot = _withHonorific(
          _selectedCustomer?.invoiceName,
          fallbackHonorific: _selectedCustomer?.title,
        );
      }
      if (userAction) {
        _cashSaleModeUserOverride = true;
      }
    });
    if (userAction) {
      _logEdit(enabled ? '現金売上モードを有効化' : '現金売上モードを無効化');
      _pushHistory(clearRedo: true);
    }
  }

  void _setShowGross(bool enabled, {bool userAction = true}) {
    if (!_grossEnabled || _showGross == enabled) return;
    setState(() {
      _showGross = enabled;
      if (userAction) {
        _showGrossUserOverride = true;
      }
    });
    if (userAction) {
      _settingsRepo.setSalesEntryShowGross(enabled);
    }
  }

  void _setGrossIncludeProvisional(bool include) {
    if (_grossIncludeProvisional == include) return;
    setState(() => _grossIncludeProvisional = include);
    _settingsRepo.setGrossProfitIncludeProvisional(include);
  }

  Future<void> _openQuickSettingsDrawer() async {
    if (!mounted || _isQuickSettingsDrawerOpen) return;
    _isQuickSettingsDrawerOpen = true;
    final rootContext = context;
    await showGeneralDialog(
      context: context,
      barrierLabel: '表示モード設定',
      barrierDismissible: true,
      barrierColor: Colors.black54,
      transitionDuration: const Duration(milliseconds: 260),
      pageBuilder: (dialogContext, animation, secondaryAnimation) {
        final theme = Theme.of(dialogContext);
        return SafeArea(
          child: Align(
            alignment: Alignment.topCenter,
            child: Padding(
              padding: const EdgeInsets.all(16),
              child: Material(
                color: theme.colorScheme.surface,
                elevation: 6,
                borderRadius: BorderRadius.circular(20),
                clipBehavior: Clip.antiAlias,
                child: ConstrainedBox(
                  constraints: const BoxConstraints(maxWidth: 520),
                  child: _buildQuickSettingsContent(dialogContext, rootContext),
                ),
              ),
            ),
          ),
        );
      },
      transitionBuilder: (context, animation, secondaryAnimation, child) {
        final curved = CurvedAnimation(parent: animation, curve: Curves.easeOutCubic, reverseCurve: Curves.easeInCubic);
        return SlideTransition(
          position: Tween(begin: const Offset(0, -1), end: Offset.zero).animate(curved),
          child: FadeTransition(opacity: curved, child: child),
        );
      },
    );
    _isQuickSettingsDrawerOpen = false;
  }

  Widget _buildQuickSettingsContent(BuildContext dialogContext, BuildContext rootContext) {
    final textTheme = Theme.of(dialogContext).textTheme;
    return SingleChildScrollView(
      padding: const EdgeInsets.fromLTRB(24, 16, 24, 32),
      child: Column(
        mainAxisSize: MainAxisSize.min,
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Row(
            children: const [
              Icon(Icons.tune),
              SizedBox(width: 8),
              Text('表示モード設定', style: TextStyle(fontSize: 18, fontWeight: FontWeight.w600)),
            ],
          ),
          const SizedBox(height: 8),
          Text('ここで切り替えた内容はこの伝票に即時反映されます。', style: textTheme.bodySmall),
          const Divider(height: 24),
          SwitchListTile.adaptive(
            contentPadding: EdgeInsets.zero,
            title: const Text('現金売上モード'),
            subtitle: const Text('顧客未選択で「現金売上」として登録します'),
            value: _cashSaleMode,
            onChanged: (value) => _toggleCashSaleMode(value),
          ),
          SwitchListTile.adaptive(
            contentPadding: EdgeInsets.zero,
            title: const Text('粗利を表示'),
            subtitle: const Text('各明細の粗利チップとサマリを表示します'),
            value: _shouldShowGross,
            onChanged: _grossEnabled ? (value) => _setShowGross(value) : null,
          ),
          SwitchListTile.adaptive(
            contentPadding: EdgeInsets.zero,
            title: const Text('暫定粗利を合計に含める'),
            subtitle: const Text('仕入未確定（粗利=0扱い）の明細を粗利合計に含めます'),
            value: _grossIncludeProvisional,
            onChanged: (value) => _setGrossIncludeProvisional(value),
          ),
          const SizedBox(height: 12),
          Text(
            'S1 > U2エディタ表示モード で既定値を変更すると、新規伝票の初期状態が更新されます。',
            style: textTheme.bodySmall,
          ),
          const SizedBox(height: 12),
          FilledButton.icon(
            icon: const Icon(Icons.settings),
            label: const Text('S1:設定で既定値を編集'),
            onPressed: () {
              Navigator.of(dialogContext).pop();
              Navigator.of(rootContext).push(MaterialPageRoute(builder: (_) => const SettingsScreen()));
            },
          ),
        ],
      ),
    );
  }

  bool get _shouldShowGross => _grossEnabled && _showGross;

  Widget _buildSettlementCard() {
    final showCardCompany = _settlementMethod == SettlementMethod.card;
    final showDueDate = _settlementMethod == SettlementMethod.accountsReceivable;
    return Card(
      color: Colors.white,
      child: Padding(
        padding: const EdgeInsets.fromLTRB(12, 8, 12, 12),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            DropdownButtonFormField<SettlementMethod>(
              initialValue: _settlementMethod,
              decoration: const InputDecoration(labelText: '清算方法'),
              items: SettlementMethod.values
                  .map((method) => DropdownMenuItem(value: method, child: Text(method.displayName)))
                  .toList(),
              onChanged: (value) {
                setState(() {
                  _settlementMethod = value;
                  if (value != SettlementMethod.card) {
                    _cardCompanyController.clear();
                  }
                  if (value != SettlementMethod.accountsReceivable) {
                    _settlementDueDate = null;
                  }
                });
              },
            ),
            if (showCardCompany) ...[
              const SizedBox(height: 8),
              TextField(
                controller: _cardCompanyController,
                decoration: const InputDecoration(labelText: 'カード会社'),
              ),
            ],
            if (showDueDate) ...[
              const SizedBox(height: 8),
              ListTile(
                contentPadding: EdgeInsets.zero,
                title: const Text('入金予定日'),
                subtitle: Text(_settlementDueDate == null ? '未設定' : _dateFormat.format(_settlementDueDate!)),
                trailing: Row(
                  mainAxisSize: MainAxisSize.min,
                  children: [
                    if (_settlementDueDate != null)
                      IconButton(
                        tooltip: 'クリア',
                        icon: const Icon(Icons.clear),
                        onPressed: () => setState(() => _settlementDueDate = null),
                      ),
                    TextButton(onPressed: _pickSettlementDueDate, child: const Text('選択')),
                  ],
                ),
              ),
            ],
          ],
        ),
      ),
    );
  }

  int _lineQuantity(LineItemFormData line) => int.tryParse(line.quantityController.text) ?? 0;

  int _lineUnitPrice(LineItemFormData line) => int.tryParse(line.unitPriceController.text) ?? 0;

  int _lineRevenue(LineItemFormData line) => _lineQuantity(line) * _lineUnitPrice(line);

  int _lineCost(LineItemFormData line) => _lineQuantity(line) * line.costAmount;

  int _lineGross(LineItemFormData line) {
    if (_isProvisional(line)) return 0;
    return _lineRevenue(line) - _lineCost(line);
  }

  bool _isProvisional(LineItemFormData line) => line.costIsProvisional || line.costAmount <= 0;

  String _formatYen(int value) => _currencyFormat.format(value).replaceAll('.00', '');

  Widget _buildLineMeta(LineItemFormData line) {
    final gross = _lineGross(line);
    final provisional = _isProvisional(line);
    final color = provisional
        ? Colors.orange
        : gross >= 0
            ? Colors.green
            : Colors.redAccent;
    final label = provisional ? '粗利(暫定0円)' : '粗利';
    return Padding(
      padding: const EdgeInsets.only(right: 8),
      child: Chip(
        label: Text('$label ${_formatYen(gross)}'),
        backgroundColor: color.withValues(alpha: 0.12),
        labelStyle: TextStyle(color: color, fontSize: 12, fontWeight: FontWeight.w600),
      ),
    );
  }

  Widget _buildLineFooter(LineItemFormData line) {
    final cost = _lineCost(line);
    final provisional = _isProvisional(line);
    final text = provisional
        ? '仕入: ${_formatYen(cost)} (粗利は暫定0円)'
        : '仕入: ${_formatYen(cost)}';
    return Align(
      alignment: Alignment.centerRight,
      child: Text(
        text,
        style: TextStyle(
          fontSize: 12,
          color: provisional ? Colors.orange.shade700 : Colors.black54,
        ),
      ),
    );
  }

  int _grossTotal({required bool includeProvisional}) {
    var total = 0;
    for (final line in _lines) {
      if (!includeProvisional && _isProvisional(line)) continue;
      total += _lineGross(line);
    }
    return total;
  }

  int _provisionalCount() => _lines.where(_isProvisional).length;

  Widget _buildGrossSummary() {
    final total = _grossTotal(includeProvisional: _grossIncludeProvisional);
    final excluded = _grossTotal(includeProvisional: false);
    final provisionalLines = _provisionalCount();
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Text('粗利サマリ', style: Theme.of(context).textTheme.titleMedium),
        const SizedBox(height: 8),
        Row(
          children: [
            Expanded(
              child: _SummaryTile(
                label: _grossIncludeProvisional ? '粗利合計(暫定含む)' : '粗利合計',
                value: _formatYen(total),
                valueColor: total >= 0 ? Colors.green.shade700 : Colors.redAccent,
              ),
            ),
            const SizedBox(width: 12),
            Expanded(
              child: _SummaryTile(
                label: '暫定を除いた粗利',
                value: _formatYen(excluded),
              ),
            ),
          ],
        ),
        if (provisionalLines > 0)
          Padding(
            padding: const EdgeInsets.only(top: 8),
            child: Text(
              '暫定粗利の明細: $provisionalLines 件 (設定で合計への含め方を変更できます)',
              style: Theme.of(context).textTheme.bodySmall?.copyWith(color: Colors.orange.shade700),
            ),
          ),
      ],
    );
  }
}

class _SummaryTile extends StatelessWidget {
  const _SummaryTile({required this.label, required this.value, this.valueColor});

  final String label;
  final String value;
  final Color? valueColor;

  @override
  Widget build(BuildContext context) {
    final theme = Theme.of(context);
    return Container(
      padding: const EdgeInsets.all(12),
      decoration: BoxDecoration(
        borderRadius: BorderRadius.circular(8),
        color: theme.colorScheme.surfaceContainerHighest.withValues(alpha: 0.4),
      ),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Text(label, style: theme.textTheme.bodySmall),
          const SizedBox(height: 4),
          Text(
            value,
            style: theme.textTheme.titleMedium?.copyWith(
              color: valueColor ?? theme.colorScheme.onSurface,
              fontWeight: FontWeight.bold,
            ),
          ),
        ],
      ),
    );
  }
}

class SalesEntryImportSheet extends StatefulWidget {
  const SalesEntryImportSheet({required this.service, super.key});

  final SalesEntryService service;

  static Future<SalesEntry?> show(BuildContext context, SalesEntryService service) {
    return showModalBottomSheet<SalesEntry>(
      context: context,
      isScrollControlled: true,
      builder: (_) => DraggableScrollableSheet(
        expand: false,
        initialChildSize: 0.85,
        builder: (_, controller) => SalesEntryImportSheet(service: service),
      ),
    );
  }

  @override
  State<SalesEntryImportSheet> createState() => _SalesEntryImportSheetState();
}

class _SalesEntryImportSheetState extends State<SalesEntryImportSheet> {
  final TextEditingController _keywordController = TextEditingController();
  final TextEditingController _subjectController = TextEditingController();

  bool _isLoading = true;
  bool _isImporting = false;
  List<SalesImportCandidate> _candidates = const [];
  Set<String> _selected = {};
  Set<DocumentType> _types = DocumentType.values.toSet();
  DateTime? _startDate;
  DateTime? _endDate;
  DateTime? _issueDateOverride;

  @override
  void initState() {
    super.initState();
    _loadCandidates();
  }

  @override
  void dispose() {
    _keywordController.dispose();
    _subjectController.dispose();
    super.dispose();
  }

  Future<void> _loadCandidates() async {
    setState(() => _isLoading = true);
    try {
      final results = await widget.service.fetchImportCandidates(
        keyword: _keywordController.text.trim().isEmpty ? null : _keywordController.text.trim(),
        documentTypes: _types,
        startDate: _startDate,
        endDate: _endDate,
      );
      if (!mounted) return;
      setState(() {
        _candidates = results;
        _isLoading = false;
        _selected = _selected.where((id) => results.any((c) => c.invoiceId == id)).toSet();
      });
    } catch (e) {
      if (!mounted) return;
      setState(() => _isLoading = false);
      ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('インポート候補の取得に失敗しました: $e')));
    }
  }

  Future<void> _pickRange({required bool isStart}) async {
    final initial = isStart ? (_startDate ?? DateTime.now().subtract(const Duration(days: 30))) : (_endDate ?? DateTime.now());
    final picked = await showDatePicker(
      context: context,
      initialDate: initial,
      firstDate: DateTime(2015),
      lastDate: DateTime(2100),
    );
    if (picked == null) return;
    setState(() {
      if (isStart) {
        _startDate = picked;
      } else {
        _endDate = picked;
      }
    });
    _loadCandidates();
  }

  Future<void> _pickIssueDate() async {
    final picked = await showDatePicker(
      context: context,
      initialDate: _issueDateOverride ?? DateTime.now(),
      firstDate: DateTime(2015),
      lastDate: DateTime(2100),
    );
    if (picked == null) return;
    setState(() => _issueDateOverride = picked);
  }

  void _toggleType(DocumentType type) {
    setState(() {
      if (_types.contains(type)) {
        _types.remove(type);
        if (_types.isEmpty) {
          _types = {type};
        }
      } else {
        _types.add(type);
      }
    });
    _loadCandidates();
  }

  void _toggleSelection(String invoiceId) {
    setState(() {
      if (_selected.contains(invoiceId)) {
        _selected.remove(invoiceId);
      } else {
        _selected.add(invoiceId);
      }
    });
  }

  Future<void> _importSelected() async {
    if (_selected.isEmpty || _isImporting) return;
    setState(() => _isImporting = true);
    try {
      final entry = await widget.service.createEntryFromInvoices(
        _selected.toList(),
        subject: _subjectController.text.trim().isEmpty ? null : _subjectController.text.trim(),
        issueDate: _issueDateOverride,
      );
      if (!mounted) return;
      Navigator.pop(context, entry);
    } catch (e) {
      if (!mounted) return;
      setState(() => _isImporting = false);
      ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('インポートに失敗しました: $e')));
    }
  }

  @override
  Widget build(BuildContext context) {
    final dateFormat = DateFormat('yyyy/MM/dd');
    return Material(
      color: Theme.of(context).scaffoldBackgroundColor,
      child: Padding(
        padding: const EdgeInsets.fromLTRB(16, 12, 16, 24),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Row(
              children: [
                const Expanded(child: Text('伝票インポート', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold))),
                IconButton(onPressed: () => Navigator.pop(context), icon: const Icon(Icons.close)),
              ],
            ),
            const SizedBox(height: 8),
            TextField(
              controller: _keywordController,
              decoration: InputDecoration(
                labelText: 'キーワード (件名/顧客)',
                suffixIcon: IconButton(icon: const Icon(Icons.search), onPressed: _loadCandidates),
              ),
              onSubmitted: (_) => _loadCandidates(),
            ),
            const SizedBox(height: 12),
            Wrap(
              spacing: 8,
              children: DocumentType.values
                  .map((type) => FilterChip(
                        label: Text(type.displayName),
                        selected: _types.contains(type),
                        onSelected: (_) => _toggleType(type),
                      ))
                  .toList(),
            ),
            const SizedBox(height: 12),
            Row(
              children: [
                Expanded(child: Text('開始日: ${_startDate != null ? dateFormat.format(_startDate!) : '指定なし'}')),
                TextButton(onPressed: () => _pickRange(isStart: true), child: const Text('開始日を選択')),
              ],
            ),
            Row(
              children: [
                Expanded(child: Text('終了日: ${_endDate != null ? dateFormat.format(_endDate!) : '指定なし'}')),
                TextButton(onPressed: () => _pickRange(isStart: false), child: const Text('終了日を選択')),
              ],
            ),
            const Divider(height: 24),
            Expanded(
              child: _isLoading
                  ? const Center(child: CircularProgressIndicator())
                  : _candidates.isEmpty
                      ? const Center(child: Text('条件に合致する伝票が見つかりません'))
                      : ListView.builder(
                          itemCount: _candidates.length,
                          itemBuilder: (context, index) {
                            final candidate = _candidates[index];
                            final selected = _selected.contains(candidate.invoiceId);
                            return CheckboxListTile(
                              value: selected,
                              onChanged: (_) => _toggleSelection(candidate.invoiceId),
                              title: Text(candidate.subject ?? '${candidate.documentTypeName}(${candidate.invoiceNumber})'),
                              subtitle: Text(
                                '${candidate.documentTypeName} / ${candidate.customerName}\n${dateFormat.format(candidate.invoiceDate)} / 合計: ${NumberFormat.currency(locale: 'ja_JP', symbol: '¥').format(candidate.totalAmount)}',
                              ),
                            );
                          },
                        ),
            ),
            const Divider(height: 24),
            TextField(
              controller: _subjectController,
              decoration: const InputDecoration(labelText: '売上伝票の件名 (任意)'),
            ),
            Row(
              children: [
                Expanded(child: Text('売上伝票の日付: ${_issueDateOverride != null ? dateFormat.format(_issueDateOverride!) : '自動設定'}')),
                TextButton(onPressed: _pickIssueDate, child: const Text('変更')),
              ],
            ),
            const SizedBox(height: 12),
            SizedBox(
              width: double.infinity,
              child: ElevatedButton.icon(
                onPressed: _selected.isEmpty || _isImporting ? null : _importSelected,
                icon: _isImporting ? const SizedBox(width: 16, height: 16, child: CircularProgressIndicator(strokeWidth: 2)) : const Icon(Icons.playlist_add),
                label: Text(_isImporting ? 'インポート中...' : '選択(${_selected.length})件をインポート'),
              ),
            ),
          ],
        ),
      ),
    );
  }
}
