// lib/services/pdf_generator.dart
import 'dart:io';
import 'dart:typed_data';
import 'package:flutter/material.dart' show debugPrint;
import 'package:flutter/services.dart';
import 'package:pdf/pdf.dart';
import 'package:pdf/widgets.dart' as pw;
import 'package:path_provider/path_provider.dart';
import 'package:crypto/crypto.dart';
import 'package:intl/intl.dart';
import 'package:printing/printing.dart';
import '../models/invoice_models.dart';
import '../models/company_model.dart'; // Companyモデルをインポート
import 'master_repository.dart'; // MasterRepositoryをインポート

/// A4サイズのプロフェッショナルな帳票PDFを生成し、保存する
/// 見積書、納品書、請求書、領収書の各DocumentTypeに対応
Future<String?> generateInvoicePdf(Invoice invoice) async {
  try {
    final pdf = pw.Document();

    // フォントのロード
    final fontData = await rootBundle.load("assets/fonts/ipaexg.ttf");
    final ttf = pw.Font.ttf(fontData);
    final boldTtf = pw.Font.ttf(fontData); // IPAexGはウェイトが1つなので同じものを使用

    // 自社情報をロード
    final MasterRepository masterRepository = MasterRepository();
    final Company company = await masterRepository.loadCompany();

    final dateFormatter = DateFormat('yyyy年MM月dd日');
    final amountFormatter = NumberFormat("¥#,###"); // ￥記号を付ける

    // 帳票の種類に応じたタイトルと接尾辞
    final String docTitle = invoice.type.label;
    final String honorific = " 御中"; // 宛名の敬称 (estimateでもinvoiceでも共通化)

    pdf.addPage(
      pw.MultiPage(
        pageFormat: PdfPageFormat.a4,
        margin: const pw.EdgeInsets.all(32),
        theme: pw.ThemeData.withFont(base: ttf, bold: boldTtf),
        build: (context) => [
          // タイトル
          pw.Header(
            level: 0,
            child: pw.Row(
              mainAxisAlignment: pw.MainAxisAlignment.spaceBetween,
              children: [
                pw.Text(docTitle, style: pw.TextStyle(fontSize: 28, fontWeight: pw.FontWeight.bold)),
                pw.Column(
                  crossAxisAlignment: pw.CrossAxisAlignment.end,
                  children: [
                    pw.Text("管理番号: ${invoice.invoiceNumber}"),
                    pw.Text("発行日: ${dateFormatter.format(invoice.date)}"),
                  ],
                ),
              ],
            ),
          ),
          pw.SizedBox(height: 20),

          // 宛名と自社情報
          pw.Row(
            crossAxisAlignment: pw.CrossAxisAlignment.start,
            children: [
              pw.Expanded(
                child: pw.Column(
                  crossAxisAlignment: pw.CrossAxisAlignment.start,
                  children: [
                    pw.Text("${invoice.customer.formalName}$honorific",
                      style: const pw.TextStyle(fontSize: 18)),
                    if (invoice.customer.department != null && invoice.customer.department!.isNotEmpty)
                      pw.Padding(
                        padding: const pw.EdgeInsets.only(top: 4),
                        child: pw.Text(invoice.customer.department!),
                      ),
                    pw.SizedBox(height: 10),
                    pw.Text(invoice.type == DocumentType.estimate
                        ? "下記の通り、御見積申し上げます。"
                        : "下記の通り、ご請求申し上げます。"),
                  ],
                ),
              ),
              pw.Expanded(
                child: pw.Column(
                  crossAxisAlignment: pw.CrossAxisAlignment.end,
                  children: [
                    pw.Text(company.formalName, style: pw.TextStyle(fontSize: 14, fontWeight: pw.FontWeight.bold)),
                    if (company.zipCode != null && company.zipCode!.isNotEmpty) pw.Text(company.zipCode!),
                    if (company.address != null && company.address!.isNotEmpty) pw.Text(company.address!),
                    if (company.tel != null && company.tel!.isNotEmpty) pw.Text(company.tel!),
                    if (company.registrationNumber != null && company.registrationNumber!.isNotEmpty) pw.Text(company.registrationNumber! ),
                  ],
                ),
              ),
            ],
          ),
          pw.SizedBox(height: 30),

          // 合計金額表示
          pw.Container(
            padding: const pw.EdgeInsets.all(8),
            decoration: const pw.BoxDecoration(color: PdfColors.grey200),
            child: pw.Row(
              mainAxisAlignment: pw.MainAxisAlignment.spaceBetween,
              children: [
                pw.Text("${docTitle}金額合計 (税込)", style: const pw.TextStyle(fontSize: 16)),
                pw.Text("${amountFormatter.format(invoice.totalAmount)} -",
                  style: pw.TextStyle(fontSize: 20, fontWeight: pw.FontWeight.bold)),
              ],
            ),
          ),
          pw.SizedBox(height: 20),

          // 明細テーブル
          pw.TableHelper.fromTextArray(
            headerStyle: pw.TextStyle(fontWeight: pw.FontWeight.bold),
            headerDecoration: const pw.BoxDecoration(color: PdfColors.grey300),
            cellHeight: 30,
            cellAlignments: {
              0: pw.Alignment.centerLeft,
              1: pw.Alignment.centerRight,
              2: pw.Alignment.centerRight,
              3: pw.Alignment.centerRight,
            },
            headers: ["品名 / 項目", "数量", "単価", "金額"],
            data: List<List<String>>.generate(
              invoice.items.length,
              (index) {
                final item = invoice.items[index];
                return [
                  item.description,
                  item.quantity.toString(),
                  amountFormatter.format(item.unitPrice),
                  amountFormatter.format(item.subtotal),
                ];
              },
            ),
          ),

          // 計算内訳
          pw.Row(
            mainAxisAlignment: pw.MainAxisAlignment.end,
            children: [
              pw.Container(
                width: 200,
                child: pw.Column(
                  children: [
                    pw.SizedBox(height: 10),
                    _buildSummaryRow("小計 (税抜)", amountFormatter.format(invoice.subtotal)),
                    _buildSummaryRow("消費税 (10%)", amountFormatter.format(invoice.tax)),
                    pw.Divider(),
                    _buildSummaryRow("合計", amountFormatter.format(invoice.totalAmount), isBold: true),
                  ],
                ),
              ),
            ],
          ),

          // 備考
          if (invoice.notes != null && invoice.notes!.isNotEmpty) ...[
            pw.SizedBox(height: 40),
            pw.Text("備考:", style: pw.TextStyle(fontWeight: pw.FontWeight.bold)),
            pw.Container(
              width: double.infinity,
              padding: const pw.EdgeInsets.all(8),
              decoration: pw.BoxDecoration(border: pw.Border.all(color: PdfColors.grey400)),
              child: pw.Text(invoice.notes!)),
          ],
        ],
        footer: (context) => pw.Container(
          alignment: pw.Alignment.centerRight,
          margin: const pw.EdgeInsets.only(top: 16),
          child: pw.Text(
            "Page ${context.pageNumber} / ${context.pagesCount}",
            style: const pw.TextStyle(color: PdfColors.grey),
          ),
        ),
      ),
    );

    final Uint8List bytes = await pdf.save();
    final String hash = sha256.convert(bytes).toString().substring(0, 8);
    final String dateFileStr = DateFormat('yyyyMMdd').format(invoice.date);
    String fileName = "${invoice.type.name}_${dateFileStr}_${invoice.customer.formalName}_$hash.pdf";

    final directory = await getExternalStorageDirectory();
    if (directory == null) return null;

    final file = File("${directory.path}/$fileName");
    await file.writeAsBytes(bytes);

    return file.path;
  } catch (e) {
    debugPrint("PDF Generation Error: $e");
    return null;
  }
}

/// ポケットサーマルプリンタ向けの58mmレシートPDFを生成して印刷ダイアログを表示する
Future<void> printThermalReceipt(Invoice invoice) async {
  try {
    final fontData = await rootBundle.load("assets/fonts/ipaexg.ttf");
    final ttf = pw.Font.ttf(fontData);
    final amountFormatter = NumberFormat("¥#,###"); // ￥記号を付ける

    // 自社情報をロード
    final MasterRepository masterRepository = MasterRepository();
    final Company company = await masterRepository.loadCompany();

    final doc = pw.Document();

    doc.addPage(
      pw.Page(
        // 58mm幅のサーマルプリンタ向け設定 (約164pt)
        pageFormat: const PdfPageFormat(58 * PdfPageFormat.mm, double.infinity, marginAll: 2 * PdfPageFormat.mm),
        theme: pw.ThemeData.withFont(base: ttf),
        build: (pw.Context context) {
          return pw.Column(
            crossAxisAlignment: pw.CrossAxisAlignment.start,
            children: [
              pw.Center(
                child: pw.Text(invoice.type.label, style: pw.TextStyle(fontSize: 16, fontWeight: pw.FontWeight.bold)),
              ),
              pw.SizedBox(height: 5),
              pw.Text("${invoice.customer.formalName} 様", style: const pw.TextStyle(fontSize: 10)),
              pw.Divider(thickness: 1, borderStyle: pw.BorderStyle.dashed),
              pw.SizedBox(height: 5),
              pw.Center(
                child: pw.Text(amountFormatter.format(invoice.totalAmount),
                  style: pw.TextStyle(fontSize: 18, fontWeight: pw.FontWeight.bold)),
              ),
              pw.Center(child: pw.Text("(うち消費税 ${amountFormatter.format(invoice.tax)})", style: const pw.TextStyle(fontSize: 8))),
              pw.SizedBox(height: 10),
              pw.Text("但し、お品代として", style: const pw.TextStyle(fontSize: 9)),
              pw.Text("上記正に領収いたしました", style: const pw.TextStyle(fontSize: 9)),
              pw.SizedBox(height: 10),

              // 明細簡易表示
              pw.Text("--- 明細 ---\n", style: const pw.TextStyle(fontSize: 8)),
              ...invoice.items.map((item) => pw.Row(
                mainAxisAlignment: pw.MainAxisAlignment.spaceBetween,
                children: [
                  pw.Expanded(child: pw.Text(item.description, style: const pw.TextStyle(fontSize: 8))),
                  pw.Text("x${item.quantity} ", style: const pw.TextStyle(fontSize: 8)),
                  pw.Text(amountFormatter.format(item.subtotal), style: const pw.TextStyle(fontSize: 8)),
                ],
              )),

              pw.Divider(thickness: 0.5),
              pw.SizedBox(height: 5),
              pw.Align(
                alignment: pw.Alignment.centerRight,
                child: pw.Column(
                  crossAxisAlignment: pw.CrossAxisAlignment.end,
                  children: [
                    pw.Text(company.formalName, style: const pw.TextStyle(fontSize: 9)),
                    pw.Text(DateFormat('yyyy/MM/dd HH:mm').format(invoice.date), style: const pw.TextStyle(fontSize: 7)),
                    pw.Text("No: ${invoice.invoiceNumber}", style: const pw.TextStyle(fontSize: 7)),
                  ],
                ),
              ),
              pw.SizedBox(height: 10),
              pw.Center(child: pw.Text("ありがとうございました", style: const pw.TextStyle(fontSize: 8))),
              pw.SizedBox(height: 20), // 切り取り用の余白
            ],
          );
        },
      ),
    );

    // 印刷ダイアログを表示
    await Printing.layoutPdf(
      onLayout: (PdfPageFormat format) async => doc.save(),
      name: "${invoice.type.name}_${invoice.invoiceNumber}",
    );
  } catch (e) {
    debugPrint("Thermal Print Error: $e");
  }
}

pw.Widget _buildSummaryRow(String label, String value, {bool isBold = false}) {
  final style = pw.TextStyle(fontSize: 12, fontWeight: isBold ? pw.FontWeight.bold : null);
  return pw.Padding(
    padding: const pw.EdgeInsets.symmetric(vertical: 2),
    child: pw.Row(
      mainAxisAlignment: pw.MainAxisAlignment.spaceBetween,
      children: [
        pw.Text(label, style: style),
        pw.Text(value, style: style),
      ],
    ),
  );
}
