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

import 'package:component_library/component_library.dart';
import 'package:extended_image/extended_image.dart';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';

import '_dashed_rect.dart';

class InputFile extends StatefulWidget {
  const InputFile({
    Key? key,
    this.files = const [],
    required this.onChange,
    this.allowMultiple = false,
    this.allowedExtensions = const ['jpg', 'jpeg', 'png', 'gif'],
    required this.inputLabel,
    this.isError = false,
    this.messageError,
  }) : super(key: key);

  final List<File> files;
  final void Function(List<File> files) onChange;
  final bool? allowMultiple;
  final List<String>? allowedExtensions;
  final String inputLabel;
  final bool? isError;
  final String? messageError;

  @override
  State<InputFile> createState() => _InputFileState();
}

class _InputFileState extends State<InputFile> {
  List<File> files = [];
  StreamController<List<File>> controller = StreamController();
  late Stream<List<File>> stream;

  void addFileToSink(List<File> addedFile) {
    controller.sink.add(files);
    files = addedFile;
  }

  void removeFile(File file) {
    final filtered = files.skipWhile((f) => f.hashCode == file.hashCode);
    controller.sink.add(filtered.toList());
    files = filtered.toList();
  }

  void close() {
    controller.close();
  }

  @override
  void initState() {
    super.initState();
    // tambahkan initial component file value
    files = widget.files;
    addFileToSink(files);
    // dapatkan stream dan listen ke onchange
    stream = controller.stream;
  }

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

  /// ketika user memilih menggunakan camera saat input file
  Future<void> pickFileFromCamera(BuildContext modalContext) async {
    final imagePicker = ImagePicker();

    final result = await imagePicker.pickImage(
      source: ImageSource.camera,
      preferredCameraDevice: CameraDevice.rear,
      imageQuality: 40,
    );

    if (result != null) {
      final pickedFile = File(result.path);
      if (widget.allowMultiple == true) {
        addFileToSink([...files, pickedFile]);
      }

      if (widget.allowMultiple == false) {
        addFileToSink([pickedFile]);
      }
    }
  }

  /// ketika user memilih menggunakan gallery saat input file
  Future<void> pickFileFromGallery(BuildContext modalContext) async {
    final result = await FilePicker.platform.pickFiles(
      allowMultiple: widget.allowMultiple!,
      type: FileType.custom,
      allowedExtensions: widget.allowedExtensions,
      allowCompression: true,
    );

    for (var file in result?.files ?? []) {
      final pickedFile = File(file.path);
      if (widget.allowMultiple == true) {
        addFileToSink([...files, pickedFile]);
      }

      if (widget.allowMultiple == false) {
        addFileToSink([pickedFile]);
      }
    }
  }

  @override
  Widget build(BuildContext context) {
    final theme = GolekTheme.of(context);

    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Container(
          decoration: BoxDecoration(
            border: Border.all(
              color: Colors.transparent,
              width: 3,
            ),
          ),
          width: 335,
          child: IntrinsicHeight(
            child: DashedRect(
              color: widget.isError!
                  ? theme.dangerMainColor // jika error dan touched
                  : theme.neutral50Color,
              strokeWidth: 2.0,
              gap: 3.0,
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  const SizedBox(height: 21),
                  OutlinedButton(
                    onPressed: () => showModalFileToPick(
                      context: context,
                      onPickCamera: (context) async {
                        await pickFileFromCamera(context);
                        Navigator.of(context).pop();
                      },
                      onPickGallery: (context) async {
                        await pickFileFromGallery(context);
                        Navigator.of(context).pop();
                      },
                    ),
                    style: OutlinedButton.styleFrom(
                      side: BorderSide(
                        width: 1,
                        color: theme.primaryMainColor,
                      ),
                      backgroundColor: Colors.transparent,
                      shape: RoundedRectangleBorder(
                        borderRadius: BorderRadius.circular(6.0),
                      ),
                    ),
                    child: Text(
                      'Upload Foto\u{002A}',
                      style: theme.textStyle.copyWith(
                        fontSize: FontSize.style14,
                        color: theme.primaryMainColor,
                      ),
                    ),
                  ),
                  const SizedBox(height: 10),
                  StreamBuilder(
                    stream: stream,
                    builder: (context, snapshot) {
                      widget.onChange.call(files);
                      return ListFilesBuilder(
                        files: files,
                        multiple: widget.allowMultiple!,
                        onRemoveFile: removeFile,
                      );
                    },
                  ),
                  Text(
                    'Maks. 1 Foto, 1 Foto Maks. 2 mb',
                    style: theme.textStyle.copyWith(
                      fontSize: FontSize.style14,
                      color: theme.primaryMainColor,
                    ),
                  ),
                  const SizedBox(height: 38),
                ],
              ),
            ),
          ),
        ),
        ErrorMessageBuilder(
          inputLabel: widget.inputLabel,
          messageError: widget.messageError ?? '',
        )
      ],
    );
  }
}

// stateless widget tampilan user files yang telah diinput
class ListFilesBuilder extends StatelessWidget {
  final List<File> files;
  final bool multiple;
  final Function(File file) onRemoveFile;

  const ListFilesBuilder({
    Key? key,
    required this.files,
    required this.multiple,
    required this.onRemoveFile,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final theme = GolekTheme.of(context);
    return Expanded(
      child: Wrap(
        runSpacing: 4,
        spacing: 4,
        alignment: WrapAlignment.center,
        children: List.generate(files.length, (index) {
          var file = files[index];

          return Column(children: [
            Visibility(
              visible: multiple == false,
              child: Container(
                margin: const EdgeInsets.all(10),
                child: ClipRRect(
                  borderRadius: BorderRadius.circular(6),
                  child: ExtendedImage.file(
                    file,
                    height: 105,
                    width: 150,
                    enableMemoryCache: false,
                    clearMemoryCacheIfFailed: true,
                    clearMemoryCacheWhenDispose: true,
                  ),
                ),
              ),
            ),
            Visibility(
              visible: multiple == true,
              child: Stack(
                children: [
                  Container(
                    margin: const EdgeInsets.all(10),
                    child: ClipRRect(
                      borderRadius: BorderRadius.circular(6),
                      child: ExtendedImage.file(
                        file,
                        height: 105,
                        width: 150,
                        enableMemoryCache: false,
                        clearMemoryCacheIfFailed: true,
                        clearMemoryCacheWhenDispose: true,
                      ),
                    ),
                  ),
                  GestureDetector(
                    onTap: () => onRemoveFile(file),
                    child: Container(
                      decoration: BoxDecoration(
                        color: theme.dangerMainColor,
                        borderRadius: BorderRadius.circular(40),
                      ),
                      child: Icon(
                        Icons.remove,
                        color: theme.neutral10Color,
                      ),
                    ),
                  )
                ],
              ),
            ),
            Padding(
              padding: const EdgeInsets.symmetric(horizontal: 10),
              child: Text(
                ((file.path).split('/').last),
                textAlign: TextAlign.center,
              ),
            ),
          ]);
        }),
      ),
    );
  }
}

// modal untuk memilih user akan menggunakan kamera atau gallery
void showModalFileToPick({
  required BuildContext context,
  required Future<void> Function(BuildContext modalContext) onPickCamera,
  required Future<void> Function(BuildContext modalContext) onPickGallery,
}) {
  final theme = GolekTheme.of(context);
  FocusScope.of(context).requestFocus(FocusNode());
  showModalBottomSheet(
    context: context,
    barrierColor: const Color.fromRGBO(196, 196, 196, 0.3),
    isScrollControlled: true,
    backgroundColor: Colors.transparent,
    builder: (BuildContext modalContext) {
      return ConstrainedBox(
        constraints: const BoxConstraints(minHeight: 150),
        child: Container(
          width: double.infinity,
          decoration: const BoxDecoration(
            borderRadius: BorderRadius.only(
              topLeft: Radius.circular(25.0),
              topRight: Radius.circular(25.0),
            ),
            color: Colors.white,
          ),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            mainAxisSize: MainAxisSize.min,
            children: [
              const SizedBox(height: 10),
              Align(
                alignment: Alignment.topCenter,
                child: Container(
                  width: 60,
                  height: 6,
                  decoration: BoxDecoration(
                    borderRadius: BorderRadius.circular(20),
                    color: const Color.fromRGBO(196, 196, 196, 1),
                  ),
                ),
              ),
              const SizedBox(height: 15),
              Row(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Column(
                    children: [
                      const SizedBox(height: 15),
                      GestureDetector(
                        onTap: () => onPickGallery.call(modalContext),
                        child: Icon(
                          Icons.folder,
                          color: theme.primaryMainColor,
                          size: 50.25,
                        ),
                      ),
                      Text(
                        'File',
                        style: theme.textStyle.copyWith(
                          fontSize: FontSize.style16,
                          fontWeight: FontWeight.w600,
                        ),
                      )
                    ],
                  ),
                  const SizedBox(width: 107.9),
                  Column(
                    children: [
                      const SizedBox(height: 15),
                      GestureDetector(
                        onTap: () => onPickCamera.call(modalContext),
                        child: Icon(
                          Icons.camera_alt,
                          color: theme.primaryMainColor,
                          size: 50.25,
                        ),
                      ),
                      Text(
                        'Kamera',
                        style: theme.textStyle.copyWith(
                          fontSize: FontSize.style16,
                          fontWeight: FontWeight.w600,
                        ),
                      ),
                    ],
                  )
                ],
              ),
              const SizedBox(height: 52),
            ],
          ),
        ),
      );
    },
  );
}
