import 'dart:math';

import 'package:flutter/material.dart';
import 'package:pdfrx/pdfrx.dart';

import '../../../core/models/config.dart';
import '../drawing/drawing.dart';

/// Displays PDF pages with optional two-page mode and drawing overlay.
class PdfPageDisplay extends StatelessWidget {
  final PdfDocument document;
  final int numPages;
  final int currentPageNumber;
  final Config config;

  /// Controller for the left/main page drawing
  final DrawingController? leftDrawingController;

  /// Controller for the right page drawing (two-page mode only)
  final DrawingController? rightDrawingController;

  /// Whether drawing is enabled
  final bool drawingEnabled;

  const PdfPageDisplay({
    super.key,
    required this.document,
    required this.numPages,
    required this.currentPageNumber,
    required this.config,
    this.leftDrawingController,
    this.rightDrawingController,
    this.drawingEnabled = false,
  });

  /// Whether two-page mode is active and we have enough pages.
  bool get _showTwoPages => config.twoPageMode && numPages >= 2;

  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(
      builder: (context, constraints) {
        final maxSize = Size(constraints.maxWidth, constraints.maxHeight);
        final (leftSize, rightSize) = calculateScaledPageSizes(maxSize);

        if (_showTwoPages) {
          // Two-page mode: pages touch each other and are centered together
          return Center(
            child: Row(
              mainAxisSize: MainAxisSize.min,
              crossAxisAlignment: CrossAxisAlignment.center,
              children: [
                _buildPage(
                  pageNumber: currentPageNumber,
                  pageSize: leftSize,
                  controller: leftDrawingController,
                ),
                // Only show right page if there is one
                if (currentPageNumber < numPages)
                  _buildPage(
                    pageNumber: currentPageNumber + 1,
                    pageSize: rightSize!,
                    controller: rightDrawingController,
                  )
                else
                  // Empty space to keep left page position consistent on last page
                  SizedBox(width: rightSize!.width, height: rightSize.height),
              ],
            ),
          );
        }

        // Single page mode
        return Center(
          child: _buildPage(
            pageNumber: currentPageNumber,
            pageSize: leftSize,
            controller: leftDrawingController,
          ),
        );
      },
    );
  }

  Widget _buildPage({
    required int pageNumber,
    required Size pageSize,
    required DrawingController? controller,
  }) {
    final pdfPage = SizedBox(
      width: pageSize.width,
      height: pageSize.height,
      child: Stack(
        children: [
          PdfPageView(
            key: ValueKey(pageNumber),
            document: document,
            pageNumber: pageNumber,
            maximumDpi: 300,
            alignment: Alignment.center,
          ),
          _buildPageIndicator(pageNumber, pageSize),
        ],
      ),
    );

    // If no controller, just show the PDF
    if (controller == null) {
      return pdfPage;
    }

    // Wrap with DrawingBoard
    return DrawingBoard(
      boardSize: pageSize,
      controller: controller,
      drawingEnabled: drawingEnabled,
      minScale: 1.0,
      maxScale: 3.0,
      alignment: Alignment.center,
      child: pdfPage,
    );
  }

  Widget _buildPageIndicator(int pageNumber, Size pageSize) {
    return Positioned(
      bottom: 5,
      left: 0,
      right: 0,
      child: Center(
        child: Text(
          '$pageNumber / $numPages',
          style: const TextStyle(
            fontSize: 12,
            color: Colors.black54,
          ),
        ),
      ),
    );
  }

  // ---------------------------------------------------------------------------
  // Page Size Calculations
  // ---------------------------------------------------------------------------

  /// Calculates scaled page sizes for the current view.
  ///
  /// Returns a tuple of (leftPageSize, rightPageSize).
  /// rightPageSize is null when not in two-page mode.
  (Size, Size?) calculateScaledPageSizes(Size parentSize) {
    if (config.twoPageMode) {
      return _calculateTwoPageSizes(parentSize);
    }
    return (_calculateSinglePageSize(parentSize), null);
  }

  (Size, Size?) _calculateTwoPageSizes(Size parentSize) {
    final leftSize = _getUnscaledPageSize(currentPageNumber);
    final rightSize = numPages > currentPageNumber
        ? _getUnscaledPageSize(currentPageNumber + 1)
        : leftSize;

    // Combine pages for scaling calculation
    final combinedSize = Size(
      leftSize.width + rightSize.width,
      max(leftSize.height, rightSize.height),
    );

    final scaledCombined = _scaleToFit(parentSize, combinedSize);
    final scaleFactor = scaledCombined.width / combinedSize.width;

    return (leftSize * scaleFactor, rightSize * scaleFactor);
  }

  Size _calculateSinglePageSize(Size parentSize) {
    return _scaleToFit(parentSize, _getUnscaledPageSize(currentPageNumber));
  }

  Size _getUnscaledPageSize(int pageNumber) {
    return document.pages.elementAt(pageNumber - 1).size;
  }

  /// Scales a page size to fit within parent bounds while maintaining aspect ratio.
  Size _scaleToFit(Size parentSize, Size pageSize) {
    // Determine if height or width is the limiting factor
    if (parentSize.aspectRatio > pageSize.aspectRatio) {
      // Constrained by height
      final height = parentSize.height;
      final width = height * pageSize.aspectRatio;
      return Size(width, height);
    } else {
      // Constrained by width
      final width = parentSize.width;
      final height = width / pageSize.aspectRatio;
      return Size(width, height);
    }
  }
}
