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 '../../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('crmc_logo.png');
  final logoImage = pw.MemoryImage(logoData.buffer.asUint8List());
  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 latestAssignment = assignedForTask.isEmpty
      ? null
      : assignedForTask.last;
  final performedBy = latestAssignment == null
      ? ''
      : (profileById[latestAssignment.userId]?.fullName ??
            latestAssignment.userId);

  doc.addPage(
    pw.Page(
      pageFormat: format,
      margin: pw.EdgeInsets.all(28),
      build: (pw.Context ctx) {
        return pw.Column(
          crossAxisAlignment: pw.CrossAxisAlignment.start,
          children: [
            pw.Row(
              crossAxisAlignment: pw.CrossAxisAlignment.start,
              children: [
                pw.Container(width: 64, height: 64, child: pw.Image(logoImage)),
                pw.SizedBox(width: 12),
                pw.Expanded(
                  child: 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(
              children: [
                pw.Text('Task Number: ${task.taskNumber ?? task.id}'),
                pw.Spacer(),
                pw.Text('Filed At: $created'),
              ],
            ),
            pw.SizedBox(height: 8),
            pw.Row(
              children: [
                pw.Text('Service: $serviceName'),
                pw.SizedBox(width: 12),
                pw.Text('Office: $officeName'),
              ],
            ),
            pw.SizedBox(height: 8),
            pw.Row(
              children: [
                pw.Text('Type: ${task.requestType ?? ''}'),
                pw.SizedBox(width: 12),
                pw.Text('Category: ${task.requestCategory ?? ''}'),
              ],
            ),
            pw.SizedBox(height: 12),
            pw.Text('Task Title: ${task.title}'),
            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
            pw.Row(
              children: [
                pw.Expanded(
                  child: pw.Column(
                    children: [
                      pw.Container(height: 28),
                      pw.Container(height: 1, color: pdf.PdfColors.black),
                      pw.SizedBox(height: 6),
                      pw.Text(requestedBy),
                      pw.Text('Requested By'),
                    ],
                  ),
                ),
                pw.SizedBox(width: 12),
                pw.Expanded(
                  child: pw.Column(
                    children: [
                      pw.Container(height: 28),
                      pw.Container(height: 1, color: pdf.PdfColors.black),
                      pw.SizedBox(height: 6),
                      pw.Text(notedBy),
                      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: 12),
            pw.Text('History updates:'),
            pw.SizedBox(height: 6),
            pw.Column(
              crossAxisAlignment: pw.CrossAxisAlignment.start,
              children: [
                for (final log in logs)
                  pw.Row(
                    children: [
                      pw.Text(AppTime.formatDate(log.createdAt)),
                      pw.SizedBox(width: 8),
                      pw.Text(AppTime.formatTime(log.createdAt)),
                      pw.SizedBox(width: 8),
                      pw.Text(log.actionType),
                    ],
                  ),
              ],
            ),
            pw.SizedBox(height: 12),
            // Performed/Received signature lines
            pw.Row(
              children: [
                pw.Expanded(
                  child: pw.Column(
                    children: [
                      pw.Container(height: 28),
                      pw.Container(height: 1, color: pdf.PdfColors.black),
                      pw.SizedBox(height: 6),
                      pw.Text(performedBy),
                      pw.Text('Performed By'),
                    ],
                  ),
                ),
                pw.SizedBox(width: 12),
                pw.Expanded(
                  child: pw.Column(
                    children: [
                      pw.Container(height: 28),
                      pw.Container(height: 1, color: pdf.PdfColors.black),
                      pw.SizedBox(height: 6),
                      pw.Text(receivedBy),
                      pw.Text('Received By'),
                    ],
                  ),
                ),
              ],
            ),
          ],
        );
      },
    ),
  );

  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) => AlertDialog(
      contentPadding: const EdgeInsets.all(8),
      content: SizedBox(
        width: 700,
        height: 900,
        child: PdfPreview(
          build: (format) => buildTaskPdfBytes(
            task,
            ticket,
            officeName,
            serviceName,
            logs,
            assignments,
            profiles,
            format,
          ),
          allowPrinting: true,
          allowSharing: true,
        ),
      ),
      actions: [
        TextButton(
          onPressed: () => Navigator.of(ctx).pop(),
          child: const Text('Close'),
        ),
      ],
    ),
  );
}
