// ignore_for_file: deprecated_member_use

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

import 'package:didvan/config/design_config.dart';
import 'package:didvan/config/theme_data.dart';
import 'package:didvan/constants/app_icons.dart';
import 'package:didvan/models/ai/bots_model.dart';
import 'package:didvan/models/ai/chats_model.dart';
import 'package:didvan/models/ai/files_model.dart';
import 'package:didvan/models/ai/messages_model.dart';
import 'package:didvan/services/media/media.dart';
import 'package:didvan/services/media/voice.dart';
import 'package:didvan/utils/action_sheet.dart';
import 'package:didvan/utils/date_time.dart';
import 'package:didvan/utils/extension.dart';
import 'package:didvan/views/ai/ai_chat_state.dart';
import 'package:didvan/views/ai/history_ai_chat_state.dart';
import 'package:didvan/views/ai/widgets/audio_wave.dart';
import 'package:didvan/views/ai/widgets/message_bar_btn.dart';
import 'package:didvan/views/widgets/animated_visibility.dart';
import 'package:didvan/views/widgets/didvan/text.dart';
import 'package:didvan/views/widgets/marquee_text.dart';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:get/get.dart';
import 'package:image_cropper/image_cropper.dart';
import 'package:image_picker/image_picker.dart';
import 'package:path_provider/path_provider.dart';
import 'package:persian_number_utility/persian_number_utility.dart';
import 'package:provider/provider.dart';
import 'package:record/record.dart';

import 'package:path/path.dart' as p;

class AiMessageBarIOS extends StatefulWidget {
  final BotsModel bot;
  final String? assistantsName;

  const AiMessageBarIOS({
    super.key,
    required this.bot,
    this.assistantsName,
  });

  @override
  State<AiMessageBarIOS> createState() => _AiMessageBarIOSState();
}

class _AiMessageBarIOSState extends State<AiMessageBarIOS> {
  final ValueNotifier<String> messageText = ValueNotifier('');
  bool openAttach = false;
  String? path;
  late HistoryAiChatState historyState = context.read<HistoryAiChatState>();

  @override
  void initState() {
    super.initState();
  }

  final record = AudioRecorder();

  @override
  void dispose() {
    super.dispose();
    record.dispose();
    try {
      _timer.cancel();
    } catch (e) {
      e.printError();
    }
  }

  late Timer _timer;
  final ValueNotifier<Duration> _countTimer = ValueNotifier(Duration.zero);
  void startTimer() {
    const oneSec = Duration(seconds: 1);
    _timer = Timer.periodic(
      oneSec,
      (Timer timer) {
        _countTimer.value = Duration(seconds: _countTimer.value.inSeconds + 1);
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return Consumer<AiChatState>(
      builder: (context, state, child) {
        return Container(
          padding: const EdgeInsets.fromLTRB(12, 24, 12, 0).copyWith(
              top: (state.file != null && !state.file!.isRecorded) ? 0 : 24),
          decoration: BoxDecoration(
            color: Theme.of(context).colorScheme.background,
          ),
          child: Column(
            children: [
              if (state.file != null && !(state.file!.isRecorded))
                fileContainer(),
              Stack(
                children: [
                  Container(
                    // height: 50,
                    decoration: BoxDecoration(
                        boxShadow: DesignConfig.defaultShadow,
                        color: Theme.of(context).colorScheme.surface,
                        border: Border.all(
                            color: Theme.of(context).colorScheme.border),
                        borderRadius: DesignConfig.highBorderRadius),
                    child: Row(
                      children: [
                        const SizedBox(
                          width: 8,
                        ),
                        Expanded(
                          child: StreamBuilder<RecordState>(
                              stream: record.onStateChanged(),
                              builder: (context, snapshot) {
                                return ValueListenableBuilder(
                                    valueListenable: messageText,
                                    builder: (context, value, child) {
                                      return Row(
                                        crossAxisAlignment:
                                            CrossAxisAlignment.end,
                                        children: [
                                          Padding(
                                            padding: const EdgeInsets.only(
                                                bottom: 8.0),
                                            child: (
                                                    // !kIsWeb &&
                                                    snapshot.hasData &&
                                                        snapshot.data! !=
                                                            RecordState.stop)
                                                ? MessageBarBtn(
                                                    enable: true,
                                                    icon: DidvanIcons
                                                        .stop_circle_solid,
                                                    click: () async {
                                                      path =
                                                          await record.stop();

                                                      Duration? duration =
                                                          await VoiceService
                                                              .getDuration(
                                                                  src: path ??
                                                                      '');

                                                      state.file = FilesModel(
                                                          path.toString(),
                                                          name:
                                                              '${DateTime.now().millisecondsSinceEpoch ~/ 1000}.m4a',
                                                          isRecorded: true,
                                                          audio: true,
                                                          image: false,
                                                          duration: duration);
                                                      _timer.cancel();

                                                      state.update();
                                                    },
                                                  )
                                                :
                                                // (!kIsWeb &&
                                                //             !Platform
                                                //                 .isIOS) &&
                                                widget.bot.attachmentType!
                                                            .contains(
                                                                'audio') &&
                                                        value.isEmpty &&
                                                        state.file == null &&
                                                        widget.bot.attachment !=
                                                            0
                                                    ? MessageBarBtn(
                                                        enable: true,
                                                        icon: DidvanIcons
                                                            .mic_regular,
                                                        click: () async {
                                                          if (await record
                                                              .hasPermission()) {
                                                            try {
                                                              String path =
                                                                  '${DateTime.now().millisecondsSinceEpoch ~/ 1000}.m4a';
                                                              //
                                                              if (!kIsWeb) {
                                                                Directory?
                                                                    downloadDir =
                                                                    await getApplicationDocumentsDirectory();
                                                                path = p.join(
                                                                    downloadDir
                                                                        .path,
                                                                    '${DateTime.now().millisecondsSinceEpoch ~/ 1000}.m4a');
                                                              }
                                                              setState(
                                                                () {
                                                                  openAttach =
                                                                      false;
                                                                },
                                                              );
                                                              record.start(
                                                                  const RecordConfig(),
                                                                  path: path);
                                                              startTimer();
                                                            } catch (e) {
                                                              if (kDebugMode) {
                                                                print(
                                                                    'Error starting recording: $e');
                                                              }
                                                            }
                                                          }
                                                        },
                                                      )
                                                    : MessageBarBtn(
                                                        enable: (state
                                                                        .file !=
                                                                    null &&
                                                                state.file!
                                                                    .isRecorded) ||
                                                            (widget.bot
                                                                    .attachment ==
                                                                1) ||
                                                            value.isNotEmpty,
                                                        icon: DidvanIcons
                                                            .send_light,
                                                        click: () async {
                                                          if ((state.file ==
                                                                      null ||
                                                                  !state.file!
                                                                      .isRecorded) &&
                                                              (widget.bot
                                                                      .attachment !=
                                                                  1) &&
                                                              value.isEmpty) {
                                                            return;
                                                          }

                                                          if (state.messages
                                                                  .isNotEmpty &&
                                                              DateTime.parse(state
                                                                      .messages
                                                                      .last
                                                                      .dateTime)
                                                                  .toPersianDateStr()
                                                                  .contains(DateTime.parse(DateTime
                                                                              .now()
                                                                          .subtract(
                                                                              const Duration(minutes: 210))
                                                                          .toIso8601String())
                                                                      .toPersianDateStr())) {
                                                            state.messages.last
                                                                .prompts
                                                                .add(Prompts(
                                                              error: false,
                                                              text: state
                                                                  .message.text
                                                                  .replaceAll(
                                                                      r"\n",
                                                                      r" \n \n "),
                                                              file: state
                                                                  .file?.path,
                                                              fileName: state
                                                                  .file?.name,
                                                              fileLocal:
                                                                  state.file,
                                                              finished: true,
                                                              role: 'user',
                                                              createdAt: DateTime
                                                                      .now()
                                                                  .subtract(
                                                                      const Duration(
                                                                          minutes:
                                                                              210))
                                                                  .toIso8601String(),
                                                            ));
                                                          } else {
                                                            state.messages.add(MessageModel(
                                                                dateTime: DateTime
                                                                        .now()
                                                                    .subtract(const Duration(
                                                                        minutes:
                                                                            210))
                                                                    .toIso8601String(),
                                                                prompts: [
                                                                  Prompts(
                                                                    error:
                                                                        false,
                                                                    text: state
                                                                        .message
                                                                        .text
                                                                        .replaceAll(
                                                                            r"\n",
                                                                            r" \n \n "),
                                                                    finished:
                                                                        true,
                                                                    file: state
                                                                        .file
                                                                        ?.path,
                                                                    fileName: state
                                                                        .file
                                                                        ?.name,
                                                                    fileLocal:
                                                                        state
                                                                            .file,
                                                                    role:
                                                                        'user',
                                                                    createdAt: DateTime
                                                                            .now()
                                                                        .subtract(const Duration(
                                                                            minutes:
                                                                                210))
                                                                        .toIso8601String(),
                                                                  )
                                                                ]));
                                                          }
                                                          state.message.clear();
                                                          messageText.value =
                                                              state
                                                                  .message.text;
                                                          await state.postMessage(
                                                              widget.bot,
                                                              widget.assistantsName !=
                                                                  null);
                                                        },
                                                      ),
                                          ),
                                          Expanded(
                                            child: Padding(
                                              padding:
                                                  const EdgeInsets.symmetric(
                                                horizontal: 8.0,
                                              ),
                                              child: snapshot.hasData &&
                                                      (snapshot.data! ==
                                                              RecordState
                                                                  .record ||
                                                          snapshot.data! ==
                                                              RecordState.pause)
                                                  ? Padding(
                                                      padding:
                                                          const EdgeInsets.all(
                                                              8.0),
                                                      child: Row(
                                                        mainAxisAlignment:
                                                            MainAxisAlignment
                                                                .spaceBetween,
                                                        children: [
                                                          Directionality(
                                                            textDirection:
                                                                TextDirection
                                                                    .ltr,
                                                            child: Row(
                                                                mainAxisAlignment:
                                                                    MainAxisAlignment
                                                                        .center,
                                                                children: List.generate(
                                                                    4,
                                                                    (index) => snapshot.data! == RecordState.pause
                                                                        ? Row(
                                                                            mainAxisAlignment:
                                                                                MainAxisAlignment.center,
                                                                            children: List.generate(
                                                                                8,
                                                                                (index) => Padding(
                                                                                      padding: const EdgeInsets.symmetric(horizontal: 1.0, vertical: 12),
                                                                                      child: Container(
                                                                                        width: 3,
                                                                                        height: 8,
                                                                                        decoration: BoxDecoration(color: Theme.of(context).colorScheme.primary.withOpacity(0.4)),
                                                                                      ),
                                                                                    )),
                                                                          )
                                                                        : SpinKitWave(
                                                                            color:
                                                                                Theme.of(context).colorScheme.primary.withOpacity(0.4),
                                                                            size:
                                                                                32,
                                                                            itemCount:
                                                                                10,
                                                                          ))),
                                                          ),
                                                          ValueListenableBuilder<
                                                              Duration>(
                                                            valueListenable:
                                                                _countTimer,
                                                            builder: (context,
                                                                    value,
                                                                    child) =>
                                                                DidvanText(DateTimeUtils
                                                                    .normalizeTimeDuration(
                                                                        value)),
                                                          ),
                                                        ],
                                                      ),
                                                    )
                                                  : state.file != null &&
                                                          state.file!.isRecorded
                                                      ? audioContainer()
                                                      : Form(
                                                          child: Directionality(
                                                          textDirection: state
                                                                  .message.text
                                                                  .toString()
                                                                  .startsWithEnglish()
                                                              ? TextDirection
                                                                  .ltr
                                                              : TextDirection
                                                                  .rtl,
                                                          child: TextFormField(
                                                            textInputAction:
                                                                TextInputAction
                                                                    .newline,
                                                            style: Theme.of(
                                                                    context)
                                                                .textTheme
                                                                .bodyMedium,
                                                            minLines: 1,
                                                            maxLines:
                                                                6, // Set this
                                                            // expands: true, //
                                                            // keyboardType: TextInputType.text,
                                                            keyboardType:
                                                                TextInputType
                                                                    .multiline,
                                                            controller:
                                                                state.message,

                                                            enabled: !(state
                                                                        .file !=
                                                                    null &&
                                                                widget.bot
                                                                        .attachment ==
                                                                    1),

                                                            decoration:
                                                                InputDecoration(
                                                              border:
                                                                  InputBorder
                                                                      .none,
                                                              hintText:
                                                                  'بنویسید...',
                                                              hintStyle: Theme.of(
                                                                      context)
                                                                  .textTheme
                                                                  .bodySmall!
                                                                  .copyWith(
                                                                      color: Theme.of(
                                                                              context)
                                                                          .colorScheme
                                                                          .disabledText),
                                                              suffixIcon: state
                                                                      .isEdite
                                                                  ? InkWell(
                                                                      onTap:
                                                                          () {
                                                                        state.isEdite =
                                                                            false;
                                                                        state
                                                                            .update();
                                                                      },
                                                                      child: const Icon(
                                                                          DidvanIcons
                                                                              .close_circle_solid),
                                                                    )
                                                                  : const SizedBox(),
                                                            ),

                                                            onChanged: (value) {
                                                              messageText
                                                                      .value =
                                                                  value;
                                                              state.update();
                                                            },
                                                          ),
                                                        )),
                                            ),
                                          ),
                                          if (snapshot.hasData)
                                            Padding(
                                              padding: const EdgeInsets.only(
                                                  bottom: 8.0),
                                              child: snapshot.data! ==
                                                      RecordState.record
                                                  ? MessageBarBtn(
                                                      enable: false,
                                                      icon: DidvanIcons
                                                          .pause_solid,
                                                      click: () async {
                                                        await record.pause();
                                                        _timer.cancel();
                                                      },
                                                    )
                                                  : snapshot.data! ==
                                                          RecordState.pause
                                                      ? MessageBarBtn(
                                                          enable: false,
                                                          icon: DidvanIcons
                                                              .play_solid,
                                                          click: () async {
                                                            await record
                                                                .resume();
                                                            startTimer();
                                                          },
                                                        )
                                                      : const SizedBox(),
                                            ),
                                          const SizedBox(
                                            width: 8,
                                          ),
                                          Padding(
                                            padding: const EdgeInsets.only(
                                                bottom: 8.0),
                                            child: attachmentLayout(
                                                state, context),
                                          ),
                                          if (!snapshot.hasData ||
                                              (snapshot.hasData &&
                                                  snapshot.data ==
                                                      RecordState.stop))
                                            Padding(
                                              padding:
                                                  const EdgeInsets.fromLTRB(
                                                      12, 0, 12, 8),
                                              child: state.file != null ||
                                                      openAttach
                                                  ? MessageBarBtn(
                                                      click: () {
                                                        if (openAttach) {
                                                          setState(() {
                                                            openAttach =
                                                                !openAttach;
                                                          });
                                                          return;
                                                        }
                                                        state.file = null;
                                                        _countTimer.value =
                                                            Duration.zero;
                                                        state.update();
                                                      },
                                                      enable: false,
                                                      icon: DidvanIcons
                                                          .close_solid)
                                                  : widget.bot.attachmentType!
                                                          .isNotEmpty
                                                      ? MessageBarBtn(
                                                          click: () {
                                                            setState(() {
                                                              openAttach =
                                                                  !openAttach;
                                                            });
                                                          },
                                                          enable: false,
                                                          icon: Icons
                                                              .add,
                                                        )
                                                      : const SizedBox(),
                                            ),
                                        ],
                                      );
                                    });
                              }),
                        ),
                      ],
                    ),
                  ),
                  if (state.onResponsing)
                    Positioned.fill(
                      child: Container(
                        decoration: BoxDecoration(
                            color: Theme.of(context)
                                .colorScheme
                                .focused
                                .withOpacity(0.5)),
                        child: Center(
                          child: SpinKitThreeBounce(
                            color: Theme.of(context).colorScheme.primary,
                            size: 32,
                          ),
                        ),
                      ),
                    )
                ],
              ),
              MediaQuery.of(context).viewInsets.bottom == 0
                  ? const Padding(
                      padding: EdgeInsets.fromLTRB(8, 8, 8, 4),
                      child: DidvanText(
                        'مدل‌های هوش مصنوعی می‌توانند اشتباه کنند، صحت اطلاعات مهم را بررسی کنید.',
                        fontSize: 12,
                      ),
                    )
                  : const SizedBox(
                      height: 12,
                    ),
            ],
          ),
        );
      },
    );
  }

  Widget audioContainer() {
    final state = context.watch<AiChatState>();

    return SizedBox(
      width: MediaQuery.sizeOf(context).width,
      child: AudioWave(
        file: state.file!.path,
        loadingPaddingSize: 8.0,
        totalDuration: _countTimer.value,
      ),
    );
  }

  AnimatedVisibility attachmentLayout(AiChatState state, BuildContext context) {
    return AnimatedVisibility(
        isVisible: openAttach,
        fadeMode: FadeMode.horizontal,
        duration: DesignConfig.lowAnimationDuration,
        child: Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            if (historyState.bot!.attachmentType!.contains('pdf'))
              MessageBarBtn(
                enable: true,
                icon: CupertinoIcons.doc_fill,
                click: () async {
                  MediaService.onLoadingPickFile(context);
                  FilePickerResult? result = await MediaService.pickPdfFile();
                  if (result != null) {
                    Uint8List? bytes =
                        result.files.first.bytes; // Access the bytes property
                    String? name = result.files.first.name;
                    if (kIsWeb) {
                      // Store bytes and file name directly in your state or model
                      state.file = FilesModel(
                        '', // No need for a file path on web
                        name: name,
                        bytes: bytes,
                        audio: false,
                        image: false,
                      );
                    } else {
                      state.file = FilesModel(result.files.single.path!,
                          name: name, audio: false, image: false);
                    }
                  }
                  Future.delayed(
                    Duration.zero,
                    () => ActionSheetUtils(context).pop(),
                  );
                  openAttach = !openAttach;

                  state.update();
                },
              ),
            if (historyState.bot!.attachmentType!.contains('image'))
              Padding(
                padding: const EdgeInsets.symmetric(horizontal: 8.0),
                child: MessageBarBtn(
                  enable: true,
                  icon: CupertinoIcons.photo,
                  click: () async {
                    MediaService.onLoadingPickFile(context);

                    final pickedFile = await MediaService.pickImage(
                        source: ImageSource.gallery);
                    CroppedFile? file;
                    if (pickedFile != null && !kIsWeb) {
                      file = await ImageCropper().cropImage(
                        sourcePath: pickedFile.path,
                        uiSettings: [
                          AndroidUiSettings(toolbarTitle: 'برش تصویر'),
                          IOSUiSettings(
                            title: 'برش تصویر',
                            doneButtonTitle: 'تایید',
                            cancelButtonTitle: 'بازگشت',
                          )
                        ],
                        compressQuality: 30,
                      );

                      if (file == null) {
                        await Future.delayed(
                          Duration.zero,
                          () => ActionSheetUtils(context).pop(),
                        );

                        return;
                      }
                    }
                    if (pickedFile == null) {
                      await Future.delayed(
                        Duration.zero,
                        () => ActionSheetUtils(context).pop(),
                      );

                      return;
                    }
                    state.file = kIsWeb
                        ? FilesModel(pickedFile.path,
                            name: pickedFile.name, image: true, audio: false)
                        : FilesModel(file!.path, image: true, audio: false);
                    await Future.delayed(
                      Duration.zero,
                      () => ActionSheetUtils(context).pop(),
                    );
                    openAttach = !openAttach;

                    state.update();
                  },
                ),
              ),
            // if (!kIsWeb && !Platform.isIOS)
            if (historyState.bot!.attachmentType!.contains('audio'))
              MessageBarBtn(
                enable: true,
                icon: CupertinoIcons.music_note_2,
                click: () async {
                  MediaService.onLoadingPickFile(context);

                  FilePickerResult? result = await MediaService.pickAudioFile();
                  if (result != null) {
                    if (kIsWeb) {
                      Uint8List? bytes =
                          result.files.first.bytes; // Access the bytes property
                      String? name = result.files.first.name;

                      state.file = FilesModel(
                        '', // No need for a file path on web
                        name: name,
                        bytes: bytes,
                        audio: true,
                        image: false,
                      );
                    } else {
                      state.file = FilesModel(result.files.single.path!,
                          audio: true, image: false);
                    }
                  }
                  await Future.delayed(
                    Duration.zero,
                    () => ActionSheetUtils(context).pop(),
                  );
                  openAttach = !openAttach;

                  state.update();
                },
              )
          ],
        ));
  }

  Widget fileContainer() {
    final state = context.watch<AiChatState>();
    return Container(
      decoration: BoxDecoration(
        borderRadius: DesignConfig.mediumBorderRadius,
        color: Theme.of(context).colorScheme.border,
      ),
      margin: const EdgeInsets.fromLTRB(4, 4, 4, 8),
      padding: const EdgeInsets.fromLTRB(12, 8, 12, 8),
      child: Row(
        children: [
          state.file != null && state.file!.isImage()
              ? SizedBox(
                  width: 32,
                  height: 42,
                  child: ClipRRect(
                      borderRadius: DesignConfig.lowBorderRadius,
                      child: state.file!.isNetwork()
                          ? Image.network(
                              state.file!.path,
                              fit: BoxFit.cover,
                            )
                          : Image.file(
                              state.file!.main,
                              fit: BoxFit.cover,
                            )))
              : const Icon(Icons.file_copy),
          const SizedBox(
            width: 12,
          ),
          Expanded(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                SizedBox(
                  height: 24,
                  child: MarqueeText(
                    text: state.file != null ? state.file!.name! : '',
                    style: const TextStyle(fontSize: 14),
                    stop: const Duration(seconds: 3),
                  ),
                ),
                if (state.file != null && !kIsWeb)
                  FutureBuilder(
                      future: state.file!.main.length(),
                      builder: (context, snapshot) {
                        if (!snapshot.hasData) {
                          return const SizedBox();
                        }
                        return DidvanText(
                          'File Size ${(snapshot.data! / 1000).round()} KB',
                          fontSize: 12,
                        );
                      })
              ],
            ),
          )
        ],
      ),
    );
  }
}
