import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_fullscreen/flutter_fullscreen.dart';
import 'package:logging/logging.dart';
import 'package:pdfrx/pdfrx.dart';
import 'package:sheetless/core/models/config.dart';
import 'package:sheetless/core/models/sheet.dart';
import 'package:sheetless/core/services/annotation_sync_service.dart';
import 'package:sheetless/core/services/api_client.dart';
import 'package:sheetless/core/services/storage_service.dart';

import '../../shared/input/pedal_shortcuts.dart';
import 'drawing/drawing.dart';
import 'widgets/pdf_page_display.dart';
import 'widgets/touch_navigation_layer.dart';

/// Page for viewing and annotating PDF sheet music.
class SheetViewerPage extends StatefulWidget {
  final Sheet sheet;
  final ApiClient apiClient;
  final Config config;

  const SheetViewerPage({
    super.key,
    required this.sheet,
    required this.apiClient,
    required this.config,
  });

  @override
  State<SheetViewerPage> createState() => _SheetViewerPageState();
}

class _SheetViewerPageState extends State<SheetViewerPage>
    with FullScreenListener {
  final _log = Logger('SheetViewerPage');
  final _storageService = StorageService();
  late final AnnotationSyncService _syncService;

  PdfDocument? _document;
  late Future<bool> _documentLoaded;
  int _currentPage = 1;
  int _totalPages = 1;
  bool _isPaintMode = false;

  /// Drawing controller for the current left page
  late DrawingController _leftDrawingController;

  /// Drawing controller for the right page (two-page mode)
  late DrawingController _rightDrawingController;

  @override
  void initState() {
    super.initState();

    // Initialize sync service
    _syncService = AnnotationSyncService(
      apiClient: widget.apiClient,
      storageService: _storageService,
    );

    // Initialize drawing controllers
    _leftDrawingController = DrawingController(maxHistorySteps: 50);
    _rightDrawingController = DrawingController(maxHistorySteps: 50);

    FullScreen.addListener(this);
    if (FullScreen.isFullScreen != widget.config.fullscreen) {
      FullScreen.setFullScreen(widget.config.fullscreen);
    }
    _documentLoaded = _loadPdf();
  }

  @override
  void dispose() {
    // Make sure annotations are saved before exiting
    if (_isPaintMode) {
      _saveCurrentAnnotations();
    }

    _leftDrawingController.dispose();
    _rightDrawingController.dispose();
    FullScreen.removeListener(this);
    _document?.dispose();
    super.dispose();
  }

  // ---------------------------------------------------------------------------
  // PDF Loading
  // ---------------------------------------------------------------------------

  Future<bool> _loadPdf() async {
    if (kIsWeb) {
      // Web: load directly into memory
      final data = await widget.apiClient.fetchPdfData(widget.sheet.uuid);
      _document = await PdfDocument.openData(data);
    } else {
      // Native: use file cache
      final file = await widget.apiClient.getPdfFileCached(widget.sheet.uuid);
      _document = await PdfDocument.openFile(file.path);
      widget.sheet.availableOffline = true;
    }

    setState(() {
      _totalPages = _document!.pages.length;
    });

    // Sync annotations from server (downloads newer versions)
    await _syncService.syncFromServer(widget.sheet.uuid);

    // Load annotations for current page(s)
    await _loadAnnotationsForCurrentPages();

    return true;
  }

  // ---------------------------------------------------------------------------
  // Annotation Persistence
  // ---------------------------------------------------------------------------

  /// Loads annotations for the current page(s) from storage.
  Future<void> _loadAnnotationsForCurrentPages() async {
    // Load left page annotations
    final leftJson = await _storageService.readAnnotations(
      widget.sheet.uuid,
      _currentPage,
    );
    if (leftJson != null && leftJson.isNotEmpty) {
      _leftDrawingController.fromJsonString(leftJson);
    } else {
      _leftDrawingController.clear();
    }

    // Load right page annotations (two-page mode)
    if (widget.config.twoPageMode && _currentPage < _totalPages) {
      final rightJson = await _storageService.readAnnotations(
        widget.sheet.uuid,
        _currentPage + 1,
      );
      if (rightJson != null && rightJson.isNotEmpty) {
        _rightDrawingController.fromJsonString(rightJson);
      } else {
        _rightDrawingController.clear();
      }
    }
  }

  /// Saves the current page(s) annotations to storage and uploads to server.
  ///
  /// Only saves if there are actual changes to avoid unnecessary writes/uploads.
  Future<void> _saveCurrentAnnotations() async {
    final now = DateTime.now();

    // Save left page only if changed
    if (_leftDrawingController.hasUnsavedChanges) {
      final leftJson = _leftDrawingController.toJsonString();
      final leftHasContent = leftJson.isNotEmpty && leftJson != '[]';

      await _storageService.writeAnnotationsWithMetadata(
        widget.sheet.uuid,
        _currentPage,
        leftHasContent ? leftJson : null,
        now,
      );

      // Upload left page to server
      _syncService.uploadAnnotation(
        sheetUuid: widget.sheet.uuid,
        page: _currentPage,
        annotationsJson: leftJson,
        lastModified: now,
      );

      _leftDrawingController.markSaved();
    }

    // Save right page (two-page mode) only if changed
    if (widget.config.twoPageMode &&
        _currentPage < _totalPages &&
        _rightDrawingController.hasUnsavedChanges) {
      final rightJson = _rightDrawingController.toJsonString();
      final rightHasContent = rightJson.isNotEmpty && rightJson != '[]';

      await _storageService.writeAnnotationsWithMetadata(
        widget.sheet.uuid,
        _currentPage + 1,
        rightHasContent ? rightJson : null,
        now,
      );

      // Upload right page to server
      _syncService.uploadAnnotation(
        sheetUuid: widget.sheet.uuid,
        page: _currentPage + 1,
        annotationsJson: rightJson,
        lastModified: now,
      );

      _rightDrawingController.markSaved();
    }
  }

  // ---------------------------------------------------------------------------
  // Fullscreen
  // ---------------------------------------------------------------------------

  @override
  void onFullScreenChanged(bool enabled, SystemUiMode? systemUiMode) {
    setState(() {
      widget.config.fullscreen = enabled;
      _storageService.writeConfig(widget.config);
    });
  }

  void _toggleFullscreen() {
    FullScreen.setFullScreen(!FullScreen.isFullScreen);
  }

  // ---------------------------------------------------------------------------
  // Navigation
  // ---------------------------------------------------------------------------

  Future<void> _turnPage(int delta) async {
    // Save current annotations before turning
    await _saveCurrentAnnotations();

    // Calculate new page
    final newPage = (_currentPage + delta).clamp(1, _totalPages);

    // Load annotations for new page(s) BEFORE updating state
    _currentPage = newPage;
    await _loadAnnotationsForCurrentPages();

    // Now update UI
    setState(() {});
  }

  // ---------------------------------------------------------------------------
  // Mode Switching
  // ---------------------------------------------------------------------------

  void _togglePaintMode() {
    if (widget.config.twoPageMode) {
      _showSnackBar('Paint mode is only available in single page mode');
      return;
    }

    if (_isPaintMode) {
      // Exiting paint mode - save annotations
      _saveCurrentAnnotations();
    }

    setState(() => _isPaintMode = !_isPaintMode);
  }

  void _toggleTwoPageMode() {
    if (_isPaintMode) {
      _showSnackBar('Cannot enter two-page mode while painting');
      return;
    }

    setState(() {
      widget.config.twoPageMode = !widget.config.twoPageMode;
      _storageService.writeConfig(widget.config);
    });

    // Reload annotations for new mode
    _loadAnnotationsForCurrentPages();
  }

  // ---------------------------------------------------------------------------
  // UI
  // ---------------------------------------------------------------------------

  @override
  Widget build(BuildContext context) {
    return PedalShortcuts(
      onPageForward: () => _turnPage(1),
      onPageBackward: () => _turnPage(-1),
      child: Scaffold(
        appBar: _buildAppBar(),
        body: _buildBody(),
        floatingActionButton: _isPaintMode ? _buildDrawingToolbar() : null,
        floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
      ),
    );
  }

  PreferredSizeWidget? _buildAppBar() {
    // Hide app bar in fullscreen when document is loaded
    if (widget.config.fullscreen && _document != null) {
      return null;
    }

    return AppBar(
      title: Text(widget.sheet.name),
      actions: [
        IconButton(
          icon: Icon(
            widget.config.fullscreen ? Icons.fullscreen_exit : Icons.fullscreen,
          ),
          tooltip: widget.config.fullscreen
              ? 'Exit Fullscreen'
              : 'Enter Fullscreen',
          onPressed: _toggleFullscreen,
        ),
        IconButton(
          icon: Icon(_isPaintMode ? Icons.brush : Icons.brush_outlined),
          tooltip: _isPaintMode ? 'Exit Paint Mode' : 'Enter Paint Mode',
          onPressed: _togglePaintMode,
        ),
        IconButton(
          icon: Icon(
            widget.config.twoPageMode ? Icons.filter_1 : Icons.filter_2,
          ),
          tooltip: widget.config.twoPageMode
              ? 'Single Page Mode'
              : 'Two Page Mode',
          onPressed: _toggleTwoPageMode,
        ),
      ],
    );
  }

  Widget _buildBody() {
    return FutureBuilder<bool>(
      future: _documentLoaded,
      builder: (context, snapshot) {
        if (snapshot.hasError) {
          _log.warning('Error loading PDF', snapshot.error);
          return _buildError(snapshot.error.toString());
        }

        if (snapshot.hasData && _document != null) {
          return _buildPdfViewer();
        }

        return const Center(child: CircularProgressIndicator());
      },
    );
  }

  Widget _buildPdfViewer() {
    final pageDisplay = PdfPageDisplay(
      document: _document!,
      numPages: _totalPages,
      currentPageNumber: _currentPage,
      config: widget.config,
      leftDrawingController: _leftDrawingController,
      rightDrawingController: widget.config.twoPageMode
          ? _rightDrawingController
          : null,
      drawingEnabled: _isPaintMode,
    );

    // When in paint mode, show the page display directly (DrawingBoard handles zoom/pan)
    if (_isPaintMode) {
      return pageDisplay;
    }

    // When not in paint mode, wrap with touch navigation
    return TouchNavigationLayer(
      pageDisplay: pageDisplay,
      config: widget.config,
      onToggleFullscreen: _toggleFullscreen,
      onExit: () => Navigator.pop(context),
      onPageTurn: _turnPage,
    );
  }

  Widget _buildDrawingToolbar() {
    return SafeArea(
      child: Padding(
        padding: const EdgeInsets.only(bottom: 16),
        child: DrawingToolbar(
          controller: _leftDrawingController,
          onClose: _togglePaintMode,
        ),
      ),
    );
  }

  Widget _buildError(String message) {
    return Center(
      child: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Text(
          message,
          style: Theme.of(
            context,
          ).textTheme.titleMedium?.copyWith(color: Colors.red),
          textAlign: TextAlign.center,
        ),
      ),
    );
  }

  void _showSnackBar(String message) {
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(content: Text(message), duration: const Duration(seconds: 2)),
    );
  }
}
