"""
階層構造商品マスタコンポーネント
入れ子構造とPDF巨大カッコ表示に対応
"""

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

class ProductNode:
    """商品ノードクラス"""
    
    def __init__(self, id: int = None, name: str = "", parent_id: int = None, 
                 level: int = 0, is_category: bool = True, price: float = 0.0, 
                 stock: int = 0, description: str = ""):
        self.id = id
        self.name = name
        self.parent_id = parent_id
        self.level = level
        self.is_category = is_category
        self.price = price
        self.stock = stock
        self.description = description
        self.children: List['ProductNode'] = []
        self.expanded = True
    
    def add_child(self, child: 'ProductNode'):
        """子ノードを追加"""
        child.parent_id = self.id
        child.level = self.level + 1
        self.children.append(child)
    
    def remove_child(self, child_id: int):
        """子ノードを削除"""
        self.children = [child for child in self.children if child.id != child_id]
    
    def to_dict(self) -> Dict:
        """辞書に変換"""
        return {
            'id': self.id,
            'name': self.name,
            'parent_id': self.parent_id,
            'level': self.level,
            'is_category': self.is_category,
            'price': self.price,
            'stock': self.stock,
            'description': self.description,
            'expanded': self.expanded,
            'children': [child.to_dict() for child in self.children]
        }
    
    @classmethod
    def from_dict(cls, data: Dict) -> 'ProductNode':
        """辞書から作成"""
        node = cls(
            id=data.get('id'),
            name=data.get('name', ''),
            parent_id=data.get('parent_id'),
            level=data.get('level', 0),
            is_category=data.get('is_category', True),
            price=data.get('price', 0.0),
            stock=data.get('stock', 0),
            description=data.get('description', '')
        )
        node.expanded = data.get('expanded', True)
        
        for child_data in data.get('children', []):
            child = cls.from_dict(child_data)
            node.add_child(child)
        
        return node

class HierarchicalProductMaster:
    """階層構造商品マスタエディタ"""
    
    def __init__(self, page: ft.Page):
        self.page = page
        self.root_nodes: List[ProductNode] = []
        self.selected_node: Optional[ProductNode] = None
        self.next_id = 1
        
        # UIコンポーネント
        self.tree_view = ft.Column([], expand=True, spacing=2)
        self.preview_area = ft.Column([], expand=True, spacing=5)
        
        # 入力フィールド
        self.name_field = ft.TextField(
            label="商品名/カテゴリ名",
            width=300,
            autofocus=True
        )
        self.price_field = ft.TextField(
            label="価格",
            width=150,
            value="0"
        )
        self.stock_field = ft.TextField(
            label="在庫数",
            width=150,
            value="0"
        )
        self.description_field = ft.TextField(
            label="説明",
            width=400,
            multiline=True,
            height=80
        )
        self.is_category_checkbox = ft.Checkbox(
            label="カテゴリとして扱う",
            value=True
        )
        
        # ボタン
        self.add_btn = ft.Button(
            "追加",
            on_click=self.add_node,
            bgcolor=ft.Colors.GREEN,
            color=ft.Colors.WHITE
        )
        self.update_btn = ft.Button(
            "更新",
            on_click=self.update_node,
            bgcolor=ft.Colors.BLUE,
            color=ft.Colors.WHITE
        )
        self.delete_btn = ft.Button(
            "削除",
            on_click=self.delete_node,
            bgcolor=ft.Colors.RED,
            color=ft.Colors.WHITE
        )
        self.preview_btn = ft.Button(
            "PDFプレビュー",
            on_click=self.show_pdf_preview,
            bgcolor=ft.Colors.ORANGE,
            color=ft.Colors.WHITE
        )
        
        # データベース初期化
        self._init_database()
        
        # サンプルデータ作成
        self._create_sample_data()
    
    def _init_database(self):
        """データベース初期化"""
        try:
            conn = sqlite3.connect('sales.db')
            cursor = conn.cursor()
            
            # 階層商品マスタテーブル作成
            cursor.execute('''
                CREATE TABLE IF NOT EXISTS hierarchical_products (
                    id INTEGER PRIMARY KEY AUTOINCREMENT,
                    name TEXT NOT NULL,
                    parent_id INTEGER,
                    level INTEGER DEFAULT 0,
                    is_category BOOLEAN DEFAULT 1,
                    price REAL DEFAULT 0.0,
                    stock INTEGER DEFAULT 0,
                    description TEXT,
                    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                    FOREIGN KEY (parent_id) REFERENCES hierarchical_products (id)
                )
            ''')
            
            conn.commit()
            conn.close()
            
        except Exception as e:
            print(f"データベース初期化エラー: {e}")
    
    def _create_sample_data(self):
        """サンプルデータ作成"""
        try:
            conn = sqlite3.connect('sales.db')
            cursor = conn.cursor()
            
            # 既存データチェック
            cursor.execute("SELECT COUNT(*) FROM hierarchical_products")
            if cursor.fetchone()[0] > 0:
                conn.close()
                return
            
            print("サンプルデータを作成中...")
            
            # 食料品カテゴリ
            cursor.execute('''
                INSERT INTO hierarchical_products (name, parent_id, level, is_category)
                VALUES (?, ?, ?, ?)
            ''', ("食料品", None, 0, True))
            
            food_id = cursor.lastrowid
            
            # 生鮮食品サブカテゴリ
            cursor.execute('''
                INSERT INTO hierarchical_products (name, parent_id, level, is_category)
                VALUES (?, ?, ?, ?)
            ''', ("生鮮食品", food_id, 1, True))
            
            fresh_id = cursor.lastrowid
            
            # 野菜カテゴリ
            cursor.execute('''
                INSERT INTO hierarchical_products (name, parent_id, level, is_category)
                VALUES (?, ?, ?, ?)
            ''', ("野菜", fresh_id, 2, True))
            
            veg_id = cursor.lastrowid
            
            # 具体的な野菜商品
            vegetables = [
                ("キャベツ", veg_id, 3, False, 198.0, 50, "新鮮なキャベツ"),
                ("人参", veg_id, 3, False, 128.0, 80, "甘い人参"),
                ("じゃがいも", veg_id, 3, False, 98.0, 100, "ホクホクのじゃがいも"),
                ("玉ねぎ", veg_id, 3, False, 88.0, 120, "辛みの少ない玉ねぎ")
            ]
            
            for veg in vegetables:
                cursor.execute('''
                    INSERT INTO hierarchical_products 
                    (name, parent_id, level, is_category, price, stock, description)
                    VALUES (?, ?, ?, ?, ?, ?, ?)
                ''', veg)
            
            # 果物カテゴリ
            cursor.execute('''
                INSERT INTO hierarchical_products (name, parent_id, level, is_category)
                VALUES (?, ?, ?, ?)
            ''', ("果物", fresh_id, 2, True))
            
            fruit_id = cursor.lastrowid
            
            # 具体的な果物商品
            fruits = [
                ("りんご", fruit_id, 3, False, 158.0, 60, "シャリシャリのりんご"),
                ("バナナ", fruit_id, 3, False, 198.0, 40, "甘いバナナ"),
                ("みかん", fruit_id, 3, False, 298.0, 30, "みかん1箱")
            ]
            
            for fruit in fruits:
                cursor.execute('''
                    INSERT INTO hierarchical_products 
                    (name, parent_id, level, is_category, price, stock, description)
                    VALUES (?, ?, ?, ?, ?, ?, ?)
                ''', fruit)
            
            # 加工食品サブカテゴリ
            cursor.execute('''
                INSERT INTO hierarchical_products (name, parent_id, level, is_category)
                VALUES (?, ?, ?, ?)
            ''', ("加工食品", food_id, 1, True))
            
            processed_id = cursor.lastrowid
            
            # 缶詰カテゴリ
            cursor.execute('''
                INSERT INTO hierarchical_products (name, parent_id, level, is_category)
                VALUES (?, ?, ?, ?)
            ''', ("缶詰", processed_id, 2, True))
            
            can_id = cursor.lastrowid
            
            # 具体的な缶詰商品
            cans = [
                ("ツナ缶", can_id, 3, False, 128.0, 100, "水煮ツナ缶"),
                ("コーン缶", can_id, 3, False, 98.0, 80, "スイートコーン缶"),
                ("ミックスビーンズ", can_id, 3, False, 158.0, 60, "ミックスビーンズ缶")
            ]
            
            for can in cans:
                cursor.execute('''
                    INSERT INTO hierarchical_products 
                    (name, parent_id, level, is_category, price, stock, description)
                    VALUES (?, ?, ?, ?, ?, ?, ?)
                ''', can)
            
            # 日用品カテゴリ
            cursor.execute('''
                INSERT INTO hierarchical_products (name, parent_id, level, is_category)
                VALUES (?, ?, ?, ?)
            ''', ("日用品", None, 0, True))
            
            daily_id = cursor.lastrowid
            
            # 衛生用品サブカテゴリ
            cursor.execute('''
                INSERT INTO hierarchical_products (name, parent_id, level, is_category)
                VALUES (?, ?, ?, ?)
            ''', ("衛生用品", daily_id, 1, True))
            
            hygiene_id = cursor.lastrowid
            
            # 具体的な衛生用品商品
            hygiene_items = [
                ("ティッシュペーパー", hygiene_id, 2, False, 198.0, 200, "柔らかいティッシュ"),
                ("トイレットペーパー", hygiene_id, 2, False, 298.0, 100, "ダブルロール12個入"),
                ("ハンドソープ", hygiene_id, 2, False, 398.0, 50, "除菌ハンドソープ")
            ]
            
            for item in hygiene_items:
                cursor.execute('''
                    INSERT INTO hierarchical_products 
                    (name, parent_id, level, is_category, price, stock, description)
                    VALUES (?, ?, ?, ?, ?, ?, ?)
                ''', item)
            
            conn.commit()
            conn.close()
            print("サンプルデータ作成完了")
            
        except Exception as e:
            print(f"サンプルデータ作成エラー: {e}")
    
    def load_data(self):
        """データベースからデータを読み込み"""
        try:
            conn = sqlite3.connect('sales.db')
            cursor = conn.cursor()
            
            cursor.execute('''
                SELECT id, name, parent_id, level, is_category, price, stock, description
                FROM hierarchical_products
                ORDER BY level, parent_id, name
            ''')
            
            rows = cursor.fetchall()
            conn.close()
            
            # ノードマップ作成
            node_map = {}
            self.root_nodes = []
            
            for row in rows:
                node = ProductNode(
                    id=row[0],
                    name=row[1],
                    parent_id=row[2],
                    level=row[3],
                    is_category=bool(row[4]),
                    price=row[5],
                    stock=row[6],
                    description=row[7]
                )
                node_map[node.id] = node
            
            # 階層構造構築
            for node in node_map.values():
                if node.parent_id is None:
                    self.root_nodes.append(node)
                else:
                    parent = node_map.get(node.parent_id)
                    if parent:
                        parent.add_child(node)
            
            # 次のIDを設定
            if rows:
                self.next_id = max(row[0] for row in rows) + 1
            
            self.update_tree_view()
            
        except Exception as e:
            print(f"データ読み込みエラー: {e}")
    
    def save_data(self):
        """データベースに保存"""
        try:
            conn = sqlite3.connect('sales.db')
            cursor = conn.cursor()
            
            # 既存データ削除
            cursor.execute("DELETE FROM hierarchical_products")
            
            # 再帰的に保存
            def save_node(node: ProductNode):
                cursor.execute('''
                    INSERT INTO hierarchical_products 
                    (id, name, parent_id, level, is_category, price, stock, description)
                    VALUES (?, ?, ?, ?, ?, ?, ?, ?)
                ''', (
                    node.id, node.name, node.parent_id, node.level,
                    node.is_category, node.price, node.stock, node.description
                ))
                
                for child in node.children:
                    save_node(child)
            
            for root in self.root_nodes:
                save_node(root)
            
            conn.commit()
            conn.close()
            
        except Exception as e:
            print(f"データ保存エラー: {e}")
    
    def update_tree_view(self):
        """ツリービュー更新"""
        self.tree_view.controls.clear()
        
        for root in self.root_nodes:
            self.tree_view.controls.append(self._create_tree_node(root))
        
        self.tree_view.update()
    
    def _create_tree_node(self, node: ProductNode) -> ft.Container:
        """ツリーノード作成"""
        indent = "  " * node.level
        
        # アイコン
        if node.is_category:
            if node.expanded and node.children:
                icon = ft.Icons.FOLDER_OPEN
            elif node.children:
                icon = ft.Icons.FOLDER
            else:
                icon = ft.Icons.FOLDER_OUTLINE
        else:
            icon = ft.Icons.SHOPPING_CART
        
        # ノードコンテナ
        node_container = ft.Container(
            content=ft.Row([
                # 展開/折りたたみボタン
                ft.IconButton(
                    icon=ft.Icons.EXPAND_MORE if node.expanded else ft.Icons.CHEVRON_RIGHT,
                    on_click=lambda _, n=node: self.toggle_node(n),
                    visible=len(node.children) > 0,
                    width=30,
                    height=30
                ),
                # アイコン
                ft.Icon(
                    icon,
                    color=ft.Colors.ORANGE if node.is_category else ft.Colors.BLUE,
                    size=20
                ),
                # 名前
                ft.Text(
                    f"{indent}{node.name}",
                    size=14,
                    weight=ft.FontWeight.BOLD if node.is_category else ft.FontWeight.NORMAL,
                    expand=True
                ),
                # 価格（商品の場合）
                ft.Text(
                    f"¥{node.price:.0f}" if not node.is_category else "",
                    size=12,
                    color=ft.Colors.GREY_600
                ),
                # 在庫（商品の場合）
                ft.Text(
                    f"在庫:{node.stock}" if not node.is_category else "",
                    size=12,
                    color=ft.Colors.GREY_600
                ),
                # 選択ボタン
                ft.IconButton(
                    icon=ft.Icons.EDIT,
                    on_click=lambda _, n=node: self.select_node(n),
                    icon_size=16,
                    tooltip="編集"
                )
            ], spacing=5),
            padding=ft.Padding.symmetric(horizontal=10, vertical=5),
            bgcolor=ft.Colors.BLUE_50 if self.selected_node == node else ft.Colors.TRANSPARENT,
            border_radius=5,
            on_click=lambda _, n=node: self.select_node(n)
        )
        
        # 子ノード
        children_container = ft.Column([], spacing=2)
        if node.expanded:
            for child in node.children:
                children_container.controls.append(self._create_tree_node(child))
        
        return ft.Column([
            node_container,
            children_container
        ], spacing=0)
    
    def toggle_node(self, node: ProductNode):
        """ノード展開/折りたたみ"""
        node.expanded = not node.expanded
        self.update_tree_view()
    
    def select_node(self, node: ProductNode):
        """ノード選択"""
        self.selected_node = node
        
        # 入力フィールドに値を設定
        self.name_field.value = node.name
        self.price_field.value = str(node.price)
        self.stock_field.value = str(node.stock)
        self.description_field.value = node.description
        self.is_category_checkbox.value = node.is_category
        
        # 価格・在庫フィールドの有効/無効
        self.price_field.disabled = node.is_category
        self.stock_field.disabled = node.is_category
        
        self.update_tree_view()
        self.page.update()
    
    def add_node(self, e=None):
        """ノード追加"""
        if not self.name_field.value:
            self.show_message("名前を入力してください", ft.Colors.RED)
            return
        
        new_node = ProductNode(
            id=self.next_id,
            name=self.name_field.value,
            parent_id=self.selected_node.id if self.selected_node else None,
            level=self.selected_node.level + 1 if self.selected_node else 0,
            is_category=self.is_category_checkbox.value,
            price=float(self.price_field.value) if not self.is_category_checkbox.value else 0.0,
            stock=int(self.stock_field.value) if not self.is_category_checkbox.value else 0,
            description=self.description_field.value
        )
        
        self.next_id += 1
        
        if self.selected_node:
            self.selected_node.add_child(new_node)
            if not self.selected_node.expanded:
                self.selected_node.expanded = True
        else:
            self.root_nodes.append(new_node)
        
        self.update_tree_view()
        self.clear_form()
        self.save_data()
        self.show_message("商品を追加しました", ft.Colors.GREEN)
    
    def update_node(self, e=None):
        """ノード更新"""
        if not self.selected_node or not self.name_field.value:
            self.show_message("更新対象を選択してください", ft.Colors.RED)
            return
        
        self.selected_node.name = self.name_field.value
        self.selected_node.is_category = self.is_category_checkbox.value
        
        if not self.is_category_checkbox.value:
            self.selected_node.price = float(self.price_field.value)
            self.selected_node.stock = int(self.stock_field.value)
        else:
            self.selected_node.price = 0.0
            self.selected_node.stock = 0
        
        self.selected_node.description = self.description_field.value
        
        self.update_tree_view()
        self.save_data()
        self.show_message("商品を更新しました", ft.Colors.GREEN)
    
    def delete_node(self, e=None):
        """ノード削除"""
        if not self.selected_node:
            self.show_message("削除対象を選択してください", ft.Colors.RED)
            return
        
        # 子ノードも削除
        def remove_from_parent(node: ProductNode, target: ProductNode):
            if target in node.children:
                node.remove_child(target.id)
                return True
            for child in node.children:
                if remove_from_parent(child, target):
                    return True
            return False
        
        # 親を探して削除
        removed = False
        for root in self.root_nodes:
            if root == self.selected_node:
                self.root_nodes.remove(root)
                removed = True
                break
            if remove_from_parent(root, self.selected_node):
                removed = True
                break
        
        if removed:
            self.selected_node = None
            self.update_tree_view()
            self.clear_form()
            self.save_data()
            self.show_message("商品を削除しました", ft.Colors.GREEN)
    
    def clear_form(self):
        """フォームクリア"""
        self.name_field.value = ""
        self.price_field.value = "0"
        self.stock_field.value = "0"
        self.description_field.value = ""
        self.is_category_checkbox.value = True
        self.price_field.disabled = True
        self.stock_field.disabled = True
    
    def show_pdf_preview(self, e=None):
        """PDFプレビュー表示"""
        self.preview_area.controls.clear()
        
        # キャラクターベースの階層表示
        preview_text = self._generate_character_preview()
        
        self.preview_area.controls = [
            ft.Container(
                content=ft.Column([
                    ft.Text(
                        "商品マスタ一覧 - PDFプレビュー",
                        size=20,
                        weight=ft.FontWeight.BOLD,
                        text_align=ft.TextAlign.CENTER
                    ),
                    ft.Divider(),
                    ft.Container(
                        content=ft.Text(
                            preview_text,
                            size=12,
                            font_family="Courier New"
                        ),
                        padding=20,
                        bgcolor=ft.Colors.WHITE,
                        border=ft.Border.all(1, ft.Colors.GREY_300),
                        border_radius=5
                    )
                ]),
                padding=20,
                bgcolor=ft.Colors.GREY_50,
                border_radius=10
            )
        ]
        
        self.preview_area.update()
    
    def _generate_character_preview(self) -> str:
        """キャラクターベースのプレビュー生成"""
        lines = []
        lines.append("┌" + "─" * 60 + "┐")
        lines.append("│" + "商品マスタ一覧".center(58, " ") + "│")
        lines.append("├" + "─" * 60 + "┤")
        
        def add_node_lines(node: ProductNode, prefix: str = "", is_last: bool = True):
            # 現在のノード
            connector = "└──" if is_last else "├──"
            
            if node.is_category:
                line = f"{prefix}{connector}【{node.name}】"
            else:
                line = f"{prefix}{connector}・{node.name} (¥{node.price:.0f}, 在庫:{node.stock})"
            
            lines.append("│" + line.ljust(58, " ") + "│")
            
            # 子ノード
            if node.children:
                child_prefix = prefix + ("    " if is_last else "│   ")
                for i, child in enumerate(node.children):
                    is_last_child = (i == len(node.children) - 1)
                    add_node_lines(child, child_prefix, is_last_child)
        
        # 全ルートノードを追加
        for i, root in enumerate(self.root_nodes):
            is_last_root = (i == len(self.root_nodes) - 1)
            add_node_lines(root, "", is_last_root)
        
        lines.append("└" + "─" * 60 + "┘")
        
        return "\n".join(lines)
    
    def show_message(self, message: str, color: ft.Colors):
        """メッセージ表示"""
        self.page.snack_bar = ft.SnackBar(
            content=ft.Text(message),
            bgcolor=color
        )
        self.page.snack_bar.open = True
        self.page.update()
    
    def build(self) -> ft.Row:
        """UI構築"""
        # 左側：ツリービュー
        left_panel = ft.Container(
            content=ft.Column([
                ft.Text(
                    "商品階層構造",
                    size=18,
                    weight=ft.FontWeight.BOLD
                ),
                ft.Divider(),
                ft.Container(
                    content=self.tree_view,
                    border=ft.Border.all(1, ft.Colors.GREY_300),
                    border_radius=5,
                    padding=10,
                    height=400
                )
            ]),
            width=400,
            padding=10
        )
        
        # 中央：入力フォーム
        center_panel = ft.Container(
            content=ft.Column([
                ft.Text(
                    "商品情報編集",
                    size=18,
                    weight=ft.FontWeight.BOLD
                ),
                ft.Divider(),
                self.name_field,
                ft.Row([
                    self.price_field,
                    self.stock_field
                ], spacing=10),
                self.description_field,
                self.is_category_checkbox,
                ft.Divider(),
                ft.Row([
                    self.add_btn,
                    self.update_btn,
                    self.delete_btn
                ], spacing=10)
            ]),
            width=400,
            padding=10
        )
        
        # 右側：プレビュー
        right_panel = ft.Container(
            content=ft.Column([
                ft.Row([
                    ft.Text(
                        "PDFプレビュー",
                        size=18,
                        weight=ft.FontWeight.BOLD
                    ),
                    self.preview_btn
                ], alignment=ft.MainAxisAlignment.SPACE_BETWEEN),
                ft.Divider(),
                ft.Container(
                    content=self.preview_area,
                    border=ft.Border.all(1, ft.Colors.GREY_300),
                    border_radius=5,
                    padding=10,
                    height=400
                )
            ]),
            width=500,
            padding=10
        )
        
        return ft.Row([
            left_panel,
            ft.VerticalDivider(width=1),
            center_panel,
            ft.VerticalDivider(width=1),
            right_panel
        ], expand=True)

def create_hierarchical_product_master(page: ft.Page) -> HierarchicalProductMaster:
    """階層商品マスタ作成"""
    master = HierarchicalProductMaster(page)
    master.load_data()
    return master
