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

import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:twonly/locator.dart';
import 'package:twonly/src/database/twonly.db.dart';
import 'package:twonly/src/utils/avatars.dart';
import 'package:twonly/src/utils/log.dart';
import 'package:vector_graphics/vector_graphics.dart';

class AvatarIcon extends StatefulWidget {
  const AvatarIcon({
    super.key,
    this.group,
    this.contactId,
    this.myAvatar = false,
    this.fontSize = 20,
    this.svg,
    this.color,
  });
  final Group? group;
  final int? contactId;
  final bool myAvatar;
  final double? fontSize;
  final String? svg;
  final Color? color;

  @override
  State<AvatarIcon> createState() => _AvatarIconState();
}

class _AvatarIconState extends State<AvatarIcon> {
  List<Contact> _avatarContacts = [];
  String? _myAvatarPath;

  StreamSubscription<List<Contact>>? groupStream;
  StreamSubscription<List<Contact>>? contactsStream;
  StreamSubscription<Contact?>? contactStream;
  StreamSubscription<void>? _userSub;

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

  @override
  void dispose() {
    groupStream?.cancel();
    contactStream?.cancel();
    contactsStream?.cancel();
    _userSub?.cancel();
    super.dispose();
  }

  Widget errorBuilder(_, _, _) {
    return const SvgPicture(
      AssetBytesLoader('assets/images/default_avatar.svg.vec'),
    );
  }

  Widget getAvatarForContact(Contact contact) {
    final avatarFile = avatarPNGFile(contact.userId);
    if (avatarFile.existsSync()) {
      return Image.file(
        avatarFile,
        errorBuilder: errorBuilder,
      );
    }

    Log.warn(
      'PNG avatar file for contact ${contact.userId} does not exist. Generating in background.',
    );
    unawaited(createPushAvatars(forceForUserId: contact.userId));

    if (contact.avatarSvgCompressed != null) {
      return SvgPicture.string(
        getAvatarSvg(contact.avatarSvgCompressed!),
        errorBuilder: errorBuilder,
      );
    }
    return errorBuilder(null, null, null);
  }

  Future<void> initAsync() async {
    if (widget.group != null) {
      groupStream = twonlyDB.groupsDao
          .watchGroupContact(widget.group!.groupId)
          .listen((contacts) {
            _avatarContacts = [];
            if (contacts.length == 1) {
              if (contacts.first.avatarSvgCompressed != null) {
                _avatarContacts.add(contacts.first);
              }
            } else {
              for (final contact in contacts) {
                if (contact.avatarSvgCompressed != null) {
                  _avatarContacts.add(contact);
                }
              }
            }
            setState(() {});
          });
    } else if (widget.myAvatar) {
      _userSub = userService.onUserUpdated.listen((_) {
        unawaited(_updateMyAvatar());
      });
      unawaited(_updateMyAvatar());
    } else if (widget.contactId != null) {
      contactStream = twonlyDB.contactsDao
          .watchContact(widget.contactId!)
          .listen((contact) {
            if (contact != null && contact.avatarSvgCompressed != null) {
              _avatarContacts = [contact];
              setState(() {});
            }
          });
    }
    if (mounted) setState(() {});
  }

  Future<void> _updateMyAvatar() async {
    final avatarSvg = userService.currentUser.avatarSvg;
    if (avatarSvg == null) {
      if (mounted) {
        setState(() {
          _myAvatarPath = null;
          _avatarContacts = [];
        });
      }
      return;
    }

    final path = await getUserAvatar();

    if (mounted) {
      setState(() {
        _myAvatarPath = path;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    final proSize = (widget.fontSize == null) ? 40 : (widget.fontSize! * 2);

    Widget avatars = Container();

    if (widget.svg != null) {
      avatars = SvgPicture.string(
        widget.svg!,
        errorBuilder: errorBuilder,
      );
    } else if (widget.myAvatar) {
      if (_myAvatarPath != null) {
        avatars = Image.file(
          File(_myAvatarPath!),
          errorBuilder: errorBuilder,
        );
      } else {
        avatars = const SvgPicture(
          AssetBytesLoader('assets/images/default_avatar.svg.vec'),
        );
      }
    } else if (_avatarContacts.length == 1) {
      avatars = getAvatarForContact(_avatarContacts.first);
    } else if (_avatarContacts.length >= 2) {
      final a = getAvatarForContact(_avatarContacts.first);
      final b = getAvatarForContact(_avatarContacts[1]);
      if (_avatarContacts.length >= 3) {
        final c = getAvatarForContact(_avatarContacts[2]);
        avatars = Stack(
          children: [
            Transform.translate(
              offset: const Offset(-15, 5),
              child: Transform.scale(
                scale: 0.8,
                child: c,
              ),
            ),
            Transform.translate(
              offset: const Offset(15, 5),
              child: Transform.scale(
                scale: 0.8,
                child: b,
              ),
            ),
            a,
          ],
        );
      } else {
        avatars = Stack(
          children: [
            Transform.translate(
              offset: const Offset(-10, 5),
              child: Transform.scale(
                scale: 0.8,
                child: b,
              ),
            ),
            Transform.translate(offset: const Offset(10, 0), child: a),
          ],
        );
      }
    } else {
      avatars = const SvgPicture(
        AssetBytesLoader('assets/images/default_avatar.svg.vec'),
      );
    }

    return Container(
      constraints: BoxConstraints(
        minHeight: 2 * (widget.fontSize ?? 20),
        minWidth: 2 * (widget.fontSize ?? 20),
        maxWidth: 2 * (widget.fontSize ?? 20),
        maxHeight: 2 * (widget.fontSize ?? 20),
      ),
      child: Center(
        child: ClipRRect(
          borderRadius: BorderRadius.circular(12),
          child: Container(
            height: proSize as double,
            width: proSize,
            color: widget.color,
            child: Center(child: avatars),
          ),
        ),
      ),
    );
  }
}
