import 'dart:io';

import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:file_picker/file_picker.dart';
import 'package:tdesign_flutter/tdesign_flutter.dart';
import 'package:marquee/marquee.dart';
import '../models/attachment_file.dart';
import '../../core/i18n/app_localizations.dart';
import '../../core/theme/app_colors.dart';
import '../../core/theme/app_colors_extension.dart';

// ═══════════════════════════════════════════════════════════════
// Controller
// ═══════════════════════════════════════════════════════════════

class AttachmentPickerController extends ChangeNotifier {
  final int maxCount;

  final List<AttachmentFile> _files = [];
  List<AttachmentFile> get files => List.unmodifiable(_files);
  int get count => _files.length;
  bool get isFull => _files.length >= maxCount;

  AttachmentPickerController({
    this.maxCount = 9,
    List<AttachmentFile>? initialFiles,
  }) {
    if (initialFiles != null) {
      _files.addAll(initialFiles.take(maxCount));
    }
  }

  void addFile(AttachmentFile file) {
    if (_files.length >= maxCount) return;
    _files.add(file);
    notifyListeners();
  }

  void addFiles(List<AttachmentFile> files) {
    for (final f in files) {
      if (_files.length >= maxCount) break;
      _files.add(f);
    }
    notifyListeners();
  }

  void removeFile(int index) {
    if (index < 0 || index >= _files.length) return;
    _files.removeAt(index);
    notifyListeners();
  }

  void clear() {
    if (_files.isEmpty) return;
    _files.clear();
    notifyListeners();
  }

  /// 从路径列表恢复（草稿兼容）
  Future<void> restoreFromPaths(List<String> paths) async {
    _files.clear();
    for (final path in paths.take(maxCount)) {
      _files.add(await AttachmentFile.fromPath(path));
    }
    notifyListeners();
  }

  /// 导出为路径列表（草稿持久化）
  List<String> toPathList() => _files.map((f) => f.path).toList();
}

// ═══════════════════════════════════════════════════════════════
// Widget
// ═══════════════════════════════════════════════════════════════

class AttachmentPicker extends StatefulWidget {
  final AttachmentPickerController controller;

  /// 图片大小上限（MB），null 不限制
  final double? maxImageSizeMB;

  /// 文件大小上限（MB），null 不限制
  final double? maxFileSizeMB;

  /// 允许的文件扩展名，null 使用默认 pdf/doc/docx/xls/xlsx/ppt/pptx/txt
  final List<String>? allowedExtensions;

  /// 文件被拒时回调
  final void Function(AttachmentFile file, String reason)? onFileRejected;

  /// 缩略图尺寸
  final double thumbnailSize;

  const AttachmentPicker({
    super.key,
    required this.controller,
    this.maxImageSizeMB,
    this.maxFileSizeMB,
    this.allowedExtensions,
    this.onFileRejected,
    this.thumbnailSize = 80,
  });

  @override
  State<AttachmentPicker> createState() => _AttachmentPickerState();
}

class _AttachmentPickerState extends State<AttachmentPicker> {
  List<AttachmentFile> get _files => widget.controller.files;

  @override
  void initState() {
    super.initState();
    widget.controller.addListener(_onChanged);
  }

  @override
  void dispose() {
    widget.controller.removeListener(_onChanged);
    super.dispose();
  }

  void _onChanged() {
    if (mounted) setState(() {});
  }

  // ── 选择入口 ──

  Future<void> _showPicker() async {
    _unfocus();
    final l10n = AppLocalizations.of(context);
    final colors = Theme.of(context).extension<AppColorsExtension>()!;

    final choice = await showModalBottomSheet<String>(
      context: context,
      backgroundColor: colors.bgCard,
      shape: const RoundedRectangleBorder(
        borderRadius: BorderRadius.vertical(top: Radius.circular(16)),
      ),
      builder: (ctx) => SafeArea(
        child: Padding(
          padding: const EdgeInsets.fromLTRB(0, 8, 0, 20),
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              // 拖拽手柄
              Center(
                child: Container(
                  width: 36,
                  height: 4,
                  margin: const EdgeInsets.only(bottom: 12),
                  decoration: BoxDecoration(
                    color: colors.border,
                    borderRadius: BorderRadius.circular(2),
                  ),
                ),
              ),
              // 选择图片
              InkWell(
                onTap: () => Navigator.pop(ctx, 'image'),
                child: Padding(
                  padding: const EdgeInsets.symmetric(
                    horizontal: 16,
                    vertical: 16,
                  ),
                  child: Row(
                    children: [
                      Container(
                        width: 44,
                        height: 44,
                        decoration: BoxDecoration(
                          color: colors.primaryLight,
                          borderRadius: BorderRadius.circular(12),
                        ),
                        child: Icon(
                          Icons.image_outlined,
                          color: colors.primary,
                          size: 24,
                        ),
                      ),
                      const SizedBox(width: 16),
                      Text(
                        l10n.get('pickImage'),
                        style: TextStyle(
                          fontSize: 16,
                          color: colors.textPrimary,
                        ),
                      ),
                    ],
                  ),
                ),
              ),
              const Divider(height: 1, indent: 76),
              // 选择文件
              InkWell(
                onTap: () => Navigator.pop(ctx, 'file'),
                child: Padding(
                  padding: const EdgeInsets.symmetric(
                    horizontal: 16,
                    vertical: 16,
                  ),
                  child: Row(
                    children: [
                      Container(
                        width: 44,
                        height: 44,
                        decoration: BoxDecoration(
                          color: colors.primaryLight,
                          borderRadius: BorderRadius.circular(12),
                        ),
                        child: Icon(
                          Icons.description_outlined,
                          color: colors.primary,
                          size: 24,
                        ),
                      ),
                      const SizedBox(width: 16),
                      Text(
                        l10n.get('pickFile'),
                        style: TextStyle(
                          fontSize: 16,
                          color: colors.textPrimary,
                        ),
                      ),
                    ],
                  ),
                ),
              ),
            ],
          ),
        ),
      ),
    );

    if (!mounted || choice == null) return;
    if (choice == 'image') {
      await _pickImages();
    } else {
      await _pickDocuments();
    }
  }

  Future<void> _pickImages() async {
    final available = widget.controller.maxCount - widget.controller.count;
    if (available <= 0) return;
    final picker = ImagePicker();
    // pickMultiImage 在某些平台上 limit=1 时无响应，兜底用单选
    if (available == 1) {
      final img = await picker.pickImage(source: ImageSource.gallery);
      if (img == null) return;
      final file = await AttachmentFile.fromXFile(img);
      if (!_checkOversized(file)) widget.controller.addFile(file);
      return;
    }
    final images = await picker.pickMultiImage(limit: available);
    if (!mounted || images.isEmpty) return;
    for (final img in images) {
      if (widget.controller.isFull) break;
      final file = await AttachmentFile.fromXFile(img);
      if (_checkOversized(file)) continue;
      widget.controller.addFile(file);
    }
  }

  Future<void> _pickDocuments() async {
    final available = widget.controller.maxCount - widget.controller.count;
    if (available <= 0) return;
    final result = await FilePicker.pickFiles(
      type: FileType.custom,
      allowedExtensions:
          widget.allowedExtensions ??
          const ['pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'txt'],
      allowMultiple: true,
    );
    if (!mounted || result == null || result.files.isEmpty) return;
    if (result.files.length > available) {
      final l10n = AppLocalizations.of(context);
      TDToast.showText(
        l10n.getString('fileLimitHint', args: {'limit': '$available'}),
        context: context,
      );
    }
    for (final pf in result.files) {
      if (widget.controller.isFull) break;
      if (pf.path == null) continue;
      final file = AttachmentFile.fromPlatformFile(pf);
      if (_checkOversized(file)) continue;
      widget.controller.addFile(file);
    }
  }

  /// 返回 true 表示文件超过大小限制
  bool _checkOversized(AttachmentFile file) {
    final l10n = AppLocalizations.of(context);
    final sizeMB = file.sizeMB;

    if (file.isImage &&
        widget.maxImageSizeMB != null &&
        sizeMB > widget.maxImageSizeMB!) {
      final reason = l10n.getString(
        'imageSizeLimit',
        args: {'max': widget.maxImageSizeMB!.toStringAsFixed(0)},
      );
      widget.onFileRejected?.call(file, reason);
      if (mounted) TDToast.showText(reason, context: context);
      return true;
    }
    if (!file.isImage &&
        widget.maxFileSizeMB != null &&
        sizeMB > widget.maxFileSizeMB!) {
      final reason = l10n.getString(
        'fileSizeLimit',
        args: {'max': widget.maxFileSizeMB!.toStringAsFixed(0)},
      );
      widget.onFileRejected?.call(file, reason);
      if (mounted) TDToast.showText(reason, context: context);
      return true;
    }
    return false;
  }

  void _unfocus() => FocusScope.of(context).unfocus();

  // ── UI ──

  @override
  Widget build(BuildContext context) {
    final colors = Theme.of(context).extension<AppColorsExtension>()!;

    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Wrap(
          spacing: 8,
          runSpacing: 8,
          children: [
            ..._files.asMap().entries.map(
              (e) => Stack(
                clipBehavior: Clip.none,
                children: [
                  _buildThumbnail(e.value),
                  Positioned(
                    right: -4,
                    top: -4,
                    child: GestureDetector(
                      onTap: () => widget.controller.removeFile(e.key),
                      child: Container(
                        width: 20,
                        height: 20,
                        decoration: BoxDecoration(
                          color: colors.danger,
                          shape: BoxShape.circle,
                        ),
                        child: const Icon(
                          Icons.close,
                          size: 12,
                          color: Colors.white,
                        ),
                      ),
                    ),
                  ),
                ],
              ),
            ),
            if (!widget.controller.isFull)
              GestureDetector(
                onTap: () => _showPicker(),
                child: Container(
                  width: widget.thumbnailSize,
                  height: widget.thumbnailSize,
                  decoration: BoxDecoration(
                    color: colors.bgCard,
                    borderRadius: BorderRadius.circular(4),
                    border: Border.all(color: colors.border, width: 1),
                  ),
                  child: Center(
                    child: Icon(
                      Icons.add,
                      size: 24,
                      color: colors.textPlaceholder,
                    ),
                  ),
                ),
              ),
          ],
        ),
      ],
    );
  }

  Widget _buildThumbnail(AttachmentFile file) {
    final colors = Theme.of(context).extension<AppColorsExtension>()!;
    final size = widget.thumbnailSize;

    if (file.isImage) {
      return Container(
        width: size,
        height: size,
        decoration: BoxDecoration(
          borderRadius: BorderRadius.circular(4),
          border: Border.all(color: colors.border, width: 0.5),
        ),
        child: ClipRRect(
          borderRadius: BorderRadius.circular(4),
          child: Image.file(
            File(file.path),
            width: size,
            height: size,
            fit: BoxFit.cover,
            errorBuilder: (_, _, _) => _buildDocTile(file, colors, size),
          ),
        ),
      );
    }

    return _buildDocTile(file, colors, size);
  }

  Widget _buildDocTile(
    AttachmentFile file,
    AppColorsExtension colors,
    double size,
  ) {
    return SizedBox(
      width: size,
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          Container(
            width: size,
            height: size,
            decoration: BoxDecoration(
              color: colors.primaryLight,
              borderRadius: BorderRadius.circular(4),
            ),
            child: Center(
              child: Icon(
                _fileTypeIcon(file.extension),
                color: colors.primary,
                size: size * 0.4,
              ),
            ),
          ),
          const SizedBox(height: 4),
          SizedBox(
            width: size,
            height:
                MediaQuery.textScalerOf(context).scale(AppFontSizes.caption) *
                1.4,
            child: Marquee(
              text: file.name,
              style: TextStyle(
                fontSize: AppFontSizes.caption,
                color: colors.textSecondary,
              ),
              scrollAxis: Axis.horizontal,
              blankSpace: 40,
              velocity: 30,
              pauseAfterRound: const Duration(seconds: 1),
              startPadding: 0,
              accelerationDuration: const Duration(milliseconds: 500),
              accelerationCurve: Curves.linear,
              decelerationDuration: const Duration(milliseconds: 500),
              decelerationCurve: Curves.easeOut,
            ),
          ),
        ],
      ),
    );
  }

  IconData _fileTypeIcon(String ext) {
    switch (ext) {
      case 'pdf':
        return Icons.picture_as_pdf;
      case 'doc':
      case 'docx':
        return Icons.description;
      case 'xls':
      case 'xlsx':
        return Icons.table_chart;
      case 'ppt':
      case 'pptx':
        return Icons.slideshow;
      default:
        return Icons.insert_drive_file;
    }
  }
}
