"""
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
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 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.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'),
                    '完了',
                    invoice.notes
                ))
            
            self.conn.commit()
        except Exception as e:
            logging.error(f"サンプルデータ作成エラー: {e}")
    
    def setup_ui(self):
        """UIセットアップ"""
        # 下部ナビゲーション（NavigationRail風）
        bottom_nav = ft.Container(
            content=ft.Row([
                ft.Container(
                    content=ft.IconButton(
                        ft.Icons.ADD_BOX,
                        selected=self.current_tab == 0,
                        on_click=lambda _: self.on_tab_change(0),
                    ),
                    ),
                    ft.Text("新規作成"),
                    ft.Container(
                        content=ft.IconButton(
                            ft.Icons.HISTORY,
                            selected=self.current_tab == 1,
                            on_click=lambda _: self.on_tab_change(1),
                        ),
                    ),
                    ft.Text("発行履歴"),
                ], alignment=ft.MainAxisAlignment.CENTER),
            padding=ft.Padding.all(10),
            bgcolor=ft.Colors.BLUE_GREY_50,
        )
        
        # メインコンテンツ
        self.main_content = ft.Column([], expand=True)
        
        # ページ構成
        self.page.add(
            ft.Column([
                self.main_content,
                bottom_nav,
            ], 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.current_tab == 0:
            if self.is_new_customer_form_open:
                self.main_content.controls.append(self.create_new_customer_screen())
            elif self.is_customer_picker_open:
                self.main_content.controls.append(self.create_customer_picker_screen())
            else:
                # 新規作成画面
                self.main_content.controls.append(self.create_slip_input_screen())
        else:
            # 発行履歴画面
            self.main_content.controls.append(self.create_slip_history_screen())
        
        self.page.update()

    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()

        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
            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(
            [
                header,
                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 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)
        
        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,
                    ]),
                    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.IconButton(
                                    ft.Icons.PERSON_SEARCH,
                                    tooltip="顧客を選択",
                                    on_click=self.open_customer_picker,
                                ),
                            ],
                            spacing=8,
                        ),
                        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=20, weight=ft.FontWeight.BOLD),
                        ft.Container(expand=True),
                        ft.IconButton(
                            ft.Icons.VERIFIED,
                            tooltip="チェーン検証",
                            icon_color=ft.Colors.BLUE_300,
                            on_click=on_verify_chain,
                        ),
                        ft.Row(
                            [
                                ft.Text("赤伝を表示", size=12, color=ft.Colors.WHITE),
                                ft.Switch(value=self.show_offsets, on_change=on_toggle_offsets),
                            ],
                            spacing=5,
                        ),
                        ft.IconButton(ft.Icons.CLEAR_ALL, icon_size=20),
                    ]),
                    padding=ft.padding.all(15),
                    bgcolor=ft.Colors.BLUE_GREY,
                ),

                # 検証結果表示（あれば）
                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,
                ),
            ]),
            expand=True,
        )
    
    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")
            status = "赤伝" if getattr(slip, "is_offset", False) else "完了"
        else:
            slip_id, slip_type, customer_name, amount, date, status, description, created_at = slip
        
        # タイプに応じたアイコンと色
        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 issue_offset(_=None):
            if not isinstance(slip, Invoice):
                return
            if getattr(slip, "is_offset", False):
                return
            offset_invoice = self.app_service.invoice.create_offset_invoice(slip.uuid)
            if offset_invoice and offset_invoice.file_path:
                self.app_service.invoice.delete_pdf_file(offset_invoice.file_path)
            # リストを更新
            self.invoices = self.app_service.invoice.get_recent_invoices(20)
            self.update_main_content()

        def regenerate_and_share(_=None):
            if not isinstance(slip, Invoice):
                return
            pdf_path = self.app_service.invoice.regenerate_pdf(slip.uuid)
            if pdf_path:
                # TODO: OSの共有ダイアログを呼ぶ（プラットフォーム依存）
                logging.info(f"PDF再生成: {pdf_path}（共有機能は未実装）")
                # 共有後に削除（今は即削除）
                self.app_service.invoice.delete_pdf_file(pdf_path)
                logging.info(f"PDF削除完了: {pdf_path}")
            else:
                logging.error("PDF再生成失敗")

        actions_row = None
        if isinstance(slip, Invoice):
            buttons = []
            if not getattr(slip, "submitted_to_tax_authority", False):
                buttons.append(
                    ft.IconButton(
                        ft.Icons.REPLAY_CIRCLE_FILLED,
                        tooltip="赤伝（相殺）を発行",
                        icon_color=ft.Colors.RED_400,
                        on_click=issue_offset,
                    )
                )
            if not getattr(slip, "submitted_to_tax_authority", False):
                buttons.append(
                    ft.IconButton(
                        ft.Icons.CHECK_CIRCLE,
                        tooltip="税務署提出済みに設定",
                        icon_color=ft.Colors.ORANGE_400,
                        on_click=lambda _: self.submit_invoice_for_tax(slip.uuid),
                    )
            )
            buttons.append(
                ft.IconButton(
                    ft.Icons.DOWNLOAD,
                    tooltip="PDF再生成→共有",
                    icon_color=ft.Colors.BLUE_400,
                    on_click=regenerate_and_share,
                )
            )
            actions_row = ft.Row(buttons, alignment=ft.MainAxisAlignment.END)

        display_amount = amount
        if isinstance(slip, Invoice) and getattr(slip, "is_offset", False):
            display_amount = -abs(amount)

        return ft.Card(
            content=ft.Container(
                content=ft.Column([
                    ft.Row([
                        ft.Container(
                            content=ft.Text(config["icon"], size=24),
                            width=40,
                            height=40,
                            bgcolor=config["color"],
                            border_radius=20,
                            alignment=ft.alignment.Alignment(0, 0),
                        ),
                        ft.Container(
                            content=ft.Column([
                                ft.Text(slip_type, size=12, weight=ft.FontWeight.BOLD),
                                ft.Text(f"{customer_name} ¥{display_amount:,.0f}", size=10),
                            ]),
                            expand=True,
                        ),
                    ]),
                    ft.Container(height=5),
                    ft.Text(f"日付: {date}", size=10, color=ft.Colors.GREY_600),
                    ft.Text(f"状態: {status}", size=10, color=ft.Colors.GREY_600),
                    actions_row if actions_row else ft.Container(height=0),
                ]),
                padding=ft.padding.all(15),
            ),
            elevation=3,
        )
    
    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_new_customer_form(self):
        """新規顧客フォームを開く（画面内遷移）"""
        self.is_new_customer_form_open = True
        self.update_main_content()

    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}")
        # UIを更新して選択された顧客を表示
        self.update_main_content()
    
    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)
