import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:mobile_scanner/mobile_scanner.dart';

class ScanTabController {
  Future<void> Function()? _resume;
  Future<void> Function()? _pause;
  Future<void> Function()? _toggleTorch;

  Future<void> resume() async => await (_resume?.call() ?? Future.value());
  Future<void> pause()  async => await (_pause?.call() ?? Future.value());
  Future<void> toggleTorch() async => await (_toggleTorch?.call() ?? Future.value());
}

class ScanTabView extends StatefulWidget {
  const ScanTabView({
    super.key,
    this.onCodeDetected,
    this.controller,
  });

  final void Function(String code, BarcodeFormat format)? onCodeDetected;
  final ScanTabController? controller;

  @override
  State<ScanTabView> createState() => _ScanTabViewState();
}

class _ScanTabViewState extends State<ScanTabView> {
  final MobileScannerController _cam = MobileScannerController(
    detectionSpeed: DetectionSpeed.noDuplicates,
    formats: [
      BarcodeFormat.ean8,
      BarcodeFormat.ean13,
      BarcodeFormat.pdf417,
      BarcodeFormat.code128,
      BarcodeFormat.code39,
      BarcodeFormat.qrCode,
    ],
  );
  bool _locked = false;

  @override
  void initState() {
    super.initState();
    widget.controller?._resume = _resume;
    widget.controller?._pause  = _pause;
    widget.controller?._toggleTorch = () => _cam.toggleTorch();
  }

  @override
  void dispose() {
    _cam.dispose();
    super.dispose();
  }
  Future<void> _resume() async {
    _locked = false;
    await _cam.start();
  }
  Future<void> _pause() async  => _cam.stop();

  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(builder: (context, c) {
      final size = c.biggest;
      final side = (size.width - 64).clamp(220.0, size.height * 0.6);
      final left = (size.width - side) / 2;
      final top = (size.height - side) / 2;
      final scanRect = Rect.fromLTWH(left, top, side, side);

      return Stack(
        children: [
          Positioned.fill(
            child: MobileScanner(
              controller: _cam,
              fit: BoxFit.cover,
              scanWindow: scanRect,
              onDetect: (capture) async {
                if (_locked) return;
                final b = capture.barcodes.firstOrNull;
                final code = b?.rawValue ?? '';
                final format = b?.format ?? BarcodeFormat.unknown;
                if (code.isEmpty) return;
                _locked = true;
                await _cam.stop();
                widget.onCodeDetected?.call(code, format);
              },
            ),
          ),

          Positioned.fill(
            child: IgnorePointer(
              child: CustomPaint(
                painter: _ScannerOverlayPainter(scanWindow: scanRect),
              ),
            ),
          ),

          // Caption hướng dẫn
          Positioned(
            left: 16,
            right: 16,
            bottom: 90,
            child: Container(
              padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
              decoration: BoxDecoration(
                color: Colors.black.withOpacity(0.35),
                borderRadius: BorderRadius.circular(24),
              ),
              child: const Text(
                'Căn chỉnh mã QR vào vị trí trong khung hình.',
                textAlign: TextAlign.center,
                style: TextStyle(color: Colors.white, fontSize: 13, fontWeight: FontWeight.w600),
              ),
            ),
          ),

          // Nút bật đèn
          Positioned(
            bottom: 32,
            left: 0,
            right: 0,
            child: Center(
              child: ValueListenableBuilder<MobileScannerState>(
                valueListenable: _cam,
                builder: (_, state, __) {
                  final on = state.torchState == TorchState.on;
                  return InkWell(
                    onTap: () => _cam.toggleTorch(),
                    borderRadius: BorderRadius.circular(32),
                    child: Container(
                      width: 48, height: 48,
                      decoration: BoxDecoration(
                        color: Colors.black.withOpacity(0.25),
                        shape: BoxShape.circle,
                        border: Border.all(color: Colors.white70),
                      ),
                      alignment: Alignment.center,
                      child: Icon(
                          on ? Icons.flashlight_off_outlined : Icons.flashlight_on_outlined,
                          color: Colors.white, size: 24,
                      ),
                    ),
                  );
                },
              ),
            ),
          ),
        ],
      );
    });
  }
}

class _ScannerOverlayPainter extends CustomPainter {
  _ScannerOverlayPainter({required this.scanWindow});
  final Rect scanWindow;

  @override
  void paint(Canvas canvas, Size size) {
    // nền mờ
    final bg = Path()..addRect(Offset.zero & size);
    final hole = Path()..addRRect(RRect.fromRectAndRadius(scanWindow, const Radius.circular(2)));
    final mask = Path.combine(PathOperation.difference, bg, hole);
    final paintMask = Paint()..color = Colors.black.withOpacity(0.65);
    canvas.drawPath(mask, paintMask);

    // viền trắng
    final border = Paint()
      ..color = Colors.white
      ..style = PaintingStyle.stroke
      ..strokeWidth = 2;
    canvas.drawRRect(RRect.fromRectAndRadius(scanWindow, const Radius.circular(2)), border);

    // 4 góc xanh
    const cornerLen = 18.0;
    final corner = Paint()
      ..color = const Color(0xFF247CFF)
      ..style = PaintingStyle.stroke
      ..strokeWidth = 3;

    // TL
    canvas.drawLine(scanWindow.topLeft + const Offset(0, 0), scanWindow.topLeft + const Offset(cornerLen, 0), corner);
    canvas.drawLine(scanWindow.topLeft + const Offset(0, 0), scanWindow.topLeft + const Offset(0, cornerLen), corner);
    // TR
    canvas.drawLine(scanWindow.topRight + const Offset(-cornerLen, 0), scanWindow.topRight, corner);
    canvas.drawLine(scanWindow.topRight + const Offset(0, 0), scanWindow.topRight + const Offset(0, cornerLen), corner);
    // BL
    canvas.drawLine(scanWindow.bottomLeft + const Offset(0, -cornerLen), scanWindow.bottomLeft, corner);
    canvas.drawLine(scanWindow.bottomLeft + const Offset(0, 0), scanWindow.bottomLeft + const Offset(cornerLen, 0), corner);
    // BR
    canvas.drawLine(scanWindow.bottomRight + const Offset(-cornerLen, 0), scanWindow.bottomRight, corner);
    canvas.drawLine(scanWindow.bottomRight + const Offset(0, -cornerLen), scanWindow.bottomRight, corner);
  }

  @override
  bool shouldRepaint(covariant _ScannerOverlayPainter oldDelegate) =>
      oldDelegate.scanWindow != scanWindow;
}
