"""
伝票データモデル
Flutter参考プロジェクトの構造をFletに適用
"""

from enum import Enum
from datetime import datetime
from typing import List, Optional, Dict, Any
import json

class DocumentType(Enum):
    """帳票の種類を定義"""
    ESTIMATE = "見積書"
    DELIVERY = "納品書"
    INVOICE = "請求書"
    RECEIPT = "領収書"
    SALES = "売上伝票"
    DRAFT = "下書き"  # 下書きタイプを追加

class Product:
    """商品マスタモデル"""
    
    def __init__(self, id: Optional[int] = None, name: str = "", unit_price: int = 0, description: str = ""):
        self.id = id
        self.name = name
        self.unit_price = unit_price
        self.description = description
    
    def to_dict(self) -> Dict[str, Any]:
        """JSON変換"""
        return {
            'id': self.id,
            'name': self.name,
            'unit_price': self.unit_price,
            'description': self.description
        }
    
    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> 'Product':
        """JSONから復元"""
        return cls(
            id=data.get('id'),
            name=data.get('name', ''),
            unit_price=data.get('unit_price', 0),
            description=data.get('description', '')
        )

class InvoiceItem:
    """伝票の各明細行を表すモデル"""
    
    def __init__(self, description: str, quantity: int, unit_price: int, is_discount: bool = False, product_id: Optional[int] = None):
        self.description = description
        self.quantity = quantity
        self.unit_price = unit_price
        self.is_discount = is_discount  # 値引き項目かどうかを示すフラグ
        self.product_id = product_id  # 商品マスタID
    
    @property
    def subtotal(self) -> int:
        """小計 (数量 * 単価)"""
        return self.quantity * self.unit_price * (-1 if self.is_discount else 1)
    
    def copy_with(self, **kwargs) -> 'InvoiceItem':
        """編集用のコピーメソッド"""
        return InvoiceItem(
            description=kwargs.get('description', self.description),
            quantity=kwargs.get('quantity', self.quantity),
            unit_price=kwargs.get('unit_price', self.unit_price),
            is_discount=kwargs.get('is_discount', self.is_discount),
            product_id=kwargs.get('product_id', self.product_id)
        )
    
    def to_dict(self) -> Dict[str, Any]:
        """JSON変換"""
        return {
            'description': self.description,
            'quantity': self.quantity,
            'unit_price': self.unit_price,
            'is_discount': self.is_discount,
            'product_id': self.product_id
        }
    
    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> 'InvoiceItem':
        """JSONから復元"""
        return cls(
            description=data['description'],
            quantity=data['quantity'],
            unit_price=data['unit_price'],
            is_discount=data.get('is_discount', False),
            product_id=data.get('product_id')
        )

class Customer:
    """顧客情報モデル"""
    
    def __init__(self, id: int, name: str, formal_name: str, address: str = "", phone: str = "", email: str = ""):
        self.id = id
        self.name = name
        self.formal_name = formal_name
        self.address = address
        self.phone = phone
        self.email = email
    
    def to_dict(self) -> Dict[str, Any]:
        """JSON変換"""
        return {
            'id': self.id,
            'name': self.name,
            'formal_name': self.formal_name,
            'address': self.address,
            'phone': self.phone
        }
    
    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> 'Customer':
        """JSONから復元"""
        return cls(
            id=data['id'],
            name=data['name'],
            formal_name=data['formal_name'],
            address=data.get('address', ''),
            phone=data.get('phone', ''),
            email=data.get('email', '')
        )

class Invoice:
    """帳票全体を管理するモデル (見積・納品・請求・領収に対応)"""
    
    def __init__(self, 
                 customer: Customer,
                 date: datetime,
                 items: List[InvoiceItem],
                 invoice_number: Optional[str] = None,
                 notes: Optional[str] = None,
                 is_shared: bool = False,
                 document_type: DocumentType = DocumentType.INVOICE,
                 file_path: Optional[str] = None,
                 uuid: Optional[str] = None,
                 is_draft: bool = False,  # 下書きフラグ
                 draft_parent_uuid: Optional[str] = None):  # 下書き元のUUID
        import uuid as uuid_module
        self.uuid = uuid or str(uuid_module.uuid4())
        self.customer = customer
        self.date = date
        self.items = items
        self.invoice_number = invoice_number or self._generate_invoice_number()
        self.notes = notes
        self.is_shared = is_shared
        self.document_type = document_type
        self.file_path = file_path
        self.is_draft = is_draft
        self.draft_parent_uuid = draft_parent_uuid
    
    def _generate_invoice_number(self) -> str:
        """請求書番号を生成"""
        return self.date.strftime('%Y%m%d-%H%M')
    
    @property
    def client_name(self) -> str:
        """互換性のためのゲッター"""
        return self.customer.formal_name
    
    @property
    def subtotal(self) -> int:
        """税抜合計金額"""
        return sum(item.subtotal for item in self.items)
    
    @property
    def tax(self) -> int:
        """消費税 (10%固定として計算、端数切り捨て)"""
        return int(self.subtotal * 0.1)
    
    @property
    def total_amount(self) -> int:
        """税込合計金額"""
        return self.subtotal + self.tax
    
    def copy_with(self, **kwargs) -> 'Invoice':
        """状態更新のためのコピーメソッド"""
        return Invoice(
            customer=kwargs.get('customer', self.customer),
            date=kwargs.get('date', self.date),
            items=kwargs.get('items', self.items),
            invoice_number=kwargs.get('invoice_number', self.invoice_number),
            notes=kwargs.get('notes', self.notes),
            is_shared=kwargs.get('is_shared', self.is_shared),
            document_type=kwargs.get('document_type', self.document_type),
            file_path=kwargs.get('file_path', self.file_path)
        )
    
    def to_csv(self) -> str:
        """CSV形式への変換"""
        lines = [
            f"Type,{self.document_type.value}",
            f"Customer,{self.customer.formal_name}",
            f"Number,{self.invoice_number}",
            f"Date,{self.date.strftime('%Y/%m/%d')}",
            f"Shared,{'Yes' if self.is_shared else 'No'}",
            "",
            "Description,Quantity,UnitPrice,Subtotal,IsDiscount"
        ]
        
        for item in self.items:
            lines.append(f"{item.description},{item.quantity},{item.unit_price},{item.subtotal},{'Yes' if item.is_discount else 'No'}")
        
        return '\n'.join(lines)
    
    def to_dict(self) -> Dict[str, Any]:
        """JSON変換 (データベース保存用)"""
        return {
            'uuid': self.uuid,
            'customer': self.customer.to_dict(),
            'date': self.date.isoformat(),
            'items': [item.to_dict() for item in self.items],
            'file_path': self.file_path,
            'invoice_number': self.invoice_number,
            'notes': self.notes,
            'is_shared': self.is_shared,
            'document_type': self.document_type.value
        }
    
    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> 'Invoice':
        """JSONから復元 (データベース読み込み用)"""
        customer = Customer.from_dict(data['customer'])
        date = datetime.fromisoformat(data['date'])
        items = [InvoiceItem.from_dict(item_data) for item_data in data['items']]
        
        # DocumentTypeの文字列からEnumに変換
        doc_type_str = data.get('document_type', '請求書')
        doc_type = next((dt for dt in DocumentType if dt.value == doc_type_str), DocumentType.INVOICE)
        
        return cls(
            customer=customer,
            date=date,
            items=items,
            invoice_number=data['invoice_number'],
            notes=data.get('notes'),
            is_shared=data.get('is_shared', False),
            document_type=doc_type,
            file_path=data.get('file_path'),
            uuid=data.get('uuid')
        )

# サンプルデータ生成関数
def create_sample_invoices() -> List[Invoice]:
    """サンプル伝票データを生成"""
    customers = [
        Customer(1, "田中商事", "田中商事株式会社", "東京都千代田区丸の内1-1-1", "03-1234-5678"),
        Customer(2, "鈴木商店", "鈴木商店", "東京都港区芝1-1-1", "03-2345-6789"),
        Customer(3, "佐藤工業", "佐藤工業株式会社", "東京都品川区東品川1-1-1", "03-3456-7890"),
        Customer(4, "高橋建設", "高橋建設株式会社", "東京都新宿区西新宿1-1-1", "03-4567-8901"),
        Customer(5, "伊藤電機", "伊藤電機株式会社", "東京都渋谷区渋谷1-1-1", "03-5678-9012")
    ]
    
    sample_invoices = [
        Invoice(
            customer=customers[0],
            date=datetime(2024, 1, 15),
            items=[
                InvoiceItem("A商品セット", 1, 150000),
                InvoiceItem("設置費用", 1, 25000)
            ],
            document_type=DocumentType.SALES,
            notes="A商品セット販売"
        ),
        Invoice(
            customer=customers[1],
            date=datetime(2024, 1, 14),
            items=[
                InvoiceItem("B部品", 10, 8500)
            ],
            document_type=DocumentType.ESTIMATE,
            notes="B部品見積"
        ),
        Invoice(
            customer=customers[2],
            date=datetime(2024, 1, 13),
            items=[
                InvoiceItem("C機器", 1, 120000)
            ],
            document_type=DocumentType.DELIVERY,
            notes="C機器納品"
        ),
        Invoice(
            customer=customers[3],
            date=datetime(2024, 1, 12),
            items=[
                InvoiceItem("D工事費用", 1, 200000)
            ],
            document_type=DocumentType.INVOICE,
            notes="D工事請求"
        ),
        Invoice(
            customer=customers[4],
            date=datetime(2024, 1, 11),
            items=[
                InvoiceItem("E製品", 1, 75000)
            ],
            document_type=DocumentType.RECEIPT,
            notes="E製品領収"
        )
    ]
    
    return sample_invoices
