import 'dart:convert';
import 'dart:typed_data';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart' show rootBundle;
import 'package:flutter_quill/flutter_quill.dart' as quill;
import 'package:pdf/widgets.dart' as pw;
import 'package:pdf/pdf.dart' as pdf;
import 'package:printing/printing.dart';
import 'package:pdfrx/pdfrx.dart';

import '../../models/task.dart';
import '../../models/ticket.dart';
import '../../models/task_activity_log.dart';
import '../../models/task_assignment.dart';
import '../../models/profile.dart';
import '../../utils/app_time.dart';

Future<Uint8List> buildTaskPdfBytes(
  Task task,
  Ticket? ticket,
  String officeName,
  String serviceName,
  List<TaskActivityLog> logs,
  List<TaskAssignment> assignments,
  List<Profile> profiles,
  pdf.PdfPageFormat? format,
) async {
  final logoData = await rootBundle.load('assets/crmc_logo.png');
  final logoImage = pw.MemoryImage(logoData.buffer.asUint8List());

  final regularFontData = await rootBundle.load(
    'assets/fonts/Roboto-Regular.ttf',
  );
  final boldFontData = await rootBundle.load('assets/fonts/Roboto-Bold.ttf');
  final regularFont = pw.Font.ttf(regularFontData);
  final boldFont = pw.Font.ttf(boldFontData);

  final doc = pw.Document();
  final created = AppTime.formatDate(task.createdAt);

  final descriptionText = ticket?.description ?? task.description;

  String plainFromAction(String? at) {
    if (at == null || at.trim().isEmpty) return '';
    dynamic decoded = at;
    for (var i = 0; i < 3; i++) {
      if (decoded is String) {
        try {
          decoded = jsonDecode(decoded);
          continue;
        } catch (_) {
          break;
        }
      }
      break;
    }

    if (decoded is Map && decoded['ops'] is List) {
      final ops = decoded['ops'] as List;
      final buf = StringBuffer();
      for (final op in ops) {
        if (op is Map) {
          final insert = op['insert'];
          if (insert is String) {
            buf.write(insert);
          } else if (insert is Map && insert.containsKey('image')) {
            buf.write('[image]');
          } else {
            buf.write(insert?.toString() ?? '');
          }
        } else {
          buf.write(op.toString());
        }
      }
      return buf.toString().trim();
    }

    if (decoded is List) {
      try {
        final doc = quill.Document.fromJson(decoded);
        return doc.toPlainText().trim();
      } catch (_) {
        return decoded.join();
      }
    }
    return decoded.toString();
  }

  final actionTakenText = plainFromAction(task.actionTaken);
  final requestedBy = task.requestedBy ?? '';
  final notedBy = task.notedBy ?? '';
  final receivedBy = task.receivedBy ?? '';
  final profileById = {for (final p in profiles) p.id: p};
  final assignedForTask = assignments.where((a) => a.taskId == task.id).toList()
    ..sort((a, b) => a.createdAt.compareTo(b.createdAt));
  final assignedUserIds = {for (final a in assignedForTask) a.userId};
  final performedBy = assignedUserIds.isEmpty
      ? ''
      : assignedUserIds.map((id) => profileById[id]?.fullName ?? id).join(', ');

  // Use MultiPage to avoid overflow on long content and apply embedded fonts via ThemeData
  doc.addPage(
    pw.MultiPage(
      pageFormat: format ?? pdf.PdfPageFormat.a4,
      margin: pw.EdgeInsets.all(28),
      theme: pw.ThemeData.withFont(base: regularFont, bold: boldFont),
      footer: (pw.Context ctx) => pw.Container(
        alignment: pw.Alignment.centerRight,
        child: pw.Text(
          'MC-IHO-F-05 Rev. 2',
          style: pw.TextStyle(fontSize: 9, color: pdf.PdfColors.grey),
        ),
      ),
      build: (pw.Context ctx) => [
        pw.Center(
          child: pw.Row(
            mainAxisAlignment: pw.MainAxisAlignment.center,
            crossAxisAlignment: pw.CrossAxisAlignment.center,
            children: [
              pw.Container(width: 80, height: 80, child: pw.Image(logoImage)),
              pw.SizedBox(width: 16),
              pw.Column(
                crossAxisAlignment: pw.CrossAxisAlignment.center,
                children: [
                  pw.Text(
                    'Republic of the Philippines',
                    textAlign: pw.TextAlign.center,
                  ),
                  pw.Text(
                    'Department of Health',
                    textAlign: pw.TextAlign.center,
                  ),
                  pw.Text(
                    'Regional and Medical Center',
                    textAlign: pw.TextAlign.center,
                  ),
                  pw.SizedBox(height: 6),
                  pw.Text(
                    'Cotabato Regional and Medical Center',
                    textAlign: pw.TextAlign.center,
                    style: pw.TextStyle(fontWeight: pw.FontWeight.bold),
                  ),
                  pw.Text(
                    'Integrated Hospital Operations and Management Program',
                    textAlign: pw.TextAlign.center,
                  ),
                  pw.Text('(IHOMP)', textAlign: pw.TextAlign.center),
                ],
              ),
            ],
          ),
        ),
        pw.SizedBox(height: 12),
        pw.Center(
          child: pw.Text(
            'IT Job / Maintenance Request Form',
            style: pw.TextStyle(fontSize: 16, fontWeight: pw.FontWeight.bold),
          ),
        ),
        pw.SizedBox(height: 12),
        pw.Row(
          crossAxisAlignment: pw.CrossAxisAlignment.start,
          children: [
            pw.Expanded(
              child: pw.Column(
                crossAxisAlignment: pw.CrossAxisAlignment.start,
                children: [
                  pw.Row(
                    children: [
                      pw.Text('Task Number: '),
                      pw.Container(
                        padding: pw.EdgeInsets.only(bottom: 2),
                        decoration: pw.BoxDecoration(
                          border: pw.Border(
                            bottom: pw.BorderSide(
                              width: 0.8,
                              color: pdf.PdfColors.black,
                            ),
                          ),
                        ),
                        child: pw.Text(task.taskNumber ?? task.id),
                      ),
                    ],
                  ),
                  pw.SizedBox(height: 8),
                  pw.Row(
                    children: [
                      pw.Text('Service: '),
                      pw.Container(
                        padding: pw.EdgeInsets.only(bottom: 2),
                        decoration: pw.BoxDecoration(
                          border: pw.Border(
                            bottom: pw.BorderSide(
                              width: 0.8,
                              color: pdf.PdfColors.black,
                            ),
                          ),
                        ),
                        child: pw.Text(serviceName),
                      ),
                    ],
                  ),
                  pw.SizedBox(height: 8),
                  pw.Row(
                    children: [
                      pw.Text('Type: '),
                      pw.Container(
                        padding: pw.EdgeInsets.only(bottom: 2),
                        decoration: pw.BoxDecoration(
                          border: pw.Border(
                            bottom: pw.BorderSide(
                              width: 0.8,
                              color: pdf.PdfColors.black,
                            ),
                          ),
                        ),
                        child: pw.Text(task.requestType ?? ''),
                      ),
                    ],
                  ),
                ],
              ),
            ),
            pw.SizedBox(width: 12),
            pw.Container(
              width: 180,
              child: pw.Column(
                crossAxisAlignment: pw.CrossAxisAlignment.start,
                children: [
                  pw.Row(
                    children: [
                      pw.Text('Filed At: '),
                      pw.Container(
                        padding: pw.EdgeInsets.only(bottom: 2),
                        decoration: pw.BoxDecoration(
                          border: pw.Border(
                            bottom: pw.BorderSide(
                              width: 0.8,
                              color: pdf.PdfColors.black,
                            ),
                          ),
                        ),
                        child: pw.Text(created),
                      ),
                    ],
                  ),
                  pw.SizedBox(height: 8),
                  pw.Row(
                    children: [
                      pw.Text('Office: '),
                      pw.Container(
                        padding: pw.EdgeInsets.only(bottom: 2),
                        decoration: pw.BoxDecoration(
                          border: pw.Border(
                            bottom: pw.BorderSide(
                              width: 0.8,
                              color: pdf.PdfColors.black,
                            ),
                          ),
                        ),
                        child: pw.Text(officeName),
                      ),
                    ],
                  ),
                  pw.SizedBox(height: 8),
                  pw.Row(
                    children: [
                      pw.Text('Category: '),
                      pw.Container(
                        padding: pw.EdgeInsets.only(bottom: 2),
                        decoration: pw.BoxDecoration(
                          border: pw.Border(
                            bottom: pw.BorderSide(
                              width: 0.8,
                              color: pdf.PdfColors.black,
                            ),
                          ),
                        ),
                        child: pw.Text(task.requestCategory ?? ''),
                      ),
                    ],
                  ),
                ],
              ),
            ),
          ],
        ),
        pw.SizedBox(height: 12),
        pw.Divider(thickness: 0.8, color: pdf.PdfColors.grey),
        pw.SizedBox(height: 6),
        pw.Center(
          child: pw.Text(
            task.title,
            textAlign: pw.TextAlign.center,
            style: pw.TextStyle(fontWeight: pw.FontWeight.bold),
          ),
        ),
        pw.SizedBox(height: 6),
        pw.Divider(thickness: 0.8, color: pdf.PdfColors.grey),
        pw.SizedBox(height: 6),
        pw.Text('Description:'),
        pw.SizedBox(height: 6),
        pw.Container(
          padding: pw.EdgeInsets.all(6),
          child: pw.Text(descriptionText),
        ),
        pw.SizedBox(height: 12),
        // Requested/Noted signature lines (bottom-aligned to match Performed/Received)
        pw.Row(
          crossAxisAlignment: pw.CrossAxisAlignment.end,
          children: [
            pw.Expanded(
              child: pw.Container(
                height: 56,
                child: pw.Column(
                  mainAxisAlignment: pw.MainAxisAlignment.end,
                  children: [
                    pw.Container(height: 1, color: pdf.PdfColors.black),
                    pw.SizedBox(height: 6),
                    pw.Text(
                      requestedBy,
                      style: pw.TextStyle(fontWeight: pw.FontWeight.bold),
                    ),
                    pw.Text('Requested By'),
                  ],
                ),
              ),
            ),
            pw.SizedBox(width: 12),
            pw.Expanded(
              child: pw.Container(
                height: 56,
                child: pw.Column(
                  mainAxisAlignment: pw.MainAxisAlignment.end,
                  children: [
                    pw.Container(height: 1, color: pdf.PdfColors.black),
                    pw.SizedBox(height: 6),
                    pw.Text(
                      notedBy,
                      style: pw.TextStyle(fontWeight: pw.FontWeight.bold),
                    ),
                    pw.Text('Noted by Supervisor/Senior'),
                  ],
                ),
              ),
            ),
          ],
        ),
        pw.SizedBox(height: 12),
        pw.Text('Action Taken:'),
        pw.SizedBox(height: 6),
        pw.Container(
          padding: pw.EdgeInsets.all(6),
          child: pw.Text(actionTakenText),
        ),
        pw.SizedBox(height: 6),
        pw.Divider(thickness: 0.8, color: pdf.PdfColors.grey),
        pw.SizedBox(height: 12),
        // Historical timestamps side-by-side: Created / Started / Closed
        pw.Row(
          crossAxisAlignment: pw.CrossAxisAlignment.start,
          children: [
            pw.Expanded(
              child: pw.Column(
                crossAxisAlignment: pw.CrossAxisAlignment.start,
                children: [
                  pw.Text('Created At:'),
                  pw.SizedBox(height: 4),
                  pw.Text(
                    '${AppTime.formatDate(task.createdAt)} ${AppTime.formatTime(task.createdAt)}',
                  ),
                ],
              ),
            ),
            pw.SizedBox(width: 12),
            pw.Expanded(
              child: pw.Column(
                crossAxisAlignment: pw.CrossAxisAlignment.start,
                children: [
                  pw.Text('Started At:'),
                  pw.SizedBox(height: 4),
                  pw.Text(
                    task.startedAt == null
                        ? ''
                        : '${AppTime.formatDate(task.startedAt!)} ${AppTime.formatTime(task.startedAt!)}',
                  ),
                ],
              ),
            ),
            pw.SizedBox(width: 12),
            pw.Expanded(
              child: pw.Column(
                crossAxisAlignment: pw.CrossAxisAlignment.start,
                children: [
                  pw.Text('Closed At:'),
                  pw.SizedBox(height: 4),
                  pw.Text(
                    task.completedAt == null
                        ? ''
                        : '${AppTime.formatDate(task.completedAt!)} ${AppTime.formatTime(task.completedAt!)}',
                  ),
                ],
              ),
            ),
          ],
        ),
        pw.SizedBox(height: 36),

        // Wrap signature block to prevent awkward page breaks
        pw.Wrap(
          spacing: 6,
          runSpacing: 6,
          children: [
            // Signature lines row (fixed)
            pw.Row(
              children: [
                pw.Expanded(
                  child: pw.Container(
                    height: 24,
                    alignment: pw.Alignment.center,
                    child: pw.Container(height: 1, color: pdf.PdfColors.black),
                  ),
                ),
                pw.SizedBox(width: 12),
                pw.Expanded(
                  child: pw.Container(
                    height: 24,
                    alignment: pw.Alignment.center,
                    child: pw.Container(height: 1, color: pdf.PdfColors.black),
                  ),
                ),
              ],
            ),
            // Names row
            pw.Row(
              children: [
                pw.Expanded(
                  child: pw.Container(
                    padding: pw.EdgeInsets.only(right: 6),
                    alignment: pw.Alignment.center,
                    child: pw.Text(
                      performedBy,
                      textAlign: pw.TextAlign.center,
                      style: pw.TextStyle(fontWeight: pw.FontWeight.bold),
                    ),
                  ),
                ),
                pw.SizedBox(width: 12),
                pw.Expanded(
                  child: pw.Container(
                    padding: pw.EdgeInsets.only(left: 6),
                    alignment: pw.Alignment.center,
                    child: pw.Text(
                      receivedBy,
                      textAlign: pw.TextAlign.center,
                      style: pw.TextStyle(fontWeight: pw.FontWeight.bold),
                    ),
                  ),
                ),
              ],
            ),
            // Labels row
            pw.Row(
              children: [
                pw.Expanded(
                  child: pw.Text(
                    'Performed By',
                    textAlign: pw.TextAlign.center,
                  ),
                ),
                pw.SizedBox(width: 12),
                pw.Expanded(
                  child: pw.Text('Received By', textAlign: pw.TextAlign.center),
                ),
              ],
            ),
          ],
        ),
        pw.SizedBox(height: 12),
      ],
    ),
  );

  return doc.save();
}

Future<void> showTaskPdfPreview(
  BuildContext context,
  Task task,
  Ticket? ticket,
  String officeName,
  String serviceName,
  List<TaskActivityLog> logs,
  List<TaskAssignment> assignments,
  List<Profile> profiles,
) async {
  await showDialog<void>(
    context: context,
    builder: (ctx) => TaskPdfDialog(
      task: task,
      ticket: ticket,
      officeName: officeName,
      serviceName: serviceName,
      logs: logs,
      assignments: assignments,
      profiles: profiles,
    ),
  );
}

class TaskPdfDialog extends StatefulWidget {
  final Task task;
  final Ticket? ticket;
  final String officeName;
  final String serviceName;
  final List<TaskActivityLog> logs;
  final List<TaskAssignment> assignments;
  final List<Profile> profiles;

  const TaskPdfDialog({
    super.key,
    required this.task,
    this.ticket,
    required this.officeName,
    required this.serviceName,
    required this.logs,
    required this.assignments,
    required this.profiles,
  });

  @override
  State<TaskPdfDialog> createState() => _TaskPdfDialogState();
}

class _TaskPdfDialogState extends State<TaskPdfDialog> {
  Future<Uint8List>? _pdfFuture;

  @override
  void initState() {
    super.initState();
    // Initialize once
    _pdfFuture = buildTaskPdfBytes(
      widget.task,
      widget.ticket,
      widget.officeName,
      widget.serviceName,
      widget.logs,
      widget.assignments,
      widget.profiles,
      null,
    );
  }

  @override
  Widget build(BuildContext context) {
    return AlertDialog(
      contentPadding: EdgeInsets.zero,
      content: SizedBox(
        width: 800,
        height: 900,
        child: Column(
          children: [
            Padding(
              padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
              child: Row(
                children: [
                  const Expanded(
                    child: Text(
                      'IT Job Preview',
                      style: TextStyle(
                        fontSize: 16,
                        fontWeight: FontWeight.w600,
                      ),
                    ),
                  ),
                  IconButton(
                    tooltip: 'Print',
                    icon: const Icon(Icons.print),
                    onPressed: () async {
                      final bytes = await _pdfFuture;
                      if (bytes == null) return;
                      await Printing.layoutPdf(
                        onLayout: (_) async => bytes,
                        name:
                            'Task - ${widget.task.taskNumber ?? widget.task.id}.pdf',
                      );
                    },
                  ),
                  IconButton(
                    tooltip: 'Download',
                    icon: const Icon(Icons.download),
                    onPressed: () async {
                      final bytes = await _pdfFuture;
                      if (bytes == null) return;
                      await Printing.sharePdf(
                        bytes: bytes,
                        filename:
                            'Task - ${widget.task.taskNumber ?? widget.task.id}.pdf',
                      );
                    },
                  ),
                  IconButton(
                    tooltip: 'Close',
                    icon: const Icon(Icons.close),
                    onPressed: () => Navigator.of(context).pop(),
                  ),
                ],
              ),
            ),
            const Divider(height: 1),
            Expanded(
              child: FutureBuilder<Uint8List>(
                future: _pdfFuture,
                builder: (context, snapshot) {
                  if (snapshot.connectionState == ConnectionState.waiting) {
                    return const Center(child: CircularProgressIndicator());
                  }
                  if (snapshot.hasError) {
                    return Center(child: Text(snapshot.error.toString()));
                  }
                  final data = snapshot.data;
                  if (data == null) return const SizedBox.shrink();
                  return PdfViewer.data(data, sourceName: 'task.pdf');
                },
              ),
            ),
          ],
        ),
      ),
    );
  }
}
