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

import 'package:flutter/material.dart';
import 'package:maid/classes/providers/artificial_intelligence.dart';
import 'package:maid/classes/providers/large_language_models/llama_cpp_model.dart';
import 'package:maid/classes/providers/sessions.dart';
import 'package:maid/enumerators/chat_role.dart';
import 'package:maid/enumerators/large_language_model_type.dart';
import 'package:maid/classes/providers/session.dart';
import 'package:maid/ui/shared/dialogs/missing_requirements_dialog.dart';
import 'package:maid/classes/static/logger.dart';
import 'package:provider/provider.dart';
import 'package:receive_sharing_intent/receive_sharing_intent.dart';

class ChatField extends StatefulWidget {
  const ChatField({super.key});

  @override
  State<ChatField> createState() => _ChatFieldState();
}

class _ChatFieldState extends State<ChatField> {
  final TextEditingController _promptController = TextEditingController();
  StreamSubscription? _intentDataStreamSubscription;

  @override
  void initState() {
    super.initState();
    if (Platform.isAndroid || Platform.isIOS) {
      // For sharing or opening text coming from outside the app while the app is in the memory
      _intentDataStreamSubscription =
          ReceiveSharingIntent.instance.getMediaStream().listen((value) {
        setState(() {
          _promptController.text = value.first.path;
        });
      }, onError: (err) {
        Logger.log("Error: $err");
      });

      // For sharing or opening text coming from outside the app while the app is closed
      ReceiveSharingIntent.instance.getInitialMedia().then((value) {
        if (value.isNotEmpty) {
          setState(() {
            _promptController.text = value.first.path;
          });
        }
      });
    }
  }

  @override
  void dispose() {
    _intentDataStreamSubscription?.cancel();
    super.dispose();
  }

  void send() async {
    if (Platform.isAndroid || Platform.isIOS) {
      FocusScope.of(context).unfocus();
    }

    final session = Session.of(context);

    
    session.chat.add(
      content: _promptController.text.trim(), 
      role: ChatRole.user
    );

    session.chat.add(
      role: ChatRole.assistant
    );

    session.notify();

    session.prompt(context);

    setState(() {
      _promptController.clear();
    });
  }

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      minimum: const EdgeInsets.all(8.0),
      child: _buildRow(),
    );
  }

  Widget _buildRow() {
    return Consumer2<Sessions, ArtificialIntelligence>(
      builder: (context, sessions, ai, child) {
        return Row(
          children: [
            if (!sessions.current.chat.tail.finalised &&
                ai.llm.type == LargeLanguageModelType.llamacpp)
              Semantics(
                label: 'Stop button',
                hint: 'Double tap to stop inference.',
                excludeSemantics: true,
                child: IconButton(
                  onPressed: (ai.llm as LlamaCppModel).stop,
                  iconSize: 50,
                  icon: const Icon(
                    Icons.stop_circle_sharp,
                    color: Colors.red,
                  )
                ),
              ),
            Expanded(
              child: Semantics(
                label: 'Prompt text field',
                hint: 'Text to be sent to the model for a response.',
                excludeSemantics: true,
                child: TextField(
                  keyboardType: TextInputType.multiline,
                  minLines: 1,
                  maxLines: 9,
                  enableInteractiveSelection: true,
                  controller: _promptController,
                  cursorColor: Theme.of(context).colorScheme.secondary,
                  decoration: InputDecoration(
                    labelText: 'Prompt',
                    hintStyle: Theme.of(context).textTheme.labelSmall,
                  ),
                )
              ),
            ),
            Semantics(
              label: 'Prompt button',
              hint: 'Double tap to prompt the model for a response.',
              excludeSemantics: true,
              child: IconButton(
                onPressed: () {
                  if (ai.llm.missingRequirements.isNotEmpty) {
                    showDialog(
                      context: context,
                      builder: (context) {
                        return const MissingRequirementsDialog();
                      }
                    );
                  }
                  else if (sessions.current.chat.tail.finalised) {
                    send();
                  }
                },
                iconSize: 50,
                icon: Icon(
                  Icons.arrow_circle_right,
                  color: !sessions.current.chat.tail.finalised 
                      ? Theme.of(context).colorScheme.onPrimary
                      : Theme.of(context).colorScheme.secondary,
                )
              )
            )
          ],
        );
      }
    );
  }
}
