"""
Flutter風ダッシュボード
下部ナビゲーションと洗練されたUIコンポーネントを実装
"""

import flet as ft
import signal
import sys
import logging
from datetime import datetime
from typing import List, Dict, Optional
from models.invoice_models import DocumentType, Invoice, create_sample_invoices, Customer, InvoiceItem
from components.customer_picker import CustomerPickerModal
from services.app_service import AppService

# ロギング設定
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s'
)

class ZoomableContainer(ft.Container):
    """ピンチイン/アウト対応コンテナ"""
    
    def __init__(self, content=None, min_scale=0.5, max_scale=3.0, **kwargs):
        super().__init__(**kwargs)
        self.content = content
        self.min_scale = min_scale
        self.max_scale = max_scale
        self.scale = 1.0
        self.initial_distance = 0
        
        # ズーム機能を無効化してシンプルなコンテナとして使用
        # 将来的な実装のためにクラスは残す

class AppBar(ft.Container):
    """標準化されたアプリケーションヘッダー"""
    
    def __init__(self, title: str, show_back: bool = False, show_edit: bool = False, 
                 on_back=None, on_edit=None, page=None):
        super().__init__()
        self.title = title
        self.show_back = show_back
        self.show_edit = show_edit
        self.on_back = on_back
        self.on_edit = on_edit
        self.page_ref = page  # page_refとして保存
        
        self.bgcolor = ft.Colors.BLUE_GREY_50
        self.padding = ft.Padding.symmetric(horizontal=16, vertical=8)
        
        self.content = self._build_content()
    
    def _build_content(self) -> ft.Row:
        """AppBarのコンテンツを構築"""
        controls = []
        
        # 左側：戻るボタン
        if self.show_back:
            controls.append(
                ft.IconButton(
                    icon=ft.Icons.ARROW_BACK,
                    icon_color=ft.Colors.BLUE_GREY_700,
                    tooltip="戻る",
                    on_click=self.on_back if self.on_back else None
                )
            )
        else:
            controls.append(ft.Container(width=48))  # スペーーサー
        
        # 中央：タイトル
        controls.append(
            ft.Container(
                content=ft.Text(
                    self.title,
                    size=18,
                    weight=ft.FontWeight.W_500,
                    color=ft.Colors.BLUE_GREY_800
                ),
                expand=True,
                alignment=ft.alignment.Alignment(0, 0)  # 中央揃え
            )
        )
        
        # 右側：編集ボタン
        if self.show_edit:
            controls.append(
                ft.IconButton(
                    icon=ft.Icons.EDIT,
                    icon_color=ft.Colors.BLUE_GREY_700,
                    tooltip="編集",
                    on_click=self.on_edit if self.on_edit else None
                )
            )
        else:
            controls.append(ft.Container(width=48))  # スペーサー
        
        return ft.Row(
            controls,
            alignment=ft.MainAxisAlignment.SPACE_BETWEEN,
            vertical_alignment=ft.CrossAxisAlignment.CENTER
        )

class FlutterStyleDashboard:
    """Flutter風の統合ダッシュボード"""
    
    def __init__(self, page: ft.Page):
        self.page = page
        self.current_tab = 0  # 0: 伝票一覧, 1: 詳細編集
        self.selected_customer = None
        self.selected_document_type = DocumentType.INVOICE
        self.amount_value = "250000"
        self.customer_picker = None
        self.editing_invoice = None  # 編集中の伝票
        self.is_edit_mode = False  # 編集モードフラグ
        self.is_customer_picker_open = False
        self.customer_search_query = ""
        self.show_offsets = False
        self.chain_verify_result = None
        self.is_new_customer_form_open = False
        
        # ビジネスロジックサービス
        self.app_service = AppService()
        self.invoices = []
        self.customers = []
        
        self.setup_page()
        self.setup_database()
        self.setup_ui()
        
    def setup_page(self):
        """ページ設定"""
        self.page.title = "販売アシスト1号"
        self.page.window.width = 420
        self.page.window.height = 900
        self.page.theme_mode = ft.ThemeMode.LIGHT
        
        # Fletのライフサイクルに任せる（SystemExitがasyncioに伝播して警告になりやすい）
        
    def setup_database(self):
        """データ初期化（サービス層経由）"""
        try:
            # 顧客データ読み込み
            self.customers = self.app_service.customer.get_all_customers()
            
            # 伝票データ読み込み
            self.invoices = self.app_service.invoice.get_recent_invoices(20)
            
            logging.info(f"データ初期化: 顧客{len(self.customers)}件, 伝票{len(self.invoices)}件")
            
        except Exception as e:
            logging.error(f"データ初期化エラー: {e}")
    
    def create_sample_data(self):
        """サンプル伝票データ作成"""
        try:
            # サンプルデータ
            sample_invoices = create_sample_invoices()
            
            for invoice in sample_invoices:
                self.cursor.execute('''
                    INSERT OR REPLACE INTO slips 
                    (document_type, customer_name, amount, date, status, description)
                    VALUES (?, ?, ?, ?, ?, ?)
                ''', (
                    invoice.document_type.value,
                    invoice.customer.formal_name,
                    invoice.total_amount,
                    invoice.date.strftime('%Y-%m-%d %H:%M'),
                    '完了',
                    invoice.notes
                ))
            
            self.conn.commit()
        except Exception as e:
            logging.error(f"サンプルデータ作成エラー: {e}")
    
    def setup_ui(self):
        """UIセットアップ"""
        # メインコンテンツ
        self.main_content = ft.Column([], expand=True)
        
        # ページ構成
        self.page.add(
            ft.Column([
                self.main_content,
            ], expand=True)
        )
        
        # 初期表示
        self.update_main_content()
    
    def on_tab_change(self, index):
        """タブ切り替え"""
        self.current_tab = index
        self.update_main_content()
        self.page.update()
    
    def update_main_content(self):
        """メインコンテンツ更新"""
        self.main_content.controls.clear()
        
        if self.is_customer_picker_open:
            # 顧客選択画面
            self.main_content.controls.append(self.create_customer_picker_screen())
        elif self.current_tab == 0:
            # 伝票一覧画面
            self.main_content.controls.append(self._build_invoice_list_screen())
        elif self.current_tab == 1:
            # 伝票詳細/編集画面
            self.main_content.controls.append(self._build_invoice_detail_screen())
        elif self.current_tab == 2:
            # 新規作成画面
            self.main_content.controls.append(self._build_new_invoice_screen())
        
        self.page.update()
    
    def _build_invoice_list_screen(self) -> ft.Column:
        """伝票一覧画面を構築"""
        # AppBar（戻るボタンなし、編集ボタンなし）
        app_bar = AppBar(
            title="伝票一覧",
            show_back=False,
            show_edit=False
        )
        
        # 伝票リスト（ズーム対応）
        invoice_list = self._build_invoice_list()
        zoomable_list = ZoomableContainer(
            content=invoice_list,
            min_scale=0.8,
            max_scale=2.5
        )
        
        # 浮動アクションボタン
        fab = ft.FloatingActionButton(
            icon=ft.Icons.ADD,
            on_click=lambda _: self.open_new_invoice(),
            tooltip="新規伝票作成"
        )
        
        return ft.Column([
            app_bar,
            ft.Container(
                content=zoomable_list,
                expand=True,
                padding=ft.Padding.all(16)
            ),
        ], expand=True)
    
    def _build_invoice_detail_screen(self) -> ft.Column:
        """伝票詳細画面を構築"""
        if not self.editing_invoice:
            return ft.Column([ft.Text("伝票が選択されていません")])
        
        # AppBar（戻るボタンあり、編集ボタン条件付き）
        is_locked = getattr(self.editing_invoice, 'final_locked', False)
        app_bar = AppBar(
            title=f"伝票詳細: {self.editing_invoice.invoice_number}",
            show_back=True,
            show_edit=not is_locked,
            on_back=lambda _: self.back_to_list(),
            on_edit=lambda _: self.toggle_edit_mode()
        )
        
        # 伝票詳細コンテンツ（ズーム対応）
        detail_content = self._create_edit_existing_screen()
        zoomable_content = ZoomableContainer(
            content=detail_content,
            min_scale=0.8,
            max_scale=2.5
        )
        
        return ft.Column([
            app_bar,
            ft.Container(
                content=zoomable_content,
                expand=True,
                padding=ft.Padding.all(16)
            ),
        ], expand=True)
    
    def _build_new_invoice_screen(self) -> ft.Column:
        """新規作成画面を構築"""
        # AppBar（戻るボタンあり、編集ボタンなし）
        app_bar = AppBar(
            title="新規伝票作成",
            show_back=True,
            show_edit=False,
            on_back=lambda _: self.back_to_list()
        )
        
        # 新規作成コンテンツ（ズーム対応）
        new_content = self.create_slip_input_screen()
        zoomable_content = ZoomableContainer(
            content=new_content,
            min_scale=0.8,
            max_scale=2.5
        )
        
        return ft.Column([
            app_bar,
            ft.Container(
                content=zoomable_content,
                expand=True,
                padding=ft.Padding.all(16)
            ),
        ], expand=True)
    
    def back_to_list(self):
        """一覧画面に戻る"""
        self.current_tab = 0
        self.editing_invoice = None
        self.update_main_content()
    
    def toggle_edit_mode(self):
        """編集モードを切り替え"""
        if hasattr(self, 'is_detail_edit_mode'):
            self.is_detail_edit_mode = not self.is_detail_edit_mode
        else:
            self.is_detail_edit_mode = True
        self.update_main_content()
    
    def _build_invoice_list(self) -> ft.Column:
        """伝票リストを構築"""
        # 履歴データ読み込み
        slips = self.load_slips()
        logging.info(f"伝票データ取得: {len(slips)}件")
        
        if not self.show_offsets:
            slips = [s for s in slips if not (isinstance(s, Invoice) and getattr(s, "is_offset", False))]
            logging.info(f"赤伝除外後: {len(slips)}件")

        def on_toggle_offsets(e):
            self.show_offsets = bool(e.control.value)
            self.update_main_content()
        
        def on_verify_chain(_):
            """チェーン検証"""
            try:
                result = self.app_service.invoice.verify_chain()
                self.chain_verify_result = result
                self.update_main_content()
            except Exception as e:
                logging.error(f"チェーン検証エラー: {e}")
        
        # 履歴カードリスト
        slip_cards = []
        for i, slip in enumerate(slips):
            logging.info(f"伝票{i}: {type(slip)}")
            card = self.create_slip_card(slip)
            slip_cards.append(card)
        
        logging.info(f"カード作成数: {len(slip_cards)}")
        
        return ft.Column([
            # 検証結果表示（あれば）
            ft.Container(
                content=self._build_chain_verify_result(),
                margin=ft.Margin.only(bottom=10),
            ) if self.chain_verify_result else ft.Container(height=0),
            
            # 伝票リスト
            ft.Column(
                controls=slip_cards,
                spacing=10,
                scroll=ft.ScrollMode.AUTO,
                expand=True,
            ),
        ])
    def create_customer_picker_screen(self) -> ft.Container:
        """顧客選択画面（画面内遷移・ダイアログ不使用）"""
        self.customers = self.app_service.customer.get_all_customers()

        def back(_=None):
            self.is_customer_picker_open = False
            self.customer_search_query = ""
            self.update_main_content()
        
        # AppBar（戻るボタンあり）
        app_bar = AppBar(
            title="顧客選択",
            show_back=True,
            show_edit=False,
            on_back=back
        )

        list_container = ft.Column([], spacing=0, scroll=ft.ScrollMode.AUTO, expand=True)

        def render_list(customers: List[Customer]):
            list_container.controls.clear()
            for customer in customers:
                list_container.controls.append(
                    ft.ListTile(
                        title=ft.Text(customer.formal_name, weight=ft.FontWeight.BOLD),
                        subtitle=ft.Text(f"{customer.address}\n{customer.phone}"),
                        on_click=lambda _, c=customer: select_customer(c),
                    )
                )
            self.page.update()

        def select_customer(customer: Customer):
            self.selected_customer = customer
            # 新規伝票作成中の場合は顧客を設定
            if hasattr(self, 'editing_invoice') and self.editing_invoice:
                self.editing_invoice.customer = customer
                logging.info(f"伝票に顧客を設定: {customer.formal_name}")
            else:
                logging.info(f"顧客を選択: {customer.formal_name}")
            back()

        def on_search_change(e):
            q = (e.control.value or "").strip().lower()
            self.customer_search_query = q
            if not q:
                render_list(self.customers)
                return
            filtered = [
                c
                for c in self.customers
                if q in (c.name or "").lower()
                or q in (c.formal_name or "").lower()
                or q in (c.address or "").lower()
                or q in (c.phone or "").lower()
            ]
            render_list(filtered)

        search_field = ft.TextField(
            label="顧客検索",
            prefix_icon=ft.Icons.SEARCH,
            value=self.customer_search_query,
            on_change=on_search_change,
            autofocus=True,
        )

        header = ft.Container(
            content=ft.Row(
                [
                    ft.IconButton(ft.Icons.ARROW_BACK, on_click=back),
                    ft.Text("顧客を選択", size=18, weight=ft.FontWeight.BOLD),
                    ft.Container(expand=True),
                    ft.IconButton(
                        ft.Icons.PERSON_ADD,
                        tooltip="新規顧客追加",
                        icon_color=ft.Colors.WHITE,
                        on_click=lambda _: self.open_new_customer_form(),
                    ),
                ]
            ),
            padding=ft.padding.all(15),
            bgcolor=ft.Colors.BLUE_GREY,
        )

        content = ft.Column(
            [
                app_bar,  # AppBarを追加
                ft.Container(content=search_field, padding=ft.padding.all(15)),
                ft.Container(content=list_container, padding=ft.padding.symmetric(horizontal=15), expand=True),
            ],
            expand=True,
        )

        # 初期表示
        render_list(self.customers)

        return ft.Container(content=content, expand=True)
    
    def save_as_draft(self, _):
        """下書きとして保存"""
        try:
            # 下書き伝票を作成
            draft_invoice = self.app_service.invoice.create_draft_invoice(
                customer=self.selected_customer,
                document_type=DocumentType.DRAFT,
                amount=int(self.amount_value or "0"),
                notes="下書き"
            )
            
            if draft_invoice:
                logging.info(f"下書き保存成功: {draft_invoice.invoice_number}")
                # 一覧を更新
                self.invoices = self.app_service.invoice.get_recent_invoices(20)
                self.back_to_list()
            else:
                logging.error("下書き保存失敗")
        except Exception as e:
            logging.error(f"下書き保存エラー: {e}")
    
    def create_slip_input_screen(self) -> ft.Container:
        """伝票入力画面"""
        # 帳票種類選択（タブ風ボタン）
        document_types = list(DocumentType)
        
        type_buttons = ft.Row([
            ft.Container(
                content=ft.Button(
                    content=ft.Text(doc_type.value, size=12),
                    bgcolor=ft.Colors.BLUE_GREY_800 if doc_type == self.selected_document_type else ft.Colors.GREY_300,
                    color=ft.Colors.WHITE if doc_type == self.selected_document_type else ft.Colors.BLACK,
                    on_click=lambda _, idx=i, dt=doc_type: self.select_document_type(dt.value),
                    width=100,
                    height=45,
                ),
                margin=ft.margin.only(right=5),
            ) for i, doc_type in enumerate(document_types)
        ], wrap=True)
        
        # 下書きボタン（新規作成時のみ表示）
        draft_button = ft.Container(
            content=ft.ElevatedButton(
                content=ft.Row([
                    ft.Icon(ft.Icons.DRAFTS, size=16),
                    ft.Text("下書きとして保存", size=12),
                ], spacing=5),
                style=ft.ButtonStyle(
                    bgcolor=ft.Colors.ORANGE_500,
                    color=ft.Colors.WHITE,
                ),
                on_click=self.save_as_draft,
            ),
            margin=ft.margin.only(top=10),
        )
        
        return ft.Container(
            content=ft.Column([
                # ヘッダー
                ft.Container(
                    content=ft.Row([
                        ft.Text("📋 販売アシスト1号", size=20, weight=ft.FontWeight.BOLD),
                        ft.Container(expand=True),
                        ft.IconButton(ft.Icons.SETTINGS, icon_size=20),
                    ]),
                    padding=ft.padding.all(15),
                    bgcolor=ft.Colors.BLUE_GREY,
                ),
                
                # 帳票種類選択
                ft.Container(
                    content=ft.Column([
                        ft.Text("帳票の種類を選択", size=16, weight=ft.FontWeight.BOLD),
                        ft.Container(height=10),
                        type_buttons,
                        draft_button,  # 下書きボタンを追加
                    ]),
                    padding=ft.padding.all(20),
                ),
                
                # 顧客選択
                ft.Container(
                    content=ft.Column([
                        ft.Text("宛先と基本金額の設定", size=16, weight=ft.FontWeight.BOLD),
                        ft.Container(height=10),
                        ft.Row(
                            [
                                ft.TextField(
                                    label="取引先名",
                                    value=self.selected_customer.formal_name if self.selected_customer else "未選択",
                                    read_only=True,
                                    border_color=ft.Colors.BLUE_GREY,
                                    expand=True,
                                ),
                                ft.Container(width=8),  # スペースを追加
                                ft.IconButton(
                                    ft.Icons.PERSON_SEARCH,
                                    tooltip="顧客を選択",
                                    on_click=self.open_customer_picker,
                                ),
                            ],
                            alignment=ft.MainAxisAlignment.SPACE_BETWEEN,  # 検索ボタンを右端に配置
                        ),
                        ft.Container(height=10),
                        ft.TextField(
                            label="基本金額 (税抜)",
                            value=self.amount_value,
                            keyboard_type=ft.KeyboardType.NUMBER,
                            on_change=self.on_amount_change,
                            border_color=ft.Colors.BLUE_GREY,
                        ),
                    ]),
                    padding=ft.padding.all(20),
                ),
                
                # 作成ボタン
                ft.Container(
                    content=ft.Button(
                        content=ft.Row([
                            ft.Icon(ft.Icons.DESCRIPTION, color=ft.Colors.WHITE),
                            ft.Text("伝票を作成して詳細編集へ", color=ft.Colors.WHITE),
                        ], alignment=ft.MainAxisAlignment.CENTER),
                        style=ft.ButtonStyle(
                            bgcolor=ft.Colors.BLUE_GREY_800,
                            padding=ft.padding.all(20),
                            shape=ft.RoundedRectangleBorder(radius=15),
                        ),
                        width=400,
                        height=60,
                        on_click=self.create_slip,
                    ),
                    padding=ft.padding.all(20),
                ),
                
            ]),
            expand=True,
        )
    
    def create_slip_history_screen(self) -> ft.Container:
        """伝票履歴画面"""
        # 履歴データ読み込み
        slips = self.load_slips()
        if not self.show_offsets:
            slips = [s for s in slips if not (isinstance(s, Invoice) and getattr(s, "is_offset", False))]

        def on_toggle_offsets(e):
            self.show_offsets = bool(e.control.value)
            self.update_main_content()

        def on_verify_chain(e=None):
            res = self.app_service.invoice.invoice_repo.verify_chain()
            self.chain_verify_result = res
            self.update_main_content()
        
        # 履歴カードリスト
        slip_cards = []
        for slip in slips:
            card = self.create_slip_card(slip)
            slip_cards.append(card)
        
        return ft.Container(
            content=ft.Column([
                # ヘッダー（コンパクトに）
                ft.Container(
                    content=ft.Row([
                        ft.Text("📄 履歴", size=16, weight=ft.FontWeight.BOLD),  # 文字を小さく
                        ft.Container(expand=True),
                        ft.Row([
                            ft.IconButton(
                                ft.Icons.VERIFIED,
                                tooltip="チェーン検証",
                                icon_color=ft.Colors.BLUE_300,
                                icon_size=16,  # アイコンを小さく
                                on_click=on_verify_chain,
                            ),
                            ft.Row(
                                [
                                    ft.Text("赤伝", size=10, color=ft.Colors.WHITE),  # 文字を小さく
                                    ft.Switch(value=self.show_offsets, on_change=on_toggle_offsets),
                                ],
                                spacing=3,  # 間隔を狭める
                            ),
                            ft.IconButton(
                                ft.Icons.CLEAR_ALL, 
                                icon_size=16,  # アイコンを小さく
                            ),
                        ], spacing=3),  # 間隔を狭める
                    ]),
                    padding=ft.padding.all(8),  # パディングを狭める
                    bgcolor=ft.Colors.BLUE_GREY,
                ),

                # 検証結果表示（あれば）
                ft.Container(
                    content=self._build_chain_verify_result(),
                    margin=ft.Margin.only(bottom=5),  # 間隔を狭める
                ) if self.chain_verify_result else ft.Container(height=0),
                
                # 履歴リスト（極限密度表示）
                ft.Column(
                    controls=slip_cards,
                    spacing=0,  # カード間隔を0pxに
                    scroll=ft.ScrollMode.AUTO,
                    expand=True,
                ),
            ]),
            expand=True,
        )
    
    def can_create_offset_invoice(self, invoice: Invoice) -> bool:
        """赤伝発行可能かチェック"""
        # LOCK済み伝票であること
        if not getattr(invoice, 'final_locked', False):
            return False
        
        # すでに赤伝が存在しないこと
        try:
            import sqlite3
            with sqlite3.connect('sales.db') as conn:
                cursor = conn.cursor()
                cursor.execute(
                    'SELECT COUNT(*) FROM invoices WHERE offset_target_uuid = ?',
                    (invoice.uuid,)
                )
                offset_count = cursor.fetchone()[0]
                return offset_count == 0
        except Exception as e:
            logging.error(f"赤伝存在チェックエラー: {e}")
            return False
    
    def create_slip_card(self, slip) -> ft.Card:
        """伝票カード作成"""
        # サービス層からは Invoice オブジェクトが返る
        if isinstance(slip, Invoice):
            slip_type = slip.document_type.value
            customer_name = slip.customer.formal_name
            amount = slip.total_amount
            date = slip.date.strftime("%Y-%m-%d %H:%M")
            status = "赤伝" if getattr(slip, "is_offset", False) else "完了"
            # 最初の商品名を取得（複数ある場合は「他」を付与）
            if slip.items and len(slip.items) > 0:
                first_item_name = slip.items[0].description
                if len(slip.items) > 1:
                    first_item_name += "（他" + str(len(slip.items) - 1) + "）"
            else:
                first_item_name = ""
        else:
            slip_id, slip_type, customer_name, amount, date, status, description, created_at = slip
            date = date.strftime("%Y-%m-%d %H:%M")
            first_item_name = description or ""
        
        # タイプに応じたアイコンと色
        type_config = {
            "売上伝票": {"icon": "💰", "color": ft.Colors.GREEN},
            "見積書": {"icon": "📄", "color": ft.Colors.BLUE},
            "納品書": {"icon": "📦", "color": ft.Colors.PURPLE},
            "請求書": {"icon": "📋", "color": ft.Colors.ORANGE},
            "領収書": {"icon": "🧾", "color": ft.Colors.RED}
        }
        
        config = type_config.get(slip_type, {"icon": "📝", "color": ft.Colors.GREY})
        
        def on_single_tap(_):
            """シングルタップ：詳細表示"""
            if isinstance(slip, Invoice):
                self.open_invoice_detail(slip)
        
        def on_double_tap(_):
            """ダブルタップ：編集モード切替"""
            if isinstance(slip, Invoice):
                self.open_invoice_edit(slip)
        
        def on_long_press(_):
            """長押し：コンテキストメニュー"""
            self.show_context_menu(slip)
        
        # 赤伝ボタンの表示条件チェック
        show_offset_button = False
        if isinstance(slip, Invoice):
            show_offset_button = self.can_create_offset_invoice(slip)
        
        # 長押しメニューで操作するため、ボタンは不要
        
        display_amount = amount
        if isinstance(slip, Invoice) and getattr(slip, "is_offset", False):
            display_amount = -abs(amount)
        
        return ft.GestureDetector(
            content=ft.Card(
                content=ft.Container(
                    content=ft.Column([
                        ft.Row([
                            ft.Container(
                                content=ft.Text(config["icon"], size=16),  # アイコンを少し大きく
                                width=28,
                                height=28,
                                bgcolor=config["color"],
                                border_radius=14,
                                alignment=ft.alignment.Alignment(0, 0),
                            ),
                            ft.Container(
                                content=ft.Column([
                                    ft.Text(slip_type, size=7, weight=ft.FontWeight.BOLD),  # タイプ文字をさらに小さく
                                    ft.Text(customer_name, size=15, weight=ft.FontWeight.W_500),  # 顧客名を1.5倍に
                                    ft.Row([
                                        ft.Text(first_item_name, size=12, color=ft.Colors.GREY_600),  # 商品名をさらに大きく
                                        ft.Container(expand=True),  # スペースを取る
                                        ft.Text(f"¥{display_amount:,.0f}", size=11, weight=ft.FontWeight.BOLD),  # 金額を右寄せ
                                    ]),
                                ],
                                spacing=0,  # 行間を最小化
                                tight=True,  # 余白を最小化
                                ),
                                expand=True,
                            ),
                        ]),
                        ft.Container(height=0),  # 間隔を完全に削除
                        ft.Row([
                            ft.Text(f"{date} | {status}", size=9, color=ft.Colors.GREY_600),  # 日付を大きく
                            ft.Container(expand=True),  # スペースを取る
                            # 赤伝ボタン（条件付きで表示）
                            ft.Container(
                                content=ft.IconButton(
                                    icon=ft.icons.REMOVE_CIRCLE_OUTLINE,
                                    icon_color=ft.Colors.RED_500,
                                    icon_size=16,
                                    tooltip="赤伝発行",
                                    on_click=lambda _: self.create_offset_invoice_dialog(slip),
                                    disabled=not show_offset_button
                                ) if show_offset_button else ft.Container(width=20),
                            ),
                        ]),
                    ],
                    spacing=0,  # カラムの行間を最小化
                    tight=True,  # 余白を最小化
                    ),
                    padding=ft.padding.all(2),  # パディングを最小化
                ),
                elevation=0,
            ),
            on_tap=on_single_tap,
            on_double_tap=on_double_tap,
            on_long_press=on_long_press,
        )
    
    def create_offset_invoice_dialog(self, invoice: Invoice):
        """赤伝発行確認ダイアログ"""
        def close_dialog(_):
            self.dialog.open = False
            self.update_main_content()
        
        def confirm_create_offset(_):
            # 赤伝を発行
            offset_invoice = self.app_service.invoice.create_offset_invoice(
                invoice.uuid, 
                f"相殺伝票: {invoice.invoice_number}"
            )
            if offset_invoice:
                logging.info(f"赤伝発行成功: {offset_invoice.invoice_number}")
                # 一覧を更新
                self.invoices = self.app_service.invoice.get_recent_invoices(20)
                self.update_main_content()
            else:
                logging.error(f"赤伝発行失敗: {invoice.invoice_number}")
            close_dialog(_)
        
        # 確認ダイアログ
        self.dialog = ft.AlertDialog(
            modal=True,
            title=ft.Text("赤伝発行確認"),
            content=ft.Column([
                ft.Text(f"以下の伝票の赤伝を発行します。"),
                ft.Container(height=10),
                ft.Text(f"伝票番号: {invoice.invoice_number}"),
                ft.Text(f"顧客: {invoice.customer.formal_name}"),
                ft.Text(f"金額: ¥{invoice.total_amount:,.0f}"),
                ft.Container(height=10),
                ft.Text("赤伝発行後は取り消せません。よろしいですか？", 
                       color=ft.Colors.RED, weight=ft.FontWeight.BOLD),
            ], tight=True),
            actions=[
                ft.TextButton("キャンセル", on_click=close_dialog),
                ft.ElevatedButton(
                    "赤伝発行", 
                    on_click=confirm_create_offset,
                    style=ft.ButtonStyle(
                        color=ft.Colors.WHITE,
                        bgcolor=ft.Colors.RED_500
                    )
                ),
            ],
            actions_alignment=ft.MainAxisAlignment.END,
        )
        
        self.dialog.open = True
        self.update_main_content()
    
    def show_context_menu(self, slip):
        """コンテキストメニューを表示"""
        if not isinstance(slip, Invoice):
            return
        
        def close_dialog(_):
            self.dialog.open = False
            self.update_main_content()
        
        def edit_invoice(_):
            self.open_invoice_edit(slip)
            close_dialog(_)
        
        def delete_invoice(_):
            self.delete_invoice(slip.uuid)
            close_dialog(_)
        
        def create_offset(_):
            self.create_offset_invoice_dialog(slip)
            close_dialog(_)
        
        # メニューアイテムの構築
        menu_items = []
        
        # 編集メニュー
        if not getattr(slip, 'final_locked', False):
            menu_items.append(
                ft.PopupMenuItem(
                    text=ft.Row([
                        ft.Icon(ft.Icons.EDIT, size=16),
                        ft.Text("編集", size=14),
                    ], spacing=8),
                    on_click=edit_invoice
                )
            )
        
        # 赤伝発行メニュー
        if self.can_create_offset_invoice(slip):
            menu_items.append(
                ft.PopupMenuItem(
                    text=ft.Row([
                        ft.Icon(ft.Icons.REMOVE_CIRCLE, size=16),
                        ft.Text("赤伝発行", size=14),
                    ], spacing=8),
                    on_click=create_offset
                )
            )
        
        # 削除メニュー
        menu_items.append(
            ft.PopupMenuItem(
                text=ft.Row([
                    ft.Icon(ft.Icons.DELETE, size=16),
                    ft.Text("削除", size=14),
                ], spacing=8),
                on_click=delete_invoice
            )
        )
        
        # コンテキストメニューダイアログ
        self.dialog = ft.AlertDialog(
            modal=True,
            title=ft.Text(f"操作選択: {slip.invoice_number}"),
            content=ft.Column(menu_items, tight=True, spacing=2),
            actions=[
                ft.TextButton("キャンセル", on_click=close_dialog),
            ],
            actions_alignment=ft.MainAxisAlignment.END,
        )
        
        self.dialog.open = True
        self.update_main_content()
    
    def open_invoice_detail(self, invoice: Invoice):
        """伝票詳細を開く"""
        self.editing_invoice = invoice
        self.current_tab = 1
        self.is_detail_edit_mode = False  # 表示モードで開く
        self.update_main_content()
    
    def open_invoice_edit(self, invoice: Invoice):
        """伝票編集を開く"""
        self.editing_invoice = invoice
        self.current_tab = 1
        self.is_detail_edit_mode = True  # 編集モードで開く
        self.update_main_content()
    
    def delete_invoice(self, invoice_uuid: str):
        """伝票を削除"""
        try:
            success = self.app_service.invoice.delete_invoice_by_uuid(invoice_uuid)
            if success:
                logging.info(f"伝票削除成功: {invoice_uuid}")
                # リストを更新
                self.invoices = self.app_service.invoice.get_recent_invoices(20)
                self.update_main_content()
            else:
                logging.error(f"伝票削除失敗: {invoice_uuid}")
        except Exception as e:
            logging.error(f"伝票削除エラー: {e}")
    
    def _build_chain_verify_result(self) -> ft.Control:
        if not self.chain_verify_result:
            return ft.Container(height=0)
        r = self.chain_verify_result
        ok = r.get("ok", False)
        checked = r.get("checked", 0)
        errors = r.get("errors", [])
        if ok:
            return ft.Container(
                content=ft.Row([
                    ft.Icon(ft.Icons.CHECK_CIRCLE, color=ft.Colors.GREEN, size=20),
                    ft.Text(f"チェーン検証 OK ({checked}件)", size=14, color=ft.Colors.GREEN),
                ]),
                bgcolor=ft.Colors.GREEN_50,
                padding=ft.Padding.all(10),
                border_radius=8,
            )
        else:
            return ft.Container(
                content=ft.Column([
                    ft.Row([
                        ft.Icon(ft.Icons.ERROR, color=ft.Colors.RED, size=20),
                        ft.Text(f"チェーン検証 NG (checked={checked})", size=14, color=ft.Colors.RED),
                    ]),
                    ft.Text(f"エラー: {errors}", size=12, color=ft.Colors.RED_700),
                ]),
                bgcolor=ft.Colors.RED_50,
                padding=ft.Padding.all(10),
                border_radius=8,
            )
    
    def open_invoice_edit(self, invoice: Invoice):
        """伝票編集画面を開く"""
        self.editing_invoice = invoice
        self.is_edit_mode = True
        self.selected_customer = invoice.customer
        self.selected_document_type = invoice.document_type
        self.amount_value = str(invoice.items[0].unit_price if invoice.items else "0")
        self.is_detail_edit_mode = False  # 初期はビューモード
        self.current_tab = 1  # 詳細編集タブに切り替え
        self.update_main_content()
    
    def open_new_customer_form(self):
        """新規顧客フォームを開く（画面内遷移）"""
        self.is_new_customer_form_open = True
        self.update_main_content()

    def create_invoice_edit_screen(self) -> ft.Container:
        """伝票編集画面（新規・編集統合）"""
        # 常に詳細編集画面を使用
        if not self.editing_invoice:
            # 新規伝票の場合は空のInvoiceを作成
            from models.invoice_models import Invoice, Customer, DocumentType
            default_customer = Customer(
                id=0,
                name="選択してください",
                formal_name="選択してください",
                address="",
                phone=""
            )
            self.editing_invoice = Invoice(
                customer=default_customer,
                date=datetime.now(),
                items=[],
                document_type=DocumentType.SALES,
                invoice_number="NEW-" + str(int(datetime.now().timestamp()))  # 新規伝票番号
            )
            self.is_detail_edit_mode = True  # 新規作成モード
        
        # 既存・新規共通で詳細編集画面を返す
        return self._create_edit_existing_screen()
    
    def _create_edit_existing_screen(self) -> ft.Container:
        """既存伝票の編集画面（新規・編集共通）"""
        # 編集不可チェック（新規作成時はFalse）
        is_new_invoice = self.editing_invoice.invoice_number.startswith("NEW-")
        
        # LOCK条件：明示的に確定された場合のみLOCK
        # PDF生成だけではLOCKしない（お試しPDFを許可）
        pdf_generated = getattr(self.editing_invoice, 'pdf_generated_at', None) is not None
        chain_hash = getattr(self.editing_invoice, 'chain_hash', None) is not None
        final_locked = getattr(self.editing_invoice, 'final_locked', False)  # 明示的確定フラグ
        
        is_locked = final_locked if not is_new_invoice else False
        is_view_mode = not getattr(self, 'is_detail_edit_mode', False)
        
        # デバッグ用にLOCK状態をログ出力
        logging.info(f"伝票LOCK状態: {self.editing_invoice.invoice_number}")
        logging.info(f"  PDF生成: {pdf_generated}")
        logging.info(f"  チェーン収容: {chain_hash}")
        logging.info(f"  明示的確定: {final_locked}")
        logging.info(f"  LOCK状態: {is_locked}")
        logging.info(f"  新規伝票: {is_new_invoice}")
        logging.info(f"  編集モード: {getattr(self, 'is_detail_edit_mode', False)}")
        logging.info(f"  表示モード: {is_view_mode}")
        
        # 伝票種類選択（ヘッダーに移動）
        document_types = list(DocumentType)
        
        # 明細テーブル
        if is_view_mode:
            items_table = self._create_view_mode_table(self.editing_invoice.items)
        else:
            items_table = self._create_edit_mode_table(self.editing_invoice.items, is_locked)
        
        # 顧客表示・選択
        def select_customer():
            """顧客選択画面を開く"""
            self.current_tab = 2  # 顧客選択タブ
            self.update_main_content()
        
        # 編集モード時は顧客名入力フィールドを表示
        if not is_view_mode and not is_locked:
            # 編集モード：顧客名入力フィールド
            customer_field = ft.TextField(
                label="顧客名",
                value=self.editing_invoice.customer.name if self.editing_invoice.customer.name != "選択してください" else "",
                disabled=is_locked,
                width=300,
            )
            
            def update_customer_name(e):
                """顧客名を更新"""
                if self.editing_invoice:
                    # 既存顧客を検索、なければ新規作成
                    customer_name = e.control.value or ""
                    found_customer = None
                    for customer in self.app_service.customer.get_all_customers():
                        if customer.name == customer_name or customer.formal_name == customer_name:
                            found_customer = customer
                            break
                    
                    if found_customer:
                        self.editing_invoice.customer = found_customer
                    else:
                        # 新規顧客を作成
                        from models.invoice_models import Customer
                        self.editing_invoice.customer = Customer(
                            id=0,
                            name=customer_name,
                            formal_name=customer_name,
                            address="",
                            phone=""
                        )
            
            customer_field.on_change = update_customer_name
            
            customer_display = ft.Container(
                content=ft.Row([
                    customer_field,  # 顧客ラベルを削除
                    ft.ElevatedButton(
                        "選択",
                        icon=ft.Icons.PERSON_SEARCH,
                        on_click=lambda _: select_customer(),
                        style=ft.ButtonStyle(
                            bgcolor=ft.Colors.BLUE_600,
                            color=ft.Colors.WHITE
                        )
                    ),
                ]),
                padding=ft.padding.symmetric(horizontal=10, vertical=5),
                bgcolor=ft.Colors.BLUE_50,
                border_radius=5,
            )
        elif is_new_invoice:
            # 新規作成時も同じ表示
            customer_field = ft.TextField(
                label="顧客名",
                value=self.editing_invoice.customer.name if self.editing_invoice.customer.name != "選択してください" else "",
                disabled=is_locked,
                width=300,
            )
            
            def update_customer_name(e):
                """顧客名を更新"""
                if self.editing_invoice:
                    # 既存顧客を検索、なければ新規作成
                    customer_name = e.control.value or ""
                    found_customer = None
                    for customer in self.app_service.customer.get_all_customers():
                        if customer.name == customer_name or customer.formal_name == customer_name:
                            found_customer = customer
                            break
                    
                    if found_customer:
                        self.editing_invoice.customer = found_customer
                    else:
                        # 新規顧客を作成
                        from models.invoice_models import Customer
                        self.editing_invoice.customer = Customer(
                            id=0,
                            name=customer_name,
                            formal_name=customer_name,
                            address="",
                            phone=""
                        )
            
            customer_field.on_change = update_customer_name
            
            customer_display = ft.Container(
                content=ft.Row([
                    customer_field,  # 顧客ラベルを削除
                    ft.ElevatedButton(
                        "選択",
                        icon=ft.Icons.PERSON_SEARCH,
                        on_click=lambda _: select_customer(),
                        style=ft.ButtonStyle(
                            bgcolor=ft.Colors.BLUE_600,
                            color=ft.Colors.WHITE
                        )
                    ),
                ]),
                padding=ft.padding.symmetric(horizontal=10, vertical=5),
                bgcolor=ft.Colors.BLUE_50,
                border_radius=5,
            )
        else:
            # 既存伝票は表示のみ
            customer_display = ft.Container(
                content=ft.Row([
                    ft.Text(self.editing_invoice.customer.name),  # 顧客ラベルを削除
                ]),
                padding=ft.padding.symmetric(horizontal=10, vertical=5),
                bgcolor=ft.Colors.GREY_100,
                border_radius=5,
            )
        
        # 備考フィールド
        notes_field = ft.TextField(
            label="備考",
            value=getattr(self.editing_invoice, 'notes', ''),
            disabled=is_locked or is_view_mode,
            multiline=True,
            min_lines=2,
            max_lines=3,
        )
        
        def toggle_edit_mode(_):
            """編集モード切替"""
            old_mode = getattr(self, 'is_detail_edit_mode', False)
            self.is_detail_edit_mode = not old_mode
            logging.debug(f"Toggle edit mode: {old_mode} -> {self.is_detail_edit_mode}")
            self.update_main_content()
        
        def save_changes(_):
            if is_locked:
                return
            
            # 伝票を更新（現在の明細を保持）
            # テーブルから実際の値を取得して更新
            self.editing_invoice.notes = notes_field.value
            self.editing_invoice.document_type = self.selected_document_type
            
            # TODO: テーブルの明細データを取得して更新
            # 現在は編集された明細データが反映されていない
            logging.info(f"更新前明細件数: {len(self.editing_invoice.items)}")
            for i, item in enumerate(self.editing_invoice.items):
                logging.info(f"  明細{i+1}: {item.description} x{item.quantity} @¥{item.unit_price}")
            
            # DBに保存（新規・更新共通）
            try:
                if is_new_invoice:
                    # 新規作成
                    logging.info(f"=== 新規伝票作成開 ===")
                    logging.info(f"顧客情報: {self.editing_invoice.customer.name} (ID: {self.editing_invoice.customer.id})")
                    logging.info(f"伝票種類: {self.editing_invoice.document_type.value}")
                    logging.info(f"明細件数: {len(self.editing_invoice.items)}")
                    
                    # 顧客を先にDBに保存（新規顧客の場合）
                    if self.editing_invoice.customer.id == 0:
                        logging.info(f"新規顧客をDBに保存します: {self.editing_invoice.customer.name}")
                        # 新規顧客をDBに保存
                        customer_id = self.app_service.customer.create_customer(
                            name=self.editing_invoice.customer.name,
                            formal_name=self.editing_invoice.customer.formal_name,
                            address=self.editing_invoice.customer.address,
                            phone=self.editing_invoice.customer.phone
                        )
                        logging.info(f"create_customer戻り値: {customer_id}")
                        if customer_id > 0:  # IDが正しく取得できたかチェック
                            self.editing_invoice.customer.id = customer_id
                            logging.info(f"新規顧客をDBに保存: {self.editing_invoice.customer.name} (ID: {customer_id})")
                        else:
                            logging.error(f"顧客保存失敗: {self.editing_invoice.customer.name}")
                            return
                    
                    # 合計金額は表示時に計算するため、DBには保存しない
                    amount = 0  # ダミー値（実際は表示時に計算）
                    
                    logging.info(f"伝票作成パラメータ: customer.id={self.editing_invoice.customer.id}, document_type={self.editing_invoice.document_type}, amount={amount}")
                    
                    success = self.app_service.invoice.create_invoice(
                        customer=self.editing_invoice.customer,
                        document_type=self.editing_invoice.document_type,
                        amount=amount,
                        notes=getattr(self.editing_invoice, 'notes', ''),
                        items=self.editing_invoice.items  # UIの明細を渡す
                    )
                    logging.info(f"create_invoice戻り値: {success}")
                    if success:
                        logging.info(f"伝票作成成功: {self.editing_invoice.invoice_number}")
                        # 一覧を更新して新規作成画面を閉じる
                        self.invoices = self.app_service.invoice.get_recent_invoices(20)
                        logging.info(f"更新後伝票件数: {len(self.invoices)}")
                        self.editing_invoice = None
                        self.current_tab = 0  # 一覧タブに戻る
                        self.update_main_content()
                    else:
                        logging.error(f"伝票作成失敗: {self.editing_invoice.invoice_number}")
                else:
                    # 更新
                    logging.info(f"=== 伝票更新開 ===")
                    success = self.app_service.invoice.update_invoice(self.editing_invoice)
                    if success:
                        logging.info(f"伝票更新成功: {self.editing_invoice.invoice_number}")
                        # 一覧を更新して編集画面を閉じる
                        self.invoices = self.app_service.invoice.get_recent_invoices(20)
                        self.editing_invoice = None
                        self.current_tab = 0  # 一覧タブに戻る
                        self.update_main_content()
                    else:
                        logging.error(f"伝票更新失敗: {self.editing_invoice.invoice_number}")
            except Exception as e:
                logging.error(f"伝票保存エラー: {e}")
                import traceback
                logging.error(f"詳細エラー: {traceback.format_exc()}")
            
            # 編集モード終了（ビューモードに戻る）
            self.is_detail_edit_mode = False  # ビューモードに戻る
            self.update_main_content()
        
        def cancel_edit(_):
            self.is_detail_edit_mode = False
            self.is_edit_mode = False
            self.editing_invoice = None
            self.current_tab = 0  # 一覧タブに戻る
            self.update_main_content()
        
        return ft.Container(
            content=ft.Column([
                # ヘッダー
                ft.Container(
                    content=ft.Row([
                        ft.Container(expand=True),
                        # コンパクトな伝票種類選択（セグメント化）
                        ft.Container(
                            content=ft.Row([
                                ft.GestureDetector(
                                    content=ft.Container(
                                        content=ft.Text(
                                            doc_type.value,
                                            size=10,
                                            color=ft.Colors.WHITE if doc_type == self.editing_invoice.document_type else ft.Colors.GREY_600,
                                            weight=ft.FontWeight.BOLD if doc_type == self.editing_invoice.document_type else ft.FontWeight.NORMAL,
                                        ),
                                        padding=ft.padding.symmetric(horizontal=8, vertical=4),
                                        bgcolor=ft.Colors.BLUE_600 if doc_type == self.editing_invoice.document_type else ft.Colors.GREY_300,
                                        border_radius=ft.border_radius.all(4),
                                        margin=ft.margin.only(right=1),
                                    ),
                                    on_tap=lambda _, dt=doc_type: self.select_document_type(dt.value) if not is_locked and not is_view_mode else None,
                                ) for doc_type in document_types
                            ]),
                            padding=ft.padding.all(2),
                            bgcolor=ft.Colors.GREY_200,
                            border_radius=ft.border_radius.all(6),
                            margin=ft.margin.only(right=10),
                        ),
                        ft.ElevatedButton(
                            content=ft.Text("編集" if is_view_mode else "保存"),
                            style=ft.ButtonStyle(
                                bgcolor=ft.Colors.BLUE_600 if is_view_mode else ft.Colors.GREEN_600,
                            ),
                            on_click=toggle_edit_mode if is_view_mode else save_changes,
                            disabled=is_locked,
                            width=70,
                            height=30,
                        ) if not is_locked else ft.Container(),
                        ft.Container(width=5),
                        ft.IconButton(ft.Icons.CLOSE, on_click=cancel_edit),
                    ]),
                    padding=ft.padding.symmetric(horizontal=15, vertical=8),
                    bgcolor=ft.Colors.BLUE_GREY,
                ),
                
                # 基本情報行（コンパクトに）
                ft.Container(
                    content=ft.Row([
                        ft.Text(f"{self.editing_invoice.invoice_number} | {self.editing_invoice.date.strftime('%Y/%m/%d %H:%M')} | {self.editing_invoice.customer.name}", size=12, weight=ft.FontWeight.BOLD),
                        ft.Container(expand=True),
                    ]),
                    padding=ft.padding.symmetric(horizontal=15, vertical=3),
                    bgcolor=ft.Colors.GREY_50,
                ),
                
                # 顧客名入力（編集モードまたは新規作成時）
                customer_display if (not is_view_mode and not is_locked) or is_new_invoice else ft.Container(height=0),
                
                # 明細テーブル（フレキシブルに）
                ft.Container(
                    content=ft.Column([
                        ft.Container(
                            content=items_table,
                            height=400,  # 高さを拡大して見やすく
                            border=ft.border.all(1, ft.Colors.GREY_300),
                            border_radius=5,
                            padding=ft.padding.all(1),  # パディングを最小化
                            width=None,  # 幅を可変に
                            expand=True,  # 利用可能な幅を全て使用
                        ),
                        ft.Container(height=10),
                        # 合計金額表示
                        ft.Container(
                            content=ft.Row([
                                ft.Text("合計: ", size=14, weight=ft.FontWeight.BOLD),  # 左に詰める
                                ft.Text(
                                    f"¥{sum(item.subtotal for item in self.editing_invoice.items):,}",
                                    size=16,
                                    weight=ft.FontWeight.BOLD,
                                    color=ft.Colors.BLUE_600
                                ),
                                ft.Container(expand=True),  # スペースを取る
                                # ＋ボタンを右端に配置
                                ft.IconButton(
                                    ft.Icons.ADD_CIRCLE_OUTLINE,
                                    tooltip="行を追加",
                                    icon_color=ft.Colors.GREEN_600,
                                    disabled=is_locked or is_view_mode,
                                    on_click=lambda _: self._add_item_row(),
                                ) if not is_locked and not is_view_mode else ft.Container(),
                            ]),
                            padding=ft.padding.symmetric(horizontal=5, vertical=8),  # 左右のパディングを減らす
                            bgcolor=ft.Colors.GREY_100,
                            border_radius=5,
                        ),
                    ]),
                    padding=ft.padding.all(15),
                    expand=True,  # 明細部分が最大限のスペースを占有
                ),
                
                # 備考（コンパクト）
                ft.Container(
                    content=ft.Column([
                        ft.Text("備考", size=12, weight=ft.FontWeight.BOLD),
                        ft.Container(height=3),
                        notes_field,
                        ft.Container(height=5),
                        ft.Text("🔒 税務署提出済みは編集できません" if is_locked else "✅ " + ("編集モード" if not is_view_mode else "ビューモード"), 
                               size=11, color=ft.Colors.RED_600 if is_locked else (ft.Colors.GREEN_600 if not is_view_mode else ft.Colors.BLUE_600)),
                        ft.Container(height=10),
                        # PDF生成ボタンを追加
                        ft.ElevatedButton(
                            content=ft.Row([
                                ft.Icon(ft.Icons.DOWNLOAD, size=16),
                                ft.Container(width=5),
                                ft.Text("PDF生成", size=12, color=ft.Colors.WHITE),
                            ]),
                            style=ft.ButtonStyle(
                                bgcolor=ft.Colors.BLUE_600,
                                padding=ft.padding.symmetric(horizontal=15, vertical=10),
                            ),
                            on_click=lambda _: self.generate_pdf_from_edit(),
                            width=120,
                            height=40,
                        ) if not is_locked else ft.Container(),
                    ]),
                    padding=ft.padding.symmetric(horizontal=15, vertical=10),
                    bgcolor=ft.Colors.GREY_50,
                ),
            ]),
            expand=True,
        )
    def generate_pdf_from_edit(self):
        """編集画面からPDFを生成"""
        if not self.editing_invoice:
            return
        
        try:
            pdf_path = self.app_service.invoice.regenerate_pdf(self.editing_invoice.uuid)
            if pdf_path:
                self.editing_invoice.file_path = pdf_path
                self.editing_invoice.pdf_generated_at = datetime.now().replace(microsecond=0).isoformat()
                logging.info(f"PDF生成完了: {pdf_path}")
                # TODO: 成功メッセージ表示
            else:
                logging.error("PDF生成失敗")
                # TODO: エラーメッセージ表示
        except Exception as e:
            logging.error(f"PDF生成エラー: {e}")
            # TODO: エラーメッセージ表示
    
    def _add_item_row(self):
        """明細行を追加"""
        if not self.editing_invoice:
            return
        
        # 空の明細行を追加（デフォルト値なし）
        new_item = InvoiceItem(
            description="",
            quantity=0,
            unit_price=0,
        )
        
        # 元のinvoice.itemsに直接追加
        self.editing_invoice.items.append(new_item)
        
        # UIを更新
        self.update_main_content()
    
    def _delete_item_row(self, index: int):
        """明細行を削除"""
        if not self.editing_invoice or index >= len(self.editing_invoice.items):
            return
        
        # 行を削除（最低1行は残す）
        if len(self.editing_invoice.items) > 1:
            del self.editing_invoice.items[index]
            self.update_main_content()
    
    def _update_item_field(self, item_index: int, field_name: str, value: str):
        """明細フィールドを更新"""
        if not self.editing_invoice or item_index >= len(self.editing_invoice.items):
            return
        
        item = self.editing_invoice.items[item_index]
        
        # デバッグ用：更新前の値をログ出力
        old_value = getattr(item, field_name)
        logging.debug(f"Updating item {item_index} {field_name}: '{old_value}' -> '{value}'")
        
        if field_name == 'description':
            item.description = value
        elif field_name == 'quantity':
            try:
                # 空文字の場合は1を設定
                if not value or value.strip() == '':
                    item.quantity = 1
                else:
                    item.quantity = int(value)
                logging.debug(f"Quantity updated to: {item.quantity}")
            except ValueError as e:
                item.quantity = 1
                logging.error(f"Quantity update error: {e}")
        elif field_name == 'unit_price':
            try:
                # 空文字の場合は0を設定
                if not value or value.strip() == '':
                    item.unit_price = 0
                else:
                    item.unit_price = int(value)
                logging.debug(f"Unit price updated to: {item.unit_price}")
            except ValueError as e:
                item.unit_price = 0
                logging.error(f"Unit price update error: {e}")
        
        # 合計金額を更新するために画面を更新
        # 空行削除ロジック：商品名が無く数量も単価も０なら削除
        self._remove_empty_items()
        self.update_main_content()
    
    def _remove_empty_items(self):
        """商品名が無く数量も単価も０の明細を削除"""
        if not self.editing_invoice:
            return
        
        # 空行を特定（ただし最低1行は残す）
        non_empty_items = []
        empty_count = 0
        
        for item in self.editing_invoice.items:
            if (not item.description or item.description.strip() == "") and \
               item.quantity == 0 and \
               item.unit_price == 0:
                empty_count += 1
                # 最低1行は残すため、空行が複数ある場合のみ削除
                if empty_count > 1:
                    continue  # 削除
            non_empty_items.append(item)
        
        self.editing_invoice.items = non_empty_items
    
    def _create_view_mode_table(self, items: List[InvoiceItem]) -> ft.Column:
        """表示モード：フレキシブルな表形式で整然と表示"""
        # ヘッダー行
        header_row = ft.Row([
            ft.Text("商品名", size=12, weight=ft.FontWeight.BOLD, expand=True),  # 可変幅
            ft.Text("数", size=12, weight=ft.FontWeight.BOLD, width=35),  # 固定幅
            ft.Text("単価", size=12, weight=ft.FontWeight.BOLD, width=70),  # 固定幅
            ft.Text("小計", size=12, weight=ft.FontWeight.BOLD, width=70),  # 固定幅
            ft.Container(width=35),  # 削除ボタン用スペースを確保
        ])
        
        # データ行
        data_rows = []
        for i, item in enumerate(items):
            row = ft.Row([
                ft.Text(item.description, size=12, expand=True),  # 可変幅
                ft.Text(str(item.quantity), size=12, width=35, text_align=ft.TextAlign.RIGHT),  # 固定幅
                ft.Text(f"¥{item.unit_price:,}", size=12, width=70, text_align=ft.TextAlign.RIGHT),  # 固定幅
                ft.Text(f"¥{item.subtotal:,}", size=12, weight=ft.FontWeight.BOLD, width=70, text_align=ft.TextAlign.RIGHT),  # 固定幅
                ft.Container(width=35),  # 削除ボタン用スペース
            ])
            data_rows.append(row)
        
        return ft.Column([
            header_row,
            ft.Divider(height=1, color=ft.Colors.GREY_400),
            ft.Column(data_rows, scroll=ft.ScrollMode.AUTO, height=250),  # 高さを制限
        ])
    
    def _create_edit_mode_table(self, items: List[InvoiceItem], is_locked: bool) -> ft.Column:
        """編集モード：フレキシブルな表形式"""
        # 自動空行追加を無効化（ユーザーが明示的に追加する場合のみ）
        # TODO: 必要に応じて空行追加ボタンを提供
        
        # 空行の自動追加を無効化
        pass
        
        # ヘッダー行
        header_row = ft.Row([
            ft.Text("商品名", size=12, weight=ft.FontWeight.BOLD, expand=True),  # 可変幅
            ft.Text("数", size=12, weight=ft.FontWeight.BOLD, width=35),  # 固定幅
            ft.Text("単価", size=12, weight=ft.FontWeight.BOLD, width=70),  # 固定幅
            ft.Text("小計", size=12, weight=ft.FontWeight.BOLD, width=70),  # 固定幅
            ft.Container(width=35),  # 削除ボタン用スペースを確保
        ])
        
        # データ行
        data_rows = []
        for i, item in enumerate(items):
            # 商品名フィールド
            product_field = ft.TextField(
                value=item.description,
                text_size=12,
                height=28,
                width=None,  # 幅を可変に
                expand=True,  # 可変幅
                border=ft.border.all(1, ft.Colors.BLUE_200),
                bgcolor=ft.Colors.WHITE,
                content_padding=ft.padding.all(5),  # 内部余白を最小化
                on_change=lambda e, idx=i: self._update_item_field(idx, 'description', e.control.value),
            )
            
            # 数量フィールド
            quantity_field = ft.TextField(
                value=str(item.quantity),
                text_size=12,
                height=28,
                width=35,  # 固定幅
                text_align=ft.TextAlign.RIGHT,
                border=ft.border.all(1, ft.Colors.BLUE_200),
                bgcolor=ft.Colors.WHITE,
                content_padding=ft.padding.all(5),  # 内部余白を最小化
                on_change=lambda e, idx=i: self._update_item_field(idx, 'quantity', e.control.value),
                keyboard_type=ft.KeyboardType.NUMBER,
            )
            
            # 単価フィールド
            unit_price_field = ft.TextField(
                value=f"{item.unit_price:,}",
                text_size=12,
                height=28,
                width=70,  # 固定幅
                text_align=ft.TextAlign.RIGHT,
                border=ft.border.all(1, ft.Colors.BLUE_200),
                bgcolor=ft.Colors.WHITE,
                content_padding=ft.padding.all(5),  # 内部余白を最小化
                on_change=lambda e, idx=i: self._update_item_field(idx, 'unit_price', e.control.value.replace(',', '')),
                keyboard_type=ft.KeyboardType.NUMBER,
            )
            
            # 削除ボタン
            delete_button = ft.IconButton(
                ft.Icons.DELETE_OUTLINE,
                tooltip="行を削除",
                icon_color=ft.Colors.RED_600,
                disabled=is_locked,
                icon_size=16,
                on_click=lambda _, idx=i: self._delete_item_row(idx),
            )
            
            # データ行
            row = ft.Row([
                product_field,
                quantity_field,
                unit_price_field,
                ft.Text(f"¥{item.subtotal:,}", size=12, weight=ft.FontWeight.BOLD, width=70, text_align=ft.TextAlign.RIGHT),  # 固定幅
                delete_button,
            ])
            data_rows.append(row)
        
        return ft.Column([
            header_row,
            ft.Divider(height=1, color=ft.Colors.GREY_400),
            ft.Column(data_rows, scroll=ft.ScrollMode.AUTO, height=250),  # 高さを制限
        ])
    def create_new_customer_screen(self) -> ft.Container:
        """新規顧客登録画面"""
        name_field = ft.TextField(label="顧客名（略称）")
        formal_name_field = ft.TextField(label="正式名称")
        address_field = ft.TextField(label="住所")
        phone_field = ft.TextField(label="電話番号")

        def save_customer(_):
            name = (name_field.value or "").strip()
            formal_name = (formal_name_field.value or "").strip()
            address = (address_field.value or "").strip()
            phone = (phone_field.value or "").strip()
            if not name or not formal_name:
                # TODO: エラー表示
                return
            new_customer = self.app_service.customer.create_customer(name, formal_name, address, phone)
            if new_customer:
                self.customers = self.app_service.customer.get_all_customers()
                self.selected_customer = new_customer
                logging.info(f"新規顧客登録: {new_customer.formal_name}")
                self.is_customer_picker_open = False
                self.is_new_customer_form_open = False
                self.update_main_content()
            else:
                logging.error("新規顧客登録失敗")

        def cancel(_):
            self.is_new_customer_form_open = False
            self.update_main_content()

        return ft.Container(
            content=ft.Column([
                ft.Container(
                    content=ft.Row([
                        ft.IconButton(ft.Icons.ARROW_BACK, on_click=cancel),
                        ft.Text("新規顧客登録", size=18, weight=ft.FontWeight.BOLD),
                    ]),
                    padding=ft.padding.all(15),
                    bgcolor=ft.Colors.BLUE_GREY,
                ),
                ft.Container(
                    content=ft.Column([
                        ft.Text("顧客情報を入力", size=16, weight=ft.FontWeight.BOLD),
                        ft.Container(height=10),
                        name_field,
                        ft.Container(height=10),
                        formal_name_field,
                        ft.Container(height=10),
                        address_field,
                        ft.Container(height=10),
                        phone_field,
                        ft.Container(height=20),
                        ft.Row([
                            ft.Button("保存", on_click=save_customer, bgcolor=ft.Colors.BLUE_GREY_800, color=ft.Colors.WHITE),
                            ft.Button("キャンセル", on_click=cancel),
                        ], spacing=10),
                    ]),
                    padding=ft.padding.all(20),
                    expand=True,
                ),
            ]),
            expand=True,
        )

    def open_customer_picker(self, e=None):
        """顧客選択を開く（画面内遷移）"""
        logging.info("顧客選択画面へ遷移")
        self.is_customer_picker_open = True
        self.update_main_content()
    
    def on_customer_selected(self, customer: Customer):
        """顧客選択時の処理"""
        self.selected_customer = customer
        logging.info(f"顧客を選択: {customer.formal_name}")
        
        # 編集中の伝票があれば顧客を設定
        if self.editing_invoice:
            self.editing_invoice.customer = customer
            logging.info(f"編集中伝票に顧客を設定: {customer.formal_name}")
        
        # 顧客選択画面を閉じて元の画面に戻る
        self.is_customer_picker_open = False
        self.customer_search_query = ""
        self.update_main_content()
    
    def submit_invoice_for_tax(self, invoice_uuid: str) -> bool:
        """税務署提出済みフラグを設定"""
        success = self.app_service.invoice.submit_to_tax_authority(invoice_uuid)
        if success:
            self.invoices = self.app_service.invoice.get_recent_invoices(20)
            self.update_main_content()
            logging.info(f"税務署提出済み: {invoice_uuid}")
        else:
            logging.error(f"税務署提出失敗: {invoice_uuid}")
        return success
    def on_customer_deleted(self, customer: Customer):
        """顧客削除時の処理"""
        self.app_service.customer.delete_customer(customer.id)
        self.customers = self.app_service.customer.get_all_customers()
        logging.info(f"顧客を削除: {customer.formal_name}")
        # モーダルを再表示してリストを更新
        if self.customer_picker and self.customer_picker.is_open:
            self.customer_picker.update_customer_list(self.customers)
    
    def on_amount_change(self, e):
        """金額変更時の処理"""
        self.amount_value = e.control.value
        logging.info(f"金額を変更: {self.amount_value}")
    
    def on_document_type_change(self, index):
        """帳票種類変更"""
        document_types = list(DocumentType)
        selected_type = document_types[index]
        logging.info(f"帳票種類を変更: {selected_type.value}")
        # TODO: 選択された種類を保存
    
    def select_document_type(self, doc_type: str):
        """帳票種類選択"""
        # DocumentTypeから対応するenumを見つける
        for dt in DocumentType:
            if dt.value == doc_type:
                self.selected_document_type = dt
                logging.info(f"帳票種類を選択: {doc_type}")
                self.update_main_content()
                break
    
    def create_slip(self, e=None):
        """伝票作成 - サービス層を使用"""
        if not self.selected_customer:
            logging.warning("顧客が選択されていません")
            return
        
        try:
            amount = int(self.amount_value) if self.amount_value else 250000
        except ValueError:
            amount = 250000
        
        logging.info(f"伝票を作成: {self.selected_document_type.value}, {self.selected_customer.formal_name}, ¥{amount:,}")
        
        # サービス層経由で伝票作成
        invoice = self.app_service.invoice.create_invoice(
            customer=self.selected_customer,
            document_type=self.selected_document_type,
            amount=amount,
            notes=""
        )
        
        if invoice:
            if invoice.file_path:
                self.app_service.invoice.delete_pdf_file(invoice.file_path)
                invoice.file_path = None
            logging.info(f"伝票作成成功: {invoice.invoice_number}")
            # リストを更新
            self.invoices = self.app_service.invoice.get_recent_invoices(20)
            # 発行履歴タブに切り替え
            self.on_tab_change(1)
        else:
            logging.error("伝票作成失敗")
    
    def load_slips(self) -> List[Invoice]:
        """伝票データ読み込み - サービス層経由"""
        return self.app_service.invoice.get_recent_invoices(20)

def main(page: ft.Page):
    """メイン関数"""
    app = FlutterStyleDashboard(page)
    page.update()

if __name__ == "__main__":
    ft.app(target=main)
