import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:pdf/pdf.dart';
import 'package:pdf/widgets.dart' as pw;
import 'package:printing/printing.dart';
import 'package:qr/qr.dart';
import '../models/sake_item.dart';
import 'pricing_calculator.dart';
import 'pricing_helper.dart';

class PdfService {
  static Future<Uint8List> generateMenuPdf(
    List<SakeItem> items, {
    required String title,
    required String date,
    required bool includePhoto,
    required bool includePoem,
    required bool includeChart,
    required bool includePrice,
    required bool includeDate,
    required bool includeQr,  // New parameter
    String pdfSize = 'a4', // 'a4', 'a5', 'b5'
    bool isMonochrome = false,
    bool isPortrait = true,
    double density = 1.2,
  }) async {
    final pdf = pw.Document();

    // Font Loading
    final font = await PdfGoogleFonts.notoSansJPRegular();

    // Prepare Images (Monochrome processing handled in View or here? 
    // Ideally Printing package handles output color, but for "Preview" we might want processing.
    // But Printing package's `PdfPreview` usually handles grayscale display if pdf is standard.
    // However, user requested "Monochrome Preview Fix", meaning usually `PdfPreview` shows color even if printer driver will default to bw.
    // We can pre-process images to grayscale here if isMonochrome is true.
    
    final Map<String, pw.MemoryImage?> itemImages = {};
    for (var item in items) {
       if (item.displayData.imagePaths.isNotEmpty) {
         final file = File(item.displayData.imagePaths.first);
         if (await file.exists()) {
           try {
              final bytes = await file.readAsBytes();
              // In a real app we might use `image` package to grayscale here.
              // For now, let's load raw bytes. 
              // Printing package's `PdfPreview` has `build(...)` that returns bytes.
              itemImages[item.id] = pw.MemoryImage(bytes);
           } catch (e) {
             debugPrint('Error loading image for ${item.displayData.displayName}: $e');
             itemImages[item.id] = null;
           }
         }
       }
    }

    final PdfPageFormat rawFormat = _getPageFormat(pdfSize);
    final PdfPageFormat pageFormat = isPortrait ? rawFormat : rawFormat.landscape;
    
    // Density Calculation
    // Base items per page (Normal Density 1.0)
    // A4: 8, A5: 4, B5: 6 (Roughly)
    // With Density 1.2 (High) -> +20% items
    // With Density 1.5 -> +50% items
    
    // Let's define base items per page for "1.0"
    int baseItems = 0;
    switch (pdfSize) {
      case 'a5': baseItems = 4; break;
      case 'b5': baseItems = 6; break;
      case 'a4': default: baseItems = 8; break; 
    }
    
    final int itemsPerPage = (baseItems * density).round().clamp(1, 20); // Safety clamp
    final int crossAxisCount = _getCrossAxisCount(pdfSize); // 1 or 2

    for (var i = 0; i < items.length; i += itemsPerPage) {
      final chunk = items.skip(i).take(itemsPerPage).toList();
      final double titleFontSize = _getTitleFontSize(pdfSize);
      final double dateFontSize = _getDateFontSize(pdfSize);
      final double margin = _getPageMargin(pdfSize);

      pdf.addPage(
        pw.Page(
          pageFormat: pageFormat,
          margin: pw.EdgeInsets.all(margin),
          theme: pw.ThemeData.withFont(base: font),
          build: (context) {
            return pw.Column(
              children: [
                // Header
                pw.Column(
                  crossAxisAlignment: pw.CrossAxisAlignment.start,
                  children: [
                    // Title Row with Tax Label
                    pw.Row(
                      crossAxisAlignment: pw.CrossAxisAlignment.start,
                      mainAxisAlignment: pw.MainAxisAlignment.spaceBetween,
                      children: [
                        pw.Expanded(
                          child: pw.Container(
                            decoration: pw.BoxDecoration(
                              border: pw.Border(bottom: pw.BorderSide(color: PdfColors.grey400, width: 1.5)),
                            ),
                            padding: const pw.EdgeInsets.only(bottom: 4),
                            child: pw.Text(
                              title,
                              style: pw.TextStyle(fontSize: titleFontSize, font: font, fontWeight: pw.FontWeight.bold),
                            ),
                          ),
                        ),
                        // Tax Included Label (Top Right)
                        if (includePrice) ...[
                          pw.SizedBox(width: 8),
                          pw.Container(
                            padding: const pw.EdgeInsets.symmetric(horizontal: 6, vertical: 3),
                            decoration: pw.BoxDecoration(
                              border: pw.Border.all(color: PdfColors.grey500),
                              borderRadius: pw.BorderRadius.circular(4),
                            ),
                            child: pw.Text(
                              '税込価格',
                              style: pw.TextStyle(
                                fontSize: dateFontSize * 0.95,
                                font: font,
                                color: PdfColors.grey700,
                              ),
                            ),
                          ),
                        ],
                      ],
                    ),
                    // Date (if included)
                    if (includeDate && date.isNotEmpty)
                      pw.Padding(
                        padding: const pw.EdgeInsets.only(bottom: 4, top: 4),
                        child: pw.Text(date, style: pw.TextStyle(fontSize: dateFontSize, font: font)),
                      ),
                  ],
                ),
                pw.SizedBox(height: 4),

                pw.Expanded(
                  child: pw.Column(
                    children: [
                      for (var r = 0; r < (itemsPerPage / crossAxisCount).ceil(); r++)
                        pw.Expanded(
                          child: pw.Row(
                            crossAxisAlignment: pw.CrossAxisAlignment.stretch,
                            children: [
                              for (var c = 0; c < crossAxisCount; c++) ...[
                                () {
                                  final indexInChunk = r * crossAxisCount + c;
                                  if (indexInChunk < chunk.length) {
                                    return pw.Expanded(
                                      child: _buildMenuItem(
                                        chunk[indexInChunk],
                                        includePhoto ? itemImages[chunk[indexInChunk].id] : null,
                                        includePoem,
                                        includeChart,
                                        includePrice,
                                        includeQr,
                                        font,
                                        pdfSize,
                                        density, // Pass density to scale standard sizes if needed
                                        isMonochrome,
                                      ),
                                    );
                                  } else {
                                    return pw.Expanded(child: pw.SizedBox()); 
                                  }
                                }(),
                                
                                if (c < crossAxisCount - 1)
                                  pw.SizedBox(width: _getGridSpacing(pdfSize)),
                              ],
                            ],
                          ),
                        ),
                    ],
                  ),
                ),
              ],
            );
          },
        ),
      );
    }
    return pdf.save();
  }

  static pw.Widget _buildMenuItem(
    SakeItem item,
    pw.MemoryImage? image,
    bool includePoem,
    bool includeChart,
    bool includePrice,
    bool includeQr,
    pw.Font font,
    String pdfSize,
    double density,
    bool isMonochrome,
  ) {
    // When absolute density increases (more items), font sizes might need specific scaling 
    // IF the container becomes too small. 
    // However, `pw.Expanded` handles height distribution.
    // If text overflows, we might need auto-scaling.
    // For now, let's keep fonts standard but reduce padding slightly if density is high.
    
    final price = includePrice ? PricingCalculator.calculatePrice(item) : 0;
    
    // Scale down fonts slightly if density > 1.2
    double scale = 1.0;
    if (density > 1.2) scale = 0.9;
    if (density > 1.4) scale = 0.85;

    final double nameFontSize = _getNameFontSize(pdfSize) * scale;
    final double priceFontSize = _getPriceFontSize(pdfSize) * scale;
    final double infoFontSize = _getInfoFontSize(pdfSize) * scale;
    final double poemFontSize = _getPoemFontSize(pdfSize) * scale;
    final double imageSize = _getImageSize(pdfSize) * scale;
    // Extreme compaction for high density
    final double containerPadding = density > 1.0 ? 2 : _getContainerPadding(pdfSize) * scale;

    // Grayscale Filter for Image
    // For monochrome logic:
    // We can't easily filter the image bytes without decode, but text colors are handled.

    final accentColor = isMonochrome ? PdfColors.grey800 : PdfColors.brown400; 
    final subColor = isMonochrome ? PdfColors.grey700 : PdfColors.grey700;

    return pw.Container(
      decoration: pw.BoxDecoration(
        border: pw.Border(bottom: pw.BorderSide(color: PdfColors.grey300, width: 0.5)),
      ),
      padding: pw.EdgeInsets.symmetric(vertical: containerPadding, horizontal: containerPadding),
      child: pw.Row(
        crossAxisAlignment: pw.CrossAxisAlignment.start,
        children: [
          // Left: Photo
          if (image != null) ...[
            pw.Container(
              width: imageSize,
              height: imageSize,
              decoration: pw.BoxDecoration(
                borderRadius: pw.BorderRadius.circular(4),
                image: pw.DecorationImage(image: image, fit: pw.BoxFit.cover),
              ),
            ),
            pw.SizedBox(width: 10), // Increased Gap
          ],

          // Right: Content
          pw.Expanded(
            child: pw.Row(
              crossAxisAlignment: pw.CrossAxisAlignment.start,
              children: [
                // Left Column: Name, Brewery, Catch Copy
                pw.Expanded(
                  child: pw.Column(
                    crossAxisAlignment: pw.CrossAxisAlignment.start,
                    mainAxisAlignment: pw.MainAxisAlignment.start,
                    children: [
                      // 1. Name
                      pw.Text(
                        item.displayData.displayName,
                        style: pw.TextStyle(fontSize: nameFontSize, fontWeight: pw.FontWeight.bold, font: font),
                        maxLines: 2,
                      ),

                      // 2. Brewery / Prefecture
                      if (item.itemType != ItemType.set) ...[
                        pw.SizedBox(height: 2),
                        pw.Text(
                          '${item.displayData.displayBrewery} / ${item.displayData.displayPrefecture}',
                          style: pw.TextStyle(fontSize: infoFontSize, color: subColor, font: font),
                          maxLines: 1,
                        ),
                      ],

                      // 3. Catch Copy (Poem)
                      if (includePoem && item.displayData.catchCopy != null) ...[
                         pw.SizedBox(height: 4),
                         pw.Container(
                           padding: const pw.EdgeInsets.only(left: 6),
                           decoration: pw.BoxDecoration(
                             border: pw.Border(left: pw.BorderSide(color: isMonochrome ? PdfColors.grey500 : PdfColors.grey400, width: 1.5))
                           ),
                           child: pw.Text(
                             item.displayData.catchCopy!,
                             style: pw.TextStyle(fontSize: poemFontSize, font: font, fontStyle: pw.FontStyle.italic, color: accentColor),
                             maxLines: 2,
                             tightBounds: true,
                           ),
                         ),
                      ],
                    ],
                  ),
                ),

                // Right Column: Price (right-aligned)
                if (includePrice) ...[
                  pw.SizedBox(width: 8),
                  _buildCompactPriceTag(item, price, priceFontSize, font),
                ],

                // 6. QR Code (Data-in-QR)
                if (includeQr) ...[
                   pw.SizedBox(width: 8),
                   _buildQrCode(item),
                ]
              ],
            ),
          ),
        ],
      )
    );
  }

  static pw.Widget _buildQrCode(SakeItem item) {
    // Compact JSON for QR
    final jsonStr = item.toQrJson();
    
    // "Cute" QR Rendering using CustomPaint (Vector) to draw circles
    final qrCode = QrCode.fromData(
      data: jsonStr,
      errorCorrectLevel: QrErrorCorrectLevel.M,
    );
    final qrImage = QrImage(qrCode);

    return pw.Container(
      width: 40,
      height: 40,
      child: pw.CustomPaint(
        size: const PdfPoint(40, 40),
        painter: (PdfGraphics canvas, PdfPoint size) {
           final double pixelSize = size.x / qrImage.moduleCount;
           
           for (var x = 0; x < qrImage.moduleCount; x++) {
             for (var y = 0; y < qrImage.moduleCount; y++) {
               if (qrImage.isDark(y, x)) {
                  final double cx = x * pixelSize + pixelSize / 2;
                  final double cy = y * pixelSize + pixelSize / 2;
                  // Increase radius ratio for cuter look (0.9 -> 1.0 or slightly overlaps? 0.85 for cleaner dots)
                  // Let's use 1.0 for full circles that touch (cute)
                  final double radius = pixelSize / 2 * 0.95; 

                  // Corner finding logic for "Eyes" (Position Detection Patterns)
                  // Top-Left: (0-6, 0-6). Top-Right: (last-7 to last, 0-6). Bottom-Left: (0-6, last-7 to last)
                  // We can color them differently or keep uniformity.
                  // For "Cute", let's keep it uniform black circles but sharp.
                  
                  canvas.drawEllipse(cx, cy, radius, radius);
                  canvas.setFillColor(PdfColors.black);
                  canvas.fillPath();
               }
             }
           }
        }
      ),
    );
  }






  static pw.Widget _buildCompactPriceTag(SakeItem item, int calcPrice, double fontSize, pw.Font font) {
     if (item.userData.priceVariants != null && item.userData.priceVariants!.isNotEmpty) {
       // Multi-price: Column aligned to right
       return pw.Column(
         crossAxisAlignment: pw.CrossAxisAlignment.end,
         children: item.userData.priceVariants!.entries.take(3).map((e) =>
           pw.RichText(
             text: pw.TextSpan(
               children: [
                 pw.TextSpan(text: '${e.key} ', style: pw.TextStyle(font: font, fontSize: fontSize * 0.7, color: PdfColors.grey700)),
                 pw.TextSpan(text: '${PricingHelper.formatPrice(e.value)}円', style: pw.TextStyle(font: font, fontSize: fontSize, fontWeight: pw.FontWeight.bold)),
               ]
             )
           )
         ).toList(),
       );
     } else if (calcPrice > 0) {
       return pw.Text(
         '${PricingHelper.formatPrice(calcPrice)}円',
         style: pw.TextStyle(font: font, fontSize: fontSize, fontWeight: pw.FontWeight.bold),
       );
     }
     return pw.SizedBox();
  }
  
  static PdfPageFormat _getPageFormat(String size) {
    switch (size) {
      case 'a5': return PdfPageFormat.a5; // 148 x 210
      case 'b5': return PdfPageFormat(182 * PdfPageFormat.mm, 257 * PdfPageFormat.mm); // 182 x 257 (Portrait)
      case 'a4': default: return PdfPageFormat.a4; // 210 x 297
    }
  }

  // TWEAKED SIZES For "Standard" Template
  static double _getTitleFontSize(String pdfSize) => pdfSize == 'a5' ? 16.0 : 20.0;
  static double _getDateFontSize(String pdfSize) => pdfSize == 'a5' ? 9.0 : 10.0;
  static double _getNameFontSize(String pdfSize) => pdfSize == 'a5' ? 12.0 : (pdfSize == 'b5' ? 12.0 : 14.0);
  static double _getPriceFontSize(String pdfSize) => pdfSize == 'a5' ? 12.0 : (pdfSize == 'b5' ? 12.0 : 14.0);
  static double _getInfoFontSize(String pdfSize) => pdfSize == 'a5' ? 8.0 : (pdfSize == 'b5' ? 8.0 : 9.0);
  static double _getPoemFontSize(String pdfSize) => pdfSize == 'a5' ? 8.5 : (pdfSize == 'b5' ? 8.5 : 10.0);

  static double _getImageSize(String pdfSize) {
     switch (pdfSize) {
       case 'a5': return 50.0; // Increased from 40
       case 'b5': return 50.0; 
       case 'a4': default: return 60.0;
     }
  }

  static double _getContainerPadding(String pdfSize) => 6.0;
  static double _getPageMargin(String pdfSize) => 10.0 * PdfPageFormat.mm;
  static double _getGridSpacing(String pdfSize) => 8.0;



  static int _getCrossAxisCount(String pdfSize) {
    switch (pdfSize) {
      case 'a5': return 1; 
      case 'b5': return 2;
      case 'a4': default: return 2;
    }
  }
}
