import 'dart:async';
import 'dart:io';

import 'package:flutter/material.dart';
import 'package:camera/camera.dart';
import 'package:google_mlkit_text_recognition/google_mlkit_text_recognition.dart';
import 'services/collection_service.dart';
import 'theme/app_colors.dart';
import 'utils/scanner_utils.dart';

/// Screen that uses the camera to scan text (OCR) from a Hot Wheels package
/// and extract the hw_id (e.g. "JKF21").
///
/// The detected ID is returned via Navigator.pop(context, hwId).
class ScannerScreen extends StatefulWidget {
  final Future<bool> Function(String hwId)? onDetected;
  final List<Collection> collections;
  final String? activeCollectionId;
  final ValueChanged<String>? onCollectionChanged;

  const ScannerScreen({
    super.key,
    this.onDetected,
    this.collections = const [],
    this.activeCollectionId,
    this.onCollectionChanged,
  });

  @override
  State<ScannerScreen> createState() => _ScannerScreenState();
}

class _ScannerScreenState extends State<ScannerScreen>
  with WidgetsBindingObserver {
  static const _autoScanTickInterval = Duration(milliseconds: 700);
  static const _scanCooldownSuccess = Duration(milliseconds: 1500);
  static const _scanCooldownNoMatch = Duration(milliseconds: 2200);
  static const _scanCooldownError = Duration(milliseconds: 2600);

  CameraController? _cameraController;
  late final TextRecognizer _textRecognizer;
  bool _isBusy = false;
  bool _cameraReady = false;
  String? _lastDetected;
  bool _scanAccepted = false;
  bool _scanNotFound = false;
  String _statusText = 'Ready to scan';
  String? _activeCollectionId;
  bool _autoScanEnabled = false;
  Timer? _autoScanTimer;
  DateTime _nextScanAllowedAt = DateTime.fromMillisecondsSinceEpoch(0);
  bool _isInitializingCamera = false;
  String? _cameraError;

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this);
    _activeCollectionId = widget.activeCollectionId;
    _autoScanEnabled = widget.onDetected != null;
    _textRecognizer = TextRecognizer();
    _initCamera();
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    if (state == AppLifecycleState.inactive ||
        state == AppLifecycleState.paused ||
        state == AppLifecycleState.detached) {
      _disposeCamera();
      return;
    }

    if (state == AppLifecycleState.resumed) {
      _initCamera(force: true);
    }
  }

  void _handleCollectionChanged(String? value) {
    if (value == null) return;
    setState(() => _activeCollectionId = value);
    widget.onCollectionChanged?.call(value);
  }

  Future<void> _initCamera({bool force = false}) async {
    if (_isInitializingCamera) return;
    if (_cameraReady && !force) return;

    _isInitializingCamera = true;
    try {
      await _disposeCamera();

      final cameras = await availableCameras();
      if (cameras.isEmpty) {
        throw Exception('No camera available');
      }

      final backCamera = cameras.firstWhere(
        (c) => c.lensDirection == CameraLensDirection.back,
        orElse: () => cameras.first,
      );

      final controller = CameraController(
        backCamera,
        ResolutionPreset.medium,
        enableAudio: false,
      );

      await controller.initialize();
      if (!mounted) {
        await controller.dispose();
        return;
      }

      _cameraController = controller;
      setState(() {
        _cameraReady = true;
        _cameraError = null;
        _statusText = 'Ready to scan';
      });
      _startAutoScanLoop();
    } catch (e) {
      if (!mounted) return;
      setState(() {
        _cameraReady = false;
        _cameraError = 'Camera unavailable. Please retry.';
        _statusText = 'Camera unavailable';
      });
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(
          content: Text('Camera init failed: $e'),
          backgroundColor: Colors.red,
        ),
      );
    } finally {
      _isInitializingCamera = false;
    }
  }

  Future<void> _disposeCamera() async {
    _autoScanTimer?.cancel();
    _autoScanTimer = null;
    final controller = _cameraController;
    _cameraController = null;
    _cameraReady = false;
    if (controller != null) {
      await controller.dispose();
    }
  }

  void _startAutoScanLoop() {
    _autoScanTimer?.cancel();
    _autoScanTimer = Timer.periodic(_autoScanTickInterval, (_) {
      if (!_autoScanEnabled || _isBusy || !_cameraReady || !mounted) return;
      if (DateTime.now().isBefore(_nextScanAllowedAt)) return;
      _captureAndScan();
    });
  }

  void _toggleAutoScan() {
    setState(() {
      _autoScanEnabled = !_autoScanEnabled;
      _scanNotFound = false;
      _statusText = _autoScanEnabled ? 'Auto scan enabled' : 'Auto scan paused';
    });
  }

  /// Capture a photo, run OCR, and look for a Hot Wheels ID.
  Future<void> _captureAndScan() async {
    if (_isBusy || _cameraController == null || !_cameraController!.value.isInitialized) return;
    if (_cameraController!.value.isTakingPicture) return;

    setState(() {
      _isBusy = true;
      _scanNotFound = false;
      _statusText = 'Scanning…';
    });

    try {
      final xFile = await _cameraController!.takePicture();
      final inputImage = InputImage.fromFilePath(xFile.path);
      final recognized = await _textRecognizer.processImage(inputImage);

      final found = extractHwIdFromLines(
        recognized.blocks
            .expand((block) => block.lines)
            .map((line) => line.text),
      );

      // Clean up the temp image.
      try {
        await File(xFile.path).delete();
      } catch (_) {}

      if (!mounted) return;

      if (found != null) {
        _nextScanAllowedAt = DateTime.now().add(_scanCooldownSuccess);
        setState(() => _lastDetected = found);
        if (widget.onDetected != null) {
          await _submitDetected(found);
        }
      } else {
        _nextScanAllowedAt = DateTime.now().add(_scanCooldownNoMatch);
        setState(() {
          _scanAccepted = false;
          _scanNotFound = true;
          _statusText = 'No HW ID found';
        });
      }
    } catch (e) {
      _nextScanAllowedAt = DateTime.now().add(_scanCooldownError);
      if (!mounted) return;
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text('Scan error: $e'), backgroundColor: Colors.red),
      );
      setState(() => _statusText = 'Scan failed, try again');
    } finally {
      if (mounted) {
        setState(() {
          _isBusy = false;
          if (_statusText == 'Scanning…') {
            _statusText = 'Ready to scan';
          }
        });
      }
    }
  }

  Future<void> _submitDetected(String hwId) async {
    if (widget.onDetected == null) {
      if (mounted) Navigator.of(context).pop(hwId);
      return;
    }

    try {
      final keepScanning = await widget.onDetected!(hwId);
      if (!mounted) return;

      if (keepScanning) {
        setState(() {
          _lastDetected = null;
          _scanAccepted = true;
          _scanNotFound = false;
          _statusText = 'Saved. Ready for next scan';
        });
        Future<void>.delayed(const Duration(milliseconds: 650), () {
          if (!mounted) return;
          setState(() {
            _scanAccepted = false;
            if (_statusText == 'Saved. Ready for next scan') {
              _statusText = 'Ready to scan';
            }
          });
        });
      } else {
        Navigator.of(context).pop();
      }
    } catch (e) {
      if (!mounted) return;
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text('Process error: $e'), backgroundColor: Colors.red),
      );
    }
  }

  @override
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    _autoScanTimer?.cancel();
    final controller = _cameraController;
    _cameraController = null;
    if (controller != null) {
      controller.dispose();
    }
    _textRecognizer.close();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      extendBodyBehindAppBar: true,
      appBar: AppBar(
        title: const Text(
          'Scan HW ID',
          style: TextStyle(color: Colors.white, fontWeight: FontWeight.w600),
        ),
        backgroundColor: Colors.black38,
        iconTheme: const IconThemeData(color: Colors.white),
      ),
      body: Column(
        children: [
          if (widget.collections.isNotEmpty)
            Container(
              width: double.infinity,
              padding: const EdgeInsets.fromLTRB(12, 10, 12, 8),
              color: Colors.black.withValues(alpha: 0.55),
              child: DropdownButtonHideUnderline(
                child: DropdownButton<String>(
                  isExpanded: true,
                  value: _activeCollectionId,
                  dropdownColor: AppColors.navy,
                  iconEnabledColor: Colors.white,
                  style: const TextStyle(color: Colors.white),
                  hint: const Text(
                    'Select collection',
                    style: TextStyle(color: Colors.white70),
                  ),
                  items: widget.collections
                      .map(
                        (c) => DropdownMenuItem<String>(
                          value: c.id,
                          child: Text(
                            c.name,
                            overflow: TextOverflow.ellipsis,
                          ),
                        ),
                      )
                      .toList(),
                  onChanged: _isBusy ? null : _handleCollectionChanged,
                ),
              ),
            ),
          Container(
            width: double.infinity,
            padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 8),
            color: _scanAccepted
                ? AppColors.success.withValues(alpha: 0.12)
                : _scanNotFound
                    ? AppColors.error.withValues(alpha: 0.14)
                    : Colors.black.withValues(alpha: 0.55),
            child: Row(
              children: [
                Expanded(
                  child: Text(
                    _statusText,
                    textAlign: TextAlign.center,
                    style: TextStyle(
                      color: _scanAccepted
                          ? AppColors.success
                          : _scanNotFound
                              ? AppColors.error
                              : Colors.white,
                      fontSize: 12,
                      fontWeight: FontWeight.w600,
                    ),
                  ),
                ),
                if (widget.onDetected != null)
                  TextButton(
                    onPressed: _isBusy ? null : _toggleAutoScan,
                    style: TextButton.styleFrom(
                      foregroundColor:
                          _autoScanEnabled ? AppColors.success : Colors.white,
                      minimumSize: const Size(0, 26),
                      padding: const EdgeInsets.symmetric(horizontal: 10),
                    ),
                    child: Text(_autoScanEnabled ? 'AUTO ON' : 'AUTO OFF'),
                  ),
              ],
            ),
          ),
          // ── Camera preview ──
          Expanded(
            child: _cameraError != null
                ? Center(
                    child: Padding(
                      padding: const EdgeInsets.symmetric(horizontal: 24),
                      child: Column(
                        mainAxisSize: MainAxisSize.min,
                        children: [
                          const Icon(Icons.camera_alt_outlined,
                              size: 46, color: AppColors.error),
                          const SizedBox(height: 12),
                          Text(
                            _cameraError!,
                            textAlign: TextAlign.center,
                            style: const TextStyle(color: AppColors.textSecondary),
                          ),
                          const SizedBox(height: 12),
                          OutlinedButton.icon(
                            onPressed: () => _initCamera(force: true),
                            icon: const Icon(Icons.refresh),
                            label: const Text('Retry Camera'),
                          ),
                        ],
                      ),
                    ),
                  )
                : _cameraReady
                ? Stack(
                    fit: StackFit.expand,
                    children: [
                      ClipRect(
                        child: SizedBox.expand(
                          child: FittedBox(
                            fit: BoxFit.cover,
                            child: SizedBox(
                              width: _cameraController!.value.previewSize!.height,
                              height: _cameraController!.value.previewSize!.width,
                              child: CameraPreview(_cameraController!),
                            ),
                          ),
                        ),
                      ),
                      // Scan overlay / crosshair
                      Center(
                        child: Container(
                          width: 240,
                          height: 100,
                          decoration: BoxDecoration(
                            border: Border.all(
                              color: (_scanAccepted
                                      ? AppColors.success
                                      : _scanNotFound
                                          ? AppColors.error
                                          : AppColors.orange)
                                  .withValues(alpha: 0.9),
                              width: 2.5,
                            ),
                            borderRadius: BorderRadius.circular(16),
                          ),
                          child: Center(
                            child: Text(
                              'Align ID here',
                              style: TextStyle(
                                color: Colors.white.withValues(alpha: 0.7),
                                fontSize: 13,
                                fontWeight: FontWeight.w500,
                              ),
                            ),
                          ),
                        ),
                      ),
                    ],
                  )
                    : const Center(child: CircularProgressIndicator()),
          ),

          // ── Detected ID confirmation area ──
          if (_lastDetected != null)
            Container(
              width: double.infinity,
              decoration: BoxDecoration(
                color: AppColors.success.withValues(alpha: 0.1),
                border: Border(
                  top: BorderSide(
                    color: AppColors.success.withValues(alpha: 0.4),
                    width: 1.5,
                  ),
                ),
              ),
              padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14),
              child: Row(
                children: [
                  Container(
                    padding: const EdgeInsets.all(6),
                    decoration: BoxDecoration(
                      color: AppColors.success.withValues(alpha: 0.15),
                      shape: BoxShape.circle,
                    ),
                    child: const Icon(Icons.check, color: AppColors.success, size: 20),
                  ),
                  const SizedBox(width: 12),
                  Expanded(
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        const Text('Detected', style: TextStyle(fontSize: 12, color: AppColors.textSecondary)),
                        Text(
                          _lastDetected!,
                          style: const TextStyle(
                            fontSize: 22,
                            fontWeight: FontWeight.w700,
                            letterSpacing: 1.5,
                            color: AppColors.success,
                          ),
                        ),
                      ],
                    ),
                  ),
                  ElevatedButton(
                    onPressed: _isBusy || _lastDetected == null
                        ? null
                        : () => _submitDetected(_lastDetected!),
                    child: const Text('Use This'),
                  ),
                ],
              ),
            ),

          // ── Bottom controls ──
          SafeArea(
            child: Padding(
              padding: const EdgeInsets.all(16),
              child: Row(
                children: [
                  Expanded(
                    child: OutlinedButton.icon(
                      icon: const Icon(Icons.keyboard),
                      label: const Text('Manual'),
                      onPressed: () => _showManualEntry(context),
                    ),
                  ),
                  const SizedBox(width: 12),
                  Expanded(
                    flex: 2,
                    child: SizedBox(
                      height: 50,
                      child: DecoratedBox(
                        decoration: BoxDecoration(
                          gradient: _isBusy ? null : AppColors.brandGradient,
                          borderRadius: BorderRadius.circular(50),
                        ),
                        child: ElevatedButton.icon(
                          icon: _isBusy
                              ? const SizedBox(
                                  height: 20,
                                  width: 20,
                                  child: CircularProgressIndicator(
                                      strokeWidth: 2.5, color: Colors.white),
                                )
                              : const Icon(Icons.camera_alt, color: Colors.white),
                          label: Text(
                            _isBusy ? 'Scanning…' : 'Capture & Scan',
                            style: const TextStyle(color: Colors.white, fontWeight: FontWeight.w600),
                          ),
                          onPressed: _isBusy || !_cameraReady ? null : _captureAndScan,
                          style: ElevatedButton.styleFrom(
                            backgroundColor: Colors.transparent,
                            shadowColor: Colors.transparent,
                          ),
                        ),
                      ),
                    ),
                  ),
                ],
              ),
            ),
          ),
        ],
      ),
    );
  }

  /// Fallback: let the user type the HW ID manually.
  Future<void> _showManualEntry(BuildContext context) async {
    final result = await showDialog<String>(
      context: context,
      builder: (_) => const _ManualEntryDialog(),
    );

    if (result != null && context.mounted) {
      await _submitDetected(result);
    }
  }
}

// ── Manual Entry Dialog ───────────────────────────────────────────────
class _ManualEntryDialog extends StatefulWidget {
  const _ManualEntryDialog();

  @override
  State<_ManualEntryDialog> createState() => _ManualEntryDialogState();
}

class _ManualEntryDialogState extends State<_ManualEntryDialog> {
  final _controller = TextEditingController();

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  void _submit() {
    final value = _controller.text.trim().toUpperCase();
    if (value.isNotEmpty) Navigator.of(context).pop(value);
  }

  @override
  Widget build(BuildContext context) {
    return AlertDialog(
      title: const Text('Enter HW ID'),
      content: TextField(
        controller: _controller,
        autofocus: true,
        textCapitalization: TextCapitalization.characters,
        decoration: const InputDecoration(
          hintText: 'e.g. JKF21',
        ),
        onSubmitted: (_) => _submit(),
      ),
      actions: [
        TextButton(
          onPressed: () => Navigator.of(context).pop(),
          child: const Text('Cancel'),
        ),
        ElevatedButton(
          onPressed: _submit,
          child: const Text('OK'),
        ),
      ],
    );
  }
}
