import 'dart:typed_data';

import 'package:flutter/services.dart' show rootBundle;
import 'package:pdf/pdf.dart';
import 'package:pdf/widgets.dart' as pw;

import 'file_service.dart';

/// One printable line of the "what I share" catalog. All strings arrive
/// already localized — this service knows nothing about i18n or the domain.
class ShareCatalogRow {
  const ShareCatalogRow({
    required this.name,
    required this.mode,
    this.scientificName,
    this.details,
  });

  /// The variety's label, as its keeper writes it.
  final String name;

  /// Scientific name of the linked species, if any (rendered in italics).
  final String? scientificName;

  /// The batch facts line ("Seeds · 2024 · 2 cobs"), if any.
  final String? details;

  /// On what terms it is offered ("To give away" / "To swap" / "For sale").
  final String mode;
}

/// Renders the "what I share" catalog as a PDF and hands it to the user via
/// the save dialog — a paper bridge for fairs and meet-ups, no network needed.
class ShareCatalogService {
  ShareCatalogService({required FileService files}) : _files = files;

  final FileService _files;

  /// Builds the catalog PDF. Pure of platform channels apart from loading the
  /// bundled font, so it runs (and is tested) on the host.
  ///
  /// The embedded DejaVu face covers Latin (extended), Cyrillic and Greek.
  /// Like the OCR traineddata, the PDF font is a per-locale resource: wider
  /// scripts (Arabic, CJK) ship alongside their locales, not hardcoded here.
  Future<Uint8List> buildPdf({
    required String title,
    required String date,
    required List<ShareCatalogRow> rows,
  }) async {
    final base = pw.Font.ttf(
      await rootBundle.load('assets/fonts/DejaVuSans.ttf'),
    );
    final bold = pw.Font.ttf(
      await rootBundle.load('assets/fonts/DejaVuSans-Bold.ttf'),
    );
    final doc = pw.Document(
      theme: pw.ThemeData.withFont(base: base, bold: bold, italic: base),
    );
    doc.addPage(
      pw.MultiPage(
        pageFormat: PdfPageFormat.a4,
        build: (context) => [
          pw.Text(title, style: pw.TextStyle(font: bold, fontSize: 20)),
          pw.SizedBox(height: 2),
          pw.Text(
            date,
            style: const pw.TextStyle(fontSize: 10, color: PdfColors.grey700),
          ),
          pw.SizedBox(height: 12),
          for (final row in rows)
            pw.Container(
              padding: const pw.EdgeInsets.symmetric(vertical: 6),
              decoration: const pw.BoxDecoration(
                border: pw.Border(
                  bottom: pw.BorderSide(color: PdfColors.grey300, width: 0.5),
                ),
              ),
              child: pw.Row(
                crossAxisAlignment: pw.CrossAxisAlignment.start,
                children: [
                  pw.Expanded(
                    child: pw.Column(
                      crossAxisAlignment: pw.CrossAxisAlignment.start,
                      children: [
                        pw.Text(
                          row.name,
                          style: pw.TextStyle(font: bold, fontSize: 12),
                        ),
                        if (row.scientificName != null)
                          pw.Text(
                            row.scientificName!,
                            style: pw.TextStyle(
                              fontSize: 10,
                              fontStyle: pw.FontStyle.italic,
                              color: PdfColors.grey700,
                            ),
                          ),
                        if (row.details != null)
                          pw.Text(
                            row.details!,
                            style: const pw.TextStyle(fontSize: 10),
                          ),
                      ],
                    ),
                  ),
                  pw.SizedBox(width: 8),
                  pw.Text(row.mode, style: const pw.TextStyle(fontSize: 10)),
                ],
              ),
            ),
        ],
      ),
    );
    return doc.save();
  }

  /// Builds the PDF and asks the user where to keep it. Returns true when
  /// saved, false when they cancelled the dialog.
  Future<bool> saveCatalog({
    required String title,
    required String date,
    required String suggestedName,
    required List<ShareCatalogRow> rows,
  }) async {
    final bytes = await buildPdf(title: title, date: date, rows: rows);
    final path = await _files.saveFile(
      suggestedName: suggestedName,
      bytes: bytes,
    );
    return path != null;
  }
}
