import 'dart:io';
import 'dart:typed_data';
import 'package:camera/camera.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:image/image.dart' as img;

import '../../app/constant.dart';

class ScanScreen extends HookConsumerWidget {
  const ScanScreen({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: [
      SystemUiOverlay.bottom,
    ]);

    final cameraController = useState<CameraController?>(null);
    final capturedImage = useState<XFile?>(null);
    final croppedImage = useState<File?>(null);
    final isLoading = useState<bool>(false);
    final initializeControllerFuture = useState<Future<void>?>(null);

    useEffect(() {
      Future<void> initializeCamera() async {
        final cameras = await availableCameras();
        cameraController.value =
            CameraController(cameras[0], ResolutionPreset.max);
        initializeControllerFuture.value = cameraController.value!.initialize();
        await initializeControllerFuture.value;
        await cameraController.value!.setFlashMode(FlashMode.off);
      }

      initializeCamera();
      return null;
    }, []);

    Future<File> rotateAndCropImage(File imageFile) async {
      Uint8List imageBytes = await imageFile.readAsBytes();
      img.Image? original = img.decodeImage(imageBytes);
      if (original == null) return imageFile;

      img.Image rotated = img.bakeOrientation(original);

      int width = rotated.width;
      int height = rotated.height;
      bool isPortrait = height > width;

      int cropWidth, cropHeight;

      if (isPortrait) {
        cropHeight = (height * 0.7).toInt();
        cropWidth = (cropHeight ~/ 1.59).toInt();
      } else {
        cropWidth = (width * 0.7).toInt();
        cropHeight = (cropWidth ~/ 1.59).toInt();
      }

      int left = ((width - cropWidth) ~/ 2).toInt();
      int top = ((height - cropHeight) ~/ 2).toInt();

      img.Image cropped = img.copyCrop(rotated,
          x: left, y: top, width: cropWidth, height: cropHeight);

      File croppedFile = File('${imageFile.path}_cropped.jpg');
      await croppedFile.writeAsBytes(img.encodeJpg(cropped));

      return croppedFile;
    }

    Future<File> rotateImage(File imageFile) async {
      Uint8List bytes = await imageFile.readAsBytes();
      img.Image? image = img.decodeImage(bytes);

      if (image == null) return imageFile;

      img.Image rotated = img.copyRotate(image, angle: -90);

      File rotatedFile = File('${imageFile.path}_rotated.jpg');
      await rotatedFile.writeAsBytes(img.encodeJpg(rotated));

      return rotatedFile;
    }

    Future<void> captureAndCropImage() async {
      try {
        isLoading.value = true;
        await initializeControllerFuture.value;

        // Ambil gambar dari kamera
        final image = await cameraController.value!.takePicture();
        File cropped = await rotateAndCropImage(File(image.path));

        // Rotate gambar setelah cropping
        File rotatedImage = await rotateImage(cropped);

        // Simpan hasil yang sudah di-crop dan di-rotate
        capturedImage.value = image;
        croppedImage.value = rotatedImage;
      } catch (e) {
        print("Error capturing image: $e");
      } finally {
        isLoading.value = false;
      }
    }

    return GestureDetector(
      onTap: () {
        FocusManager.instance.primaryFocus!.unfocus();
      },
      child: Scaffold(
        resizeToAvoidBottomInset: true,
        backgroundColor: Constant.textBlack,
        body: Stack(
          children: [
            if (cameraController.value != null)
              FutureBuilder<void>(
                future: initializeControllerFuture.value,
                builder: (context, snapshot) {
                  if (snapshot.connectionState == ConnectionState.done) {
                    return CameraPreview(cameraController.value!);
                  } else {
                    return const Center(child: CircularProgressIndicator());
                  }
                },
              ),
            // bingkai foto
            Positioned.fill(
              child: CustomPaint(
                painter: OverlayPainter(),
              ),
            ),
            // hasil foto
            if (croppedImage.value != null)
              Positioned.fill(
                child: Image.file(
                  croppedImage.value!,
                  fit: BoxFit.contain,
                ),
              ),
            // loading
            if (isLoading.value)
              Positioned.fill(
                child: Container(
                  color: Colors.black.withOpacity(0.5),
                  child: const Center(
                    child: CircularProgressIndicator(color: Colors.white),
                  ),
                ),
              ),
          ],
        ),
        bottomNavigationBar: BottomAppBar(
          shape: const CircularNotchedRectangle(),
          child: Row(
            children: [
              ElevatedButton.icon(
                onPressed: () {
                  Navigator.of(context).pop();
                },
                icon: Icon(
                  Icons.arrow_back,
                  size: 17,
                  color: Constant.textWhite,
                ),
                label: Text(
                  'Kembali',
                  style: Constant.cardText(context: context).copyWith(
                    color: Constant.textWhite,
                  ),
                ),
                style: ElevatedButton.styleFrom(
                  backgroundColor: Constant.textCardGrey,
                  shape: RoundedRectangleBorder(
                    borderRadius: BorderRadius.circular(8),
                  ),
                  elevation: 8,
                  shadowColor: Constant.bgButton.withOpacity(0.24),
                ),
              ),

              Spacer(),

              // clear
              ElevatedButton.icon(
                onPressed: () {
                  capturedImage.value = null;
                  croppedImage.value = null;
                },
                icon: Icon(
                  Icons.clear,
                  size: 17,
                  color: Constant.textWhite,
                ),
                label: Text(
                  'Reset',
                  style: Constant.cardText(context: context).copyWith(
                    color: Constant.textWhite,
                  ),
                ),
                style: ElevatedButton.styleFrom(
                  backgroundColor: Constant.textRed,
                  shape: RoundedRectangleBorder(
                    borderRadius: BorderRadius.circular(8),
                  ),
                  elevation: 8,
                  shadowColor: Constant.bgButton.withOpacity(0.24),
                ),
              ),

              SizedBox(
                width: Constant.getActualXPhone(context: context, x: 10),
              ),
              // scan
              ElevatedButton.icon(
                onPressed: captureAndCropImage,
                icon: Icon(
                  Icons.camera,
                  size: 17,
                  color: Constant.textWhite,
                ),
                label: Text(
                  'Foto',
                  style: Constant.cardText(context: context).copyWith(
                    color: Constant.textWhite,
                  ),
                ),
                style: ElevatedButton.styleFrom(
                  backgroundColor: Constant.bgButton,
                  shape: RoundedRectangleBorder(
                    borderRadius: BorderRadius.circular(8),
                  ),
                  elevation: 8,
                  shadowColor: Constant.bgButton.withOpacity(0.24),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

class OverlayPainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    final paint = Paint()
      ..color = Colors.black.withOpacity(0.6)
      ..style = PaintingStyle.fill;

    final borderPaint = Paint()
      ..color = Colors.yellow
      ..strokeWidth = 4
      ..style = PaintingStyle.stroke;

    double boxHeight = size.height * 0.7;
    double boxWidth = boxHeight / 1.59;

    double left = (size.width - boxWidth) / 2;
    double top = (size.height - boxHeight) / 2;

    Path path = Path()
      ..addRect(Rect.fromLTWH(0, 0, size.width, size.height))
      ..addRect(Rect.fromLTWH(left, top, boxWidth, boxHeight))
      ..fillType = PathFillType.evenOdd;

    canvas.drawPath(path, paint);
    canvas.drawRect(Rect.fromLTWH(left, top, boxWidth, boxHeight), borderPaint);
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) => false;
}
