"""
PDF生成サービス
Flutter参考プロジェクトの機能をPythonで実装
"""

import sys
import os
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import A4
from reportlab.lib.units import mm
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
from datetime import datetime
from typing import Optional
from models.invoice_models import Invoice, InvoiceItem
import os

class PdfGenerator:
    """PDF生成サービス"""
    
    def __init__(self):
        self.output_dir = "generated_pdfs"
        os.makedirs(self.output_dir, exist_ok=True)
        
        # 日本語フォント登録（システムフォントを使用）
        try:
            pdfmetrics.registerFont(TTFont('Japanese', '/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf'))
        except:
            # フォールバック：デフォルトフォント
            pass
    
    def generate_invoice_pdf(self, invoice: Invoice, company_info: dict) -> Optional[str]:
        """請求書PDFを生成
        
        Args:
            invoice: 伝票データモデル
            company_info: 自社情報 dict{name, address, phone, registration_number}
        
        Returns:
            生成されたPDFファイルパス、失敗時はNone
        """
        try:
            # ファイル名生成ルール: {日付}({タイプ}){株式会社等を除く顧客名}_{件名or商品1行目}_{金額}円_{HASH下8桁}.PDF
            date_str = invoice.date.strftime("%Y%m%d")
            doc_type = invoice.document_type.value if invoice.document_type else "請求"
            
            # 顧客名から株式会社等を除去
            customer_name = invoice.customer.name
            for suffix in ["株式会社", "有限会社", "合資会社", "合同会社"]:
                customer_name = customer_name.replace(suffix, "")
            
            # 顧客名から不正な文字を除去（ファイル名に使えない文字）
            import re
            customer_name = re.sub(r'[\\/:*?"<>|]', '', customer_name)
            
            # 件名または商品1行目
            subject_or_product = invoice.notes or ""
            if not subject_or_product and invoice.items:
                subject_or_product = invoice.items[0].description
            
            # 件名から不正な文字を除去
            subject_or_product = re.sub(r'[\\/:*?"<>|]', '', subject_or_product)
            
            # 件名が長すぎる場合は短縮
            if len(subject_or_product) > 30:
                subject_or_product = subject_or_product[:30] + "..."
            
            # 金額
            total_amount = sum(item.subtotal for item in invoice.items)
            amount_str = f"{total_amount:,}円"
            
            # ハッシュ（仮実装）
            import hashlib
            hash_input = f"{date_str}{doc_type}{customer_name}{subject_or_product}{total_amount}"
            hash_value = hashlib.md5(hash_input.encode()).hexdigest()[:8]
            
            filename = f"{date_str}({doc_type}){customer_name}_{subject_or_product}_{amount_str}_{hash_value}.PDF"
            filepath = os.path.join(self.output_dir, filename)
            
            # PDF生成
            c = canvas.Canvas(filepath, pagesize=A4)
            width, height = A4

            # 監査向けのメタ情報（バイナリ同一性は要求しない）
            try:
                c.setAuthor(company_info.get("id", ""))
                c.setTitle(f"{invoice.document_type.value} {invoice.invoice_number}")
                c.setSubject(getattr(invoice, "uuid", ""))
                keywords = []
                for key in ["payload_hash", "chain_hash", "node_id"]:
                    v = getattr(invoice, key, None)
                    if v:
                        keywords.append(f"{key}={v}")
                if keywords:
                    c.setKeywords(",".join(keywords))
            except Exception:
                pass
            
            # ヘッダー: 会社ロゴ・名前
            self._draw_header(c, invoice, company_info, width, height)
            
            # 顧客情報
            self._draw_customer_info(c, invoice, width, height)
            
            # 明細テーブル
            self._draw_items_table(c, invoice, width, height)
            
            # 合計金額
            self._draw_totals(c, invoice, width, height)
            
            # フッター: 登録番号など
            self._draw_footer(c, company_info, width)

            # payload_json をPDFに埋め込む（不可視テキストとして格納）
            try:
                payload_json = getattr(invoice, "payload_json", None)
                if payload_json:
                    c.saveState()
                    c.setFillColorRGB(1, 1, 1)
                    c.setFont("Helvetica", 1)
                    # PDFのどこかに確実に残す（見えない）
                    c.drawString(1 * mm, 1 * mm, f"INVOICE_PAYLOAD_JSON:{payload_json}")
                    c.restoreState()
            except Exception:
                pass
            
            c.save()
            return filepath
            
        except Exception as e:
            print(f"PDF生成エラー: {e}")
            return None
    
    def _draw_header(self, c: canvas.Canvas, invoice: Invoice, company_info: dict, width: float, height: float):
        """ヘッダー描画"""
        # 帳票種類タイトル
        c.setFont("Helvetica-Bold", 24)
        title = invoice.document_type.value
        c.drawString(20*mm, height - 30*mm, title)
        
        # 自社情報
        c.setFont("Helvetica", 10)
        company_name = company_info.get('name', '自社名未設定')
        c.drawString(20*mm, height - 45*mm, f"{company_name}")
        
        # 日付・番号
        c.setFont("Helvetica", 10)
        date_str = invoice.date.strftime("%Y年%m月%d日")
        c.drawString(width - 80*mm, height - 30*mm, f"発行日: {date_str}")
        c.drawString(width - 80*mm, height - 40*mm, f"No. {invoice.invoice_number}")
    
    def _draw_customer_info(self, c: canvas.Canvas, invoice: Invoice, width: float, height: float):
        """顧客情報描画"""
        y_pos = height - 70*mm
        
        c.setFont("Helvetica-Bold", 12)
        c.drawString(20*mm, y_pos, "御中:")
        
        c.setFont("Helvetica", 11)
        customer_name = invoice.customer.formal_name
        c.drawString(20*mm, y_pos - 8*mm, customer_name)
        
        if invoice.customer.address:
            c.setFont("Helvetica", 9)
            c.drawString(20*mm, y_pos - 16*mm, invoice.customer.address)
    
    def _draw_items_table(self, c: canvas.Canvas, invoice: Invoice, width: float, height: float):
        """明細テーブル描画"""
        # テーブルヘッダー
        y_start = height - 110*mm
        col_x = [20*mm, 80*mm, 110*mm, 140*mm, 170*mm]
        
        # ヘッダーライン
        c.setFont("Helvetica-Bold", 10)
        headers = ["品名", "数量", "単価", "金額", "摘要"]
        for i, header in enumerate(headers):
            c.drawString(col_x[i], y_start, header)
        
        # 明細行
        c.setFont("Helvetica", 9)
        y_pos = y_start - 10*mm
        
        for item in invoice.items:
            c.drawString(col_x[0], y_pos, item.description[:20])
            c.drawRightString(col_x[1] + 20*mm, y_pos, str(item.quantity))
            c.drawRightString(col_x[2] + 20*mm, y_pos, f"¥{item.unit_price:,}")
            c.drawRightString(col_x[3] + 20*mm, y_pos, f"¥{item.subtotal:,}")
            y_pos -= 8*mm
    
    def _draw_totals(self, c: canvas.Canvas, invoice: Invoice, width: float, height: float):
        """合計金額描画"""
        y_pos = height - 180*mm
        x_right = width - 40*mm
        
        c.setFont("Helvetica", 10)
        c.drawRightString(x_right, y_pos, f"小計: ¥{invoice.subtotal:,}")
        c.drawRightString(x_right, y_pos - 8*mm, f"消費税: ¥{invoice.tax:,}")
        
        c.setFont("Helvetica-Bold", 14)
        c.drawRightString(x_right, y_pos - 20*mm, f"合計: ¥{invoice.total_amount:,}")
    
    def _draw_footer(self, c: canvas.Canvas, company_info: dict, width: float):
        """フッター描画"""
        y_pos = 30*mm
        
        c.setFont("Helvetica", 8)
        reg_num = company_info.get('registration_number', '')
        if reg_num:
            c.drawString(20*mm, y_pos, f"登録番号: {reg_num}")
        
        # 支払期限・備考
        c.drawString(20*mm, y_pos - 5*mm, "お支払期限: 月末まで")

# 使用例
if __name__ == "__main__":
    from models.invoice_models import Customer, InvoiceItem, DocumentType
    from datetime import datetime
    
    # サンプルデータ
    customer = Customer(1, "田中商事", "田中商事株式会社", "東京都千代田区", "03-1234-5678")
    
    invoice = Invoice(
        customer=customer,
        date=datetime.now(),
        items=[
            InvoiceItem("商品A", 2, 15000),
            InvoiceItem("商品B", 1, 30000),
        ],
        document_type=DocumentType.INVOICE,
    )
    
    company = {
        'id': 'SAMPLE001',
        'name': 'サンプル株式会社',
        'registration_number': 'T1234567890123'
    }
    
    generator = PdfGenerator()
    pdf_path = generator.generate_invoice_pdf(invoice, company)
    
    if pdf_path:
        print(f"PDF生成成功: {pdf_path}")
    else:
        print("PDF生成失敗")
