import 'dart:async';
import 'dart:typed_data';

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:image_picker/image_picker.dart';
import 'package:kasy_kit/components/kasy_avatar.dart';
import 'package:kasy_kit/core/data/entities/upload_result.dart';
import 'package:kasy_kit/core/data/models/user.dart';
import 'package:kasy_kit/core/data/repositories/user_repository.dart';
import 'package:kasy_kit/core/states/models/user_state.dart';
import 'package:kasy_kit/core/states/user_state_notifier.dart';
import 'package:kasy_kit/core/theme/theme.dart';
import 'package:kasy_kit/features/settings/ui/widgets/avatar_utils.dart';
import 'package:kasy_kit/features/settings/ui/widgets/round_progress.dart';
import 'package:kasy_kit/i18n/translations.g.dart';

/// Displays the user avatar using [KasyAvatar] with soft-icon fallback.
/// Tapping opens the gallery to upload a new photo.
/// Shows a circular progress ring and fade animation during upload.
class EditableUserAvatar extends ConsumerStatefulWidget {
  final OnAvatarTap? onTap;
  final double? diameter;

  const EditableUserAvatar({super.key, this.onTap, this.diameter});

  @override
  ConsumerState<EditableUserAvatar> createState() => _EditableUserAvatarState();
}

class _EditableUserAvatarState extends ConsumerState<EditableUserAvatar> {
  Uint8List? temporaryAvatarBytes;
  StreamSubscription<UploadResult>? _saveAvatarSubscription;
  double? uploadProgress;
  bool _isUploading = false;
  String? _optimisticAvatarUrl;

  ImageProvider? get _temporaryAvatarImage {
    final bytes = temporaryAvatarBytes;
    return bytes == null ? null : MemoryImage(bytes);
  }

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

  @override
  Widget build(BuildContext context) {
    final userState = ref.watch(userStateNotifierProvider);
    final userId = userState.user.idOrNull;
    final avatarPath = switch (userState.user) {
      AuthenticatedUserData(:final avatarPath) => avatarPath,
      _ => null,
    };
    final displayAvatarPath = _optimisticAvatarUrl ?? avatarPath;
    final double d = widget.diameter ?? KasyAvatarSize.medium.diameter;

    return GestureDetector(
      behavior: HitTestBehavior.opaque,
      onTap: userId != null && !_isUploading
          ? () => _onTapAvatar(context, userState, avatarPath)
          : null,
      child: Padding(
        padding: const EdgeInsets.all(6),
        child: Stack(
          clipBehavior: Clip.none,
          children: [
            _AvatarFadeAnimation(
              isUploading: _isUploading,
              child: _AvatarContent(
                diameter: d,
                localImage: _temporaryAvatarImage,
                userId: userId,
                avatarPath: displayAvatarPath,
              ),
            ),
            if (_isUploading)
              Positioned.fill(
                child: RoundProgress(
                  color: context.colors.primary.withValues(alpha: .6),
                  radius: d / 2,
                  progress: uploadProgress,
                ),
              ),
            Positioned(
              bottom: 0,
              right: 0,
              child: Container(
                width: 22,
                height: 22,
                decoration: const BoxDecoration(
                  color: Color(0x99000000),
                  shape: BoxShape.circle,
                ),
                child: const Icon(
                  KasyIcons.cameraAlt,
                  size: 12,
                  color: Colors.white,
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }

  Future<void> _onTapAvatar(
    BuildContext context,
    UserState userState,
    String? avatarPath,
  ) async {
    final userId = userState.user.idOrNull;
    final cachedUrl = userId == null ? null : getCachedAvatarUrl(userId);
    final hasAvatar =
        _hasAvatarUrl(avatarPath) ||
        _hasAvatarUrl(cachedUrl) ||
        temporaryAvatarBytes != null;
    final result = await _showAvatarBottomSheet(context, hasAvatar: hasAvatar);
    if (result == null || !mounted) return;
    switch (result) {
      case _AvatarAction.camera:
        final file = await ImagePicker().pickImage(source: ImageSource.camera);
        await _uploadTask(file, userState);
      case _AvatarAction.library:
        final file = await ImagePicker().pickImage(source: ImageSource.gallery);
        await _uploadTask(file, userState);
      case _AvatarAction.remove:
        await _removeAvatar(userState);
    }
  }

  Future<_AvatarAction?> _showAvatarBottomSheet(
    BuildContext context, {
    required bool hasAvatar,
  }) {
    return showModalBottomSheet<_AvatarAction>(
      context: context,
      useRootNavigator: true,
      backgroundColor: context.colors.surface,
      shape: const RoundedRectangleBorder(
        borderRadius: BorderRadius.vertical(top: Radius.circular(16)),
      ),
      builder: (sheetContext) => SafeArea(
        child: Padding(
          padding: const EdgeInsets.symmetric(vertical: KasySpacing.sm),
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              _BottomSheetTile(
                icon: KasyIcons.cameraAlt,
                label: t.settings.avatar.take_photo,
                onTap: () => Navigator.pop(sheetContext, _AvatarAction.camera),
              ),
              _BottomSheetTile(
                icon: KasyIcons.gallery,
                label: t.settings.avatar.choose_library,
                onTap: () => Navigator.pop(sheetContext, _AvatarAction.library),
              ),
              if (hasAvatar) ...[
                Divider(
                  color: sheetContext.colors.onSurface.withValues(alpha: .08),
                  height: 1,
                ),
                _BottomSheetTile(
                  icon: KasyIcons.trash,
                  label: t.settings.avatar.remove_photo,
                  color: sheetContext.colors.error,
                  onTap: () => Navigator.pop(sheetContext, _AvatarAction.remove),
                ),
              ],
            ],
          ),
        ),
      ),
    );
  }

  Future<void> _uploadTask(XFile? file, UserState userState) async {
    if (file == null) return;
    final userId = userState.user.idOrNull;
    if (userId == null) return;
    final bytes = await file.readAsBytes();
    if (!mounted) return;

    await _saveAvatarSubscription?.cancel();
    _saveAvatarSubscription = null;
    setState(() {
      temporaryAvatarBytes = bytes;
      uploadProgress = null;
      _isUploading = true;
      _optimisticAvatarUrl = null;
    });

    _saveAvatarSubscription = ref
        .read(userRepositoryProvider)
        .saveAvatar(userId: userId, data: bytes)
        .listen(
          (event) {
            switch (event) {
              case UploadResultProgress():
                _updateUploadProgress(event.progress);
              case UploadResultCompleted():
                _finishUpload(userId, event.imagePublicUrl);
            }
          },
          onError: (e, s) {
            _resetUploadState(clearPreview: true);
          },
          onDone: () => _resetUploadState(clearPreview: false),
          cancelOnError: true,
        );
  }

  void _finishUpload(String userId, String newUrl) {
    final oldUrl = getCachedAvatarUrl(userId);
    final version = DateTime.now().millisecondsSinceEpoch;
    final displayUrl = cacheBustedAvatarUrl(newUrl, version);

    _evictAvatarImage(oldUrl);
    _evictAvatarImage(newUrl);
    _evictAvatarImage(displayUrl);

    if (displayUrl.isNotEmpty) {
      cacheAvatarUrl(userId, displayUrl);
    }
    unawaited(ref.read(userStateNotifierProvider.notifier).onUpdateAvatar());
    unawaited(_saveAvatarSubscription?.cancel());
    _saveAvatarSubscription = null;
    if (!mounted) return;
    setState(() {
      uploadProgress = null;
      _isUploading = false;
      _optimisticAvatarUrl = displayUrl.isEmpty ? null : displayUrl;
    });
  }

  Future<void> _removeAvatar(UserState userState) async {
    final userId = userState.user.idOrNull;
    if (userId == null) return;
    final cachedUrl = getCachedAvatarUrl(userId);
    final avatarPath = switch (userState.user) {
      AuthenticatedUserData(:final avatarPath) => avatarPath,
      _ => null,
    };
    setState(() {
      temporaryAvatarBytes = null;
      _optimisticAvatarUrl = null;
      uploadProgress = null;
      _isUploading = false;
    });
    await ref.read(userRepositoryProvider).deleteAvatar(userId: userId);
    _evictAvatarImage(cachedUrl);
    _evictAvatarImage(avatarPath);
    clearAvatarCache(userId);
    unawaited(ref.read(userStateNotifierProvider.notifier).onUpdateAvatar());
  }

  void _updateUploadProgress(double progress) {
    if (!mounted) return;
    final normalized = _normalizeProgress(progress);
    setState(() {
      uploadProgress = normalized <= 0 ? null : normalized;
    });
  }

  double _normalizeProgress(double progress) {
    if (!progress.isFinite || progress <= 0) return 0.0;
    if (progress >= 1) return 1.0;
    return progress;
  }

  void _resetUploadState({required bool clearPreview}) {
    unawaited(_saveAvatarSubscription?.cancel());
    _saveAvatarSubscription = null;
    if (!mounted || !_isUploading) return;
    setState(() {
      if (clearPreview) {
        temporaryAvatarBytes = null;
      }
      uploadProgress = null;
      _isUploading = false;
    });
  }

  void _evictAvatarImage(String? url) {
    if (url == null || url.isEmpty) return;
    PaintingBinding.instance.imageCache.evict(NetworkImage(url));
  }

  bool _hasAvatarUrl(String? url) {
    return url != null && url.isNotEmpty;
  }
}

enum _AvatarAction { camera, library, remove }

class _BottomSheetTile extends StatelessWidget {
  final IconData? icon;
  final String label;
  final Color? color;
  final VoidCallback onTap;

  const _BottomSheetTile({
    this.icon,
    required this.label,
    this.color,
    required this.onTap,
  });

  @override
  Widget build(BuildContext context) {
    final Color fg = color ?? context.colors.onSurface;
    return InkWell(
      onTap: onTap,
      child: Padding(
        padding: const EdgeInsets.symmetric(
          horizontal: KasySpacing.md,
          vertical: KasySpacing.smd,
        ),
        child: Row(
          children: [
            if (icon != null) ...[
              Icon(icon, size: 22, color: fg),
              const SizedBox(width: KasySpacing.sm),
            ],
            Text(
              label,
              style: context.textTheme.bodyLarge?.copyWith(color: fg),
            ),
          ],
        ),
      ),
    );
  }
}

/// Resolves the avatar [ImageProvider] and renders a [KasyAvatar] with
/// [KasyAvatarFallbackSurface.soft]. Firebase Storage URL is loaded async.
class _AvatarContent extends StatelessWidget {
  final double diameter;
  final ImageProvider? localImage;
  final String? userId;
  final String? avatarPath;

  const _AvatarContent({
    required this.diameter,
    this.localImage,
    this.userId,
    this.avatarPath,
  });

  @override
  Widget build(BuildContext context) {
    // 1. Arquivo temporário escolhido da galeria (prioridade máxima)
    if (localImage != null) {
      return KasyAvatar(
        diameter: diameter,
        image: localImage,
        fallbackSurface: KasyAvatarFallbackSurface.soft,
        tone: KasyAvatarTone.neutral,
      );
    }

    final path = avatarPath;
    if (path != null && path.isNotEmpty) {
      return KasyAvatar(
        diameter: diameter,
        image: NetworkImage(path),
        fallbackSurface: KasyAvatarFallbackSurface.soft,
        tone: KasyAvatarTone.neutral,
      );
    }

    final id = userId;
    if (id != null) {
      // 2. URL em cache: síncrono, sem FutureBuilder, sem flash de fallback
      final cachedUrl = getCachedAvatarUrl(id);
      if (cachedUrl != null && cachedUrl.isNotEmpty) {
        return KasyAvatar(
          diameter: diameter,
          image: NetworkImage(cachedUrl),
          fallbackSurface: KasyAvatarFallbackSurface.soft,
          tone: KasyAvatarTone.neutral,
        );
      }

      // 3. URL não está em cache: busca async (primeiro acesso ou após upload)
      return FutureBuilder<String>(
        future: resolveAvatarUrl(id),
        builder: (context, snapshot) {
          final url = snapshot.data;
          return KasyAvatar(
            diameter: diameter,
            image: (url != null && url.isNotEmpty) ? NetworkImage(url) : null,
            fallbackSurface: KasyAvatarFallbackSurface.soft,
            tone: KasyAvatarTone.neutral,
          );
        },
      );
    }

    // 4. Guest: fallback suave
    return KasyAvatar(
      diameter: diameter,
      fallbackSurface: KasyAvatarFallbackSurface.soft,
      tone: KasyAvatarTone.neutral,
    );
  }
}

/// Fades the avatar to 0.6 opacity during upload and back to 1.0 when done.
class _AvatarFadeAnimation extends StatelessWidget {
  final Widget child;
  final bool isUploading;

  const _AvatarFadeAnimation({required this.child, required this.isUploading});

  @override
  Widget build(BuildContext context) {
    return AnimatedOpacity(
      opacity: isUploading ? 0.6 : 1.0,
      duration: const Duration(milliseconds: 300),
      curve: Curves.easeOut,
      child: child,
    );
  }
}
