import 'dart:convert';
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';
import '../../provider/current_user_provider.dart';
import '../../widget/customsnackbarwidget.dart';
import 'upload_scan_provider.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 initializeControllerFuture = useState<Future<void>?>(null);
    final capturedImage = useState<XFile?>(null);
    final croppedImage = useState<File?>(null);
    final isLoading = useState<bool>(false);
    final isModalOpen = useState<bool>(false);
    final currentUser = ref.watch(currentUserProvider);
    final host = currentUser?.host ?? "";

    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;
    }

    void showResultModal(BuildContext context) {
      isModalOpen.value = true;

      showModalBottomSheet(
        context: context,
        isScrollControlled: true,
        enableDrag: false,
        backgroundColor: Colors.white,
        builder: (context) {
          return Padding(
            padding: const EdgeInsets.all(16.0),
            child: Column(
              mainAxisSize: MainAxisSize.min,
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                // Header dengan tombol close
                Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  children: [
                    Text(
                      "Hasil Foto",
                      style: Constant.cardText(context: context).copyWith(
                        fontWeight: FontWeight.bold,
                        fontSize: 18,
                        color: Constant.textBlack,
                      ),
                    ),
                    IconButton(
                      icon: const Icon(Icons.close, color: Colors.black),
                      onPressed: () {
                        isModalOpen.value = false;
                        Navigator.of(context).pop();
                      },
                    ),
                  ],
                ),
                const SizedBox(height: 16),

                // Gambar hasil foto
                if (croppedImage.value != null)
                  Container(
                    width: double.infinity,
                    height: 300,
                    decoration: BoxDecoration(
                      borderRadius: BorderRadius.circular(12),
                    ),
                    child: ClipRRect(
                      borderRadius: BorderRadius.circular(12),
                      child: Image.file(
                        croppedImage.value!,
                        fit: BoxFit.contain,
                      ),
                    ),
                  ),

                const SizedBox(height: 16),

                // Tombol Hapus dan Upload
                Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  children: [
                    // Tombol Hapus
                    ElevatedButton.icon(
                      onPressed: () {
                        capturedImage.value = null;
                        croppedImage.value = null;
                        isModalOpen.value = false;
                        Navigator.of(context).pop();
                      },
                      icon: const Icon(Icons.delete,
                          size: 17, color: Colors.white),
                      label: Text(
                        'Hapus',
                        style: Constant.cardText(context: context).copyWith(
                          color: Colors.white,
                        ),
                      ),
                      style: ElevatedButton.styleFrom(
                        backgroundColor: Constant.textRed,
                        shape: RoundedRectangleBorder(
                          borderRadius: BorderRadius.circular(8),
                        ),
                        elevation: 8,
                      ),
                    ),

                    // Tombol Upload
                    ElevatedButton.icon(
                      onPressed: () async {
                        // print('upload baru');
                        Uint8List bytes =
                            await croppedImage.value!.readAsBytes();
                        String base64String = base64Encode(bytes);
                        ref.read(uploadScanProvider.notifier).uploadScan(
                              host: host,
                              base64File: base64String,
                            );
                      },
                      icon: const Icon(Icons.upload,
                          size: 17, color: Colors.white),
                      label: Text(
                        'Upload',
                        style: Constant.cardText(context: context).copyWith(
                          color: Colors.white,
                        ),
                      ),
                      style: ElevatedButton.styleFrom(
                        backgroundColor: Colors.green,
                        shape: RoundedRectangleBorder(
                          borderRadius: BorderRadius.circular(8),
                        ),
                        elevation: 8,
                      ),
                    ),
                  ],
                ),
              ],
            ),
          );
        },
      ).whenComplete(() => isModalOpen.value = false);
    }

    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;

        showResultModal(context);
      } catch (e) {
        print("Error capturing image: $e");
      } finally {
        isLoading.value = false;
      }
    }

    // proses upload
    ref.listen(uploadScanProvider, (prev, next) {
      if (next is UploadScanStateLoading) {
        isLoading.value = true;
      } else if (next is UploadScanStateError) {
        isLoading.value = false;
        // errorMessage.value = next.message;
        debugPrint(next.message);
        snackbarWidget(
          context,
          next.message,
          snackbarType.error,
          Duration(seconds: 3),
        );
      } else if (next is UploadScanStateDone) {
        isLoading.value = false;
      }
    });

    return Scaffold(
      backgroundColor: Colors.black.withOpacity(0.5),
      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(),
            ),
          ),
          // loading
          if (isLoading.value)
            Positioned.fill(
              child: Container(
                color: Colors.black.withOpacity(0.5),
                child: const Center(
                  child: CircularProgressIndicator(color: Colors.white),
                ),
              ),
            ),
        ],
      ),
      bottomNavigationBar: BottomAppBar(
        height: Constant.getActualYPhone(
          context: context,
          y: 100,
        ),
        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),
              ),
            ),
            const Spacer(),
            // 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;
}
