"""
伝票入力フレームワーク
表示形式を動的に切り替える伝票入力システム
"""

import flet as ft
import sqlite3
import logging
import json
from datetime import datetime
from typing import List, Dict, Optional, Any

class DisplayTheme:
    """表示形式テーマ"""
    
    def __init__(self, name: str, title: str, format_type: str, config: Dict):
        self.name = name
        self.title = title
        self.format_type = format_type  # 'table', 'card', 'list', 'custom'
        self.config = config

class SlipEntryRenderer:
    """伝票入力レンダラ"""
    
    def __init__(self, page: ft.Page):
        self.page = page
        self.current_theme = None
        self.items = []
        
    def set_theme(self, theme: DisplayTheme):
        """テーマを設定"""
        self.current_theme = theme
        
    def render_table_format(self, items: List[Dict]) -> ft.Column:
        """表形式でレンダリング"""
        if not self.current_theme or self.current_theme.format_type != 'table':
            return ft.Column([ft.Text("テーマが設定されていません")])
        
        config = self.current_theme.config
        columns = config.get('columns', [])
        
        # ヘッダー行
        header_row = ft.Row(
            [ft.Text(col.get('label', ''), weight=ft.FontWeight.BOLD, width=col.get('width', 100)) 
             for col in columns],
            spacing=5
        )
        
        # データ行
        data_rows = []
        for item in items:
            row_controls = []
            for col in columns:
                field_name = col.get('field', '')
                value = item.get(field_name, '')
                align = col.get('align', 'left')
                
                text_control = ft.Text(
                    value=str(value),
                    width=col.get('width', 100),
                    text_align=ft.TextAlign.LEFT if align == 'left' else ft.TextAlign.RIGHT
                )
                row_controls.append(text_control)
            
            data_rows.append(ft.Row(row_controls, spacing=5))
        
        return ft.Column([header_row] + data_rows, spacing=5)
    
    def render_card_format(self, items: List[Dict]) -> ft.Column:
        """カード形式でレンダリング"""
        if not self.current_theme or self.current_theme.format_type != 'card':
            return ft.Column([ft.Text("テーマが設定されていません")])
        
        config = self.current_theme.config
        card_width = config.get('card_width', 300)
        card_height = config.get('card_height', 120)
        
        cards = []
        for i, item in enumerate(items):
            card_content = []
            
            # カード内のフィールド
            for field_name, value in item.items():
                if field_name != 'id':
                    card_content.append(ft.Text(f"{field_name}: {value}", size=12))
            
            card = ft.Card(
                content=ft.Container(
                    content=ft.Column(card_content),
                    padding=10,
                    width=card_width,
                    height=card_height
                ),
                margin=ft.margin.only(bottom=5)
            )
            cards.append(card)
        
        return ft.Column(cards, scroll=ft.ScrollMode.AUTO)
    
    def render_list_format(self, items: List[Dict]) -> ft.Column:
        """リスト形式でレンダリング"""
        if not self.current_theme or self.current_theme.format_type != 'list':
            return ft.Column([ft.Text("テーマが設定されていません")])
        
        config = self.current_theme.config
        item_height = config.get('item_height', 60)
        show_dividers = config.get('show_dividers', True)
        compact_mode = config.get('compact_mode', False)
        
        list_items = []
        for item in items:
            item_content = []
            
            for field_name, value in item.items():
                if field_name != 'id':
                    item_content.append(ft.Text(f"{field_name}: {value}", size=12))
            
            list_item = ft.Container(
                content=ft.Column(item_content),
                padding=10,
                height=item_height if not compact_mode else None,
                bgcolor=ft.Colors.GREY_50 if not compact_mode else None
            )
            
            list_items.append(list_item)
            
            if show_dividers:
                list_items.append(ft.Divider(height=1))
        
        return ft.Column(list_items, scroll=ft.ScrollMode.AUTO)
    
    def render_custom_format(self, items: List[Dict]) -> ft.Column:
        """カスタム形式でレンダリング"""
        if not self.current_theme or self.current_theme.format_type != 'custom':
            return ft.Column([ft.Text("テーマが設定されていません")])
        
        config = self.current_theme.config
        
        # カスタムレンダリングロジック
        custom_items = []
        for item in items:
            custom_content = []
            
            # ユーザー定義のレンダリング
            for field_name, value in item.items():
                if field_name != 'id':
                    field_config = config.get('fields', {}).get(field_name, {})
                    field_type = field_config.get('type', 'text')
                    
                    if field_type == 'text':
                        custom_content.append(ft.Text(f"{field_name}: {value}", size=12))
                    elif field_type == 'badge':
                        custom_content.append(
                            ft.Container(
                                content=ft.Text(value, size=10),
                                bgcolor=ft.Colors.BLUE,
                                padding=ft.padding.symmetric(5, 2),
                                border_radius=5
                            )
                        )
                    elif field_type == 'progress':
                        custom_content.append(
                            ft.ProgressBar(
                                value=float(value) if value else 0,
                                width=200
                            )
                        )
            
            custom_items.append(ft.Container(
                content=ft.Column(custom_content),
                padding=10,
                border=ft.border.all(1, ft.Colors.GREY_300),
                border_radius=5,
                margin=ft.margin.only(bottom=10)
            ))
        
        return ft.Column(custom_items, scroll=ft.ScrollMode.AUTO)

class SlipEntryFramework:
    """伝票入力フレームワーク"""
    
    def __init__(self, page: ft.Page):
        self.page = page
        self.renderer = SlipEntryRenderer(page)
        self.themes = {}
        self.current_theme_name = None
        self.items = []
        
        # UI部品
        self.title = ft.Text("伝票入力フレームワーク", size=24, weight=ft.FontWeight.BOLD, color=ft.Colors.BLUE_900)
        
        # テーマ選択
        self.theme_dropdown = ft.Dropdown(
            label="表示形式",
            options=[],
            on_change=self.change_theme
        )
        
        # 入力フォーム
        self.form_fields = ft.Column([], spacing=10)
        
        # 表示エリア
        self.display_area = ft.Column([], scroll=ft.ScrollMode.AUTO, height=300)
        
        # ボタン群
        self.add_item_btn = ft.Button("明細追加", on_click=self.add_item, bgcolor=ft.Colors.BLUE, color=ft.Colors.WHITE)
        self.save_btn = ft.Button("保存", on_click=self.save_slip, bgcolor=ft.Colors.GREEN, color=ft.Colors.WHITE)
        self.clear_btn = ft.Button("クリア", on_click=self.clear_form, bgcolor=ft.Colors.ORANGE, color=ft.Colors.WHITE)
        
        # 操作説明
        self.instructions = ft.Text(
            "操作方法: 表示形式を選択して伝票を入力",
            size=12,
            color=ft.Colors.GREY_600
        )
        
        # 初期化
        self._init_themes()
        self._build_form()
    
    def _init_themes(self):
        """テーマを初期化"""
        try:
            conn = sqlite3.connect('sales.db')
            cursor = conn.cursor()
            
            # テーマテーブル作成
            cursor.execute('''
                CREATE TABLE IF NOT EXISTS display_themes (
                    id INTEGER PRIMARY KEY AUTOINCREMENT,
                    name TEXT NOT NULL UNIQUE,
                    title TEXT NOT NULL,
                    format_type TEXT NOT NULL,
                    layout_config TEXT NOT NULL,
                    is_active BOOLEAN DEFAULT 1,
                    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
                )
            ''')
            
            # デフォルトテーマを挿入
            default_themes = [
                {
                    'name': 'table_standard',
                    'title': '表形式（標準）',
                    'format_type': 'table',
                    'layout_config': json.dumps({
                        'columns': [
                            {'field': 'item_name', 'label': '商品名', 'width': 200},
                            {'field': 'quantity', 'label': '数量', 'width': 100, 'align': 'right'},
                            {'field': 'unit_price', 'label': '単価', 'width': 120, 'align': 'right'},
                            {'field': 'amount', 'label': '金額', 'width': 120, 'align': 'right'}
                        ]
                    })
                },
                {
                    'name': 'card_standard',
                    'title': 'カード形式（標準）',
                    'format_type': 'card',
                    'layout_config': json.dumps({
                        'card_width': 350,
                        'card_height': 100,
                        'fields_layout': 'vertical'
                    })
                },
                {
                    'name': 'list_standard',
                    'title': 'リスト形式（標準）',
                    'format_type': 'list',
                    'layout_config': json.dumps({
                        'item_height': 80,
                        'show_dividers': True,
                        'compact_mode': False
                    })
                }
            ]
            
            # デフォルトテーマがなければ挿入
            cursor.execute("SELECT COUNT(*) FROM display_themes")
            if cursor.fetchone()[0] == 0:
                for theme in default_themes:
                    cursor.execute('''
                        INSERT INTO display_themes (name, title, format_type, layout_config)
                        VALUES (?, ?, ?, ?)
                    ''', (theme['name'], theme['title'], theme['format_type'], theme['layout_config']))
                conn.commit()
            
            # テーマを読み込み
            cursor.execute("SELECT * FROM display_themes WHERE is_active = 1 ORDER BY id")
            themes_data = cursor.fetchall()
            
            for theme_data in themes_data:
                theme_id, name, title, format_type, layout_config, is_active, created_at = theme_data
                self.themes[name] = DisplayTheme(name, title, format_type, json.loads(layout_config))
            
            conn.close()
            
            # ドロップダウンを更新
            self.theme_dropdown.options = [
                ft.dropdown.Option(theme.title, name)
                for name, theme in self.themes.items()
            ]
            
            if self.themes:
                first_theme = list(self.themes.keys())[0]
                self.theme_dropdown.value = first_theme
                self.current_theme_name = first_theme
                self.current_theme = self.themes[first_theme]
                self.renderer.set_theme(self.current_theme)
            
            self.page.update()
            
        except Exception as e:
            logging.error(f"テーマ初期化エラー: {e}")
    
    def change_theme(self, e):
        """テーマを変更"""
        theme_name = e.control.value
        if theme_name in self.themes:
            self.current_theme_name = theme_name
            self.current_theme = self.themes[theme_name]
            self.renderer.set_theme(self.current_theme)
            self._update_display()
            logging.info(f"テーマ変更: {theme_name}")
    
    def _build_form(self):
        """入力フォームを構築"""
        self.form_fields.controls.clear()
        
        # 基本フィールド
        fields = [
            {'name': 'item_name', 'label': '商品名', 'width': 200},
            {'name': 'quantity', 'label': '数量', 'width': 100},
            {'name': 'unit_price', 'label': '単価', 'width': 120},
            {'name': 'amount', 'label': '金額', 'width': 120}
        ]
        
        for field in fields:
            field_control = ft.TextField(
                label=field['label'],
                value='',
                width=field['width']
            )
            self.form_fields.controls.append(field_control)
        
        self.page.update()
    
    def _update_display(self):
        """表示エリアを更新"""
        self.display_area.controls.clear()
        
        if self.items:
            if self.current_theme.format_type == 'table':
                self.display_area.controls.append(self.renderer.render_table_format(self.items))
            elif self.current_theme.format_type == 'card':
                self.display_area.controls.append(self.renderer.render_card_format(self.items))
            elif self.current_theme.format_type == 'list':
                self.display_area.controls.append(self.renderer.render_list_format(self.items))
            elif self.current_theme.format_type == 'custom':
                self.display_area.controls.append(self.renderer.render_custom_format(self.items))
        
        self.page.update()
    
    def add_item(self, e):
        """明細を追加"""
        # フォームデータを収集
        form_data = {}
        for i, field in enumerate(self.form_fields.controls):
            field_name = ['item_name', 'quantity', 'unit_price', 'amount'][i]
            form_data[field_name] = field.control.value
        
        # 金額を計算
        try:
            quantity = float(form_data.get('quantity', 0))
            unit_price = float(form_data.get('unit_price', 0))
            amount = quantity * unit_price
            form_data['amount'] = str(amount)
        except:
            form_data['amount'] = '0'
        
        # リストに追加
        self.items.append(form_data)
        
        # 表示を更新
        self._update_display()
        
        # フォームをクリア
        self.clear_form(None)
        
        logging.info(f"明細追加: {form_data}")
    
    def clear_form(self, e):
        """フォームをクリア"""
        for field_control in self.form_fields.controls:
            field_control.value = ''
        
        self.page.update()
        logging.info("フォームをクリア")
    
    def save_slip(self, e):
        """伝票を保存"""
        if not self.items:
            return
        
        try:
            # データベースに保存
            conn = sqlite3.connect('sales.db')
            cursor = conn.cursor()
            
            # 伝票テーブル作成
            cursor.execute('''
                CREATE TABLE IF NOT EXISTS slips (
                    id INTEGER PRIMARY KEY AUTOINCREMENT,
                    title TEXT NOT NULL,
                    theme_name TEXT NOT NULL,
                    items_data TEXT NOT NULL,
                    total_amount REAL NOT NULL,
                    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
                )
            ''')
            
            # 合計金額を計算
            total_amount = sum(float(item.get('amount', 0)) for item in self.items)
            
            # 伝票を保存
            cursor.execute('''
                INSERT INTO slips (title, theme_name, items_data, total_amount)
                VALUES (?, ?, ?, ?)
            ''', (
                f"伝票_{datetime.now().strftime('%Y%m%d_%H%M%S')}",
                self.current_theme_name,
                json.dumps(self.items),
                total_amount
            ))
            
            conn.commit()
            conn.close()
            
            # 成功メッセージ
            self._show_snackbar("伝票を保存しました", ft.Colors.GREEN)
            logging.info(f"伝票保存: {len(self.items)}件, 合計: {total_amount}")
            
            # クリア
            self.items.clear()
            self._update_display()
            
        except Exception as ex:
            logging.error(f"伝票保存エラー: {ex}")
            self._show_snackbar("保存エラー", ft.Colors.RED)
    
    def _show_snackbar(self, message: str, color: ft.Colors):
        """SnackBarを表示"""
        try:
            self.page.snack_bar = ft.SnackBar(
                content=ft.Text(message),
                bgcolor=color
            )
            self.page.snack_bar.open = True
            self.page.update()
        except:
            pass
    
    def build(self):
        """UIを構築して返す"""
        return ft.Column([
            ft.Row([
                self.title,
                self.theme_dropdown
            ], alignment=ft.MainAxisAlignment.SPACE_BETWEEN),
            ft.Divider(),
            ft.Text("明細入力", size=18, weight=ft.FontWeight.BOLD),
            self.form_fields,
            ft.Row([self.add_item_btn, self.save_btn, self.clear_btn], spacing=10),
            ft.Divider(),
            ft.Text("伝票プレビュー", size=18, weight=ft.FontWeight.BOLD),
            self.instructions,
            self.display_area
        ], expand=True, spacing=15)

# 使用例
def create_slip_entry_framework(page: ft.Page) -> SlipEntryFramework:
    """伝票入力フレームワークを作成"""
    return SlipEntryFramework(page)
