import 'dart:io';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:http/http.dart' as http;
import 'package:path/path.dart' as p;
import 'package:path_provider/path_provider.dart';
import 'package:pyramid/core/theme.dart';
import 'package:pyramid/core/update_checker.dart';
import 'package:pyramid/widgets/pyramid_loader.dart';

// ─── Entry point ──────────────────────────────────────────────────────────────

Future<void> showUpdateDownloadDialog(BuildContext context, UpdateInfo info) {
  return showDialog(
    context: context,
    barrierDismissible: false,
    barrierColor: Colors.black.withAlpha(160),
    builder: (_) => _UpdateDownloadDialog(info: info),
  );
}

// ─── States ───────────────────────────────────────────────────────────────────

enum _DownloadState { idle, downloading, installing, done, error }

// ─── Dialog widget ────────────────────────────────────────────────────────────

class _UpdateDownloadDialog extends ConsumerStatefulWidget {
  final UpdateInfo info;
  const _UpdateDownloadDialog({required this.info});

  @override
  ConsumerState<_UpdateDownloadDialog> createState() =>
      _UpdateDownloadDialogState();
}

class _UpdateDownloadDialogState extends ConsumerState<_UpdateDownloadDialog> {
  _DownloadState _state = _DownloadState.idle;
  double _progress = 0.0;
  int _received = 0;
  int _total = 0;
  String _errorMsg = '';

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

  // ─── Download ───────────────────────────────────────────────────────────────

  Future<void> _startDownload() async {
    setState(() {
      _state = _DownloadState.downloading;
      _progress = 0;
      _received = 0;
      _total = 0;
    });

    try {
      final dir = await getTemporaryDirectory();
      final downloadDir = Directory(p.join(dir.path, 'downloads'));
      await downloadDir.create(recursive: true);

      final ext = Platform.isWindows ? '.exe' : '.apk';
      final fileName = 'pyramid-update-${widget.info.tagName}$ext';
      final file = File(p.join(downloadDir.path, fileName));
      final request = http.Request('GET', Uri.parse(widget.info.downloadUrl!));
      final streamedResponse =
          await http.Client().send(request).timeout(const Duration(minutes: 5));

      _total = streamedResponse.contentLength ?? 0;
      final sink = file.openWrite();

      await for (final chunk in streamedResponse.stream) {
        sink.add(chunk);
        _received += chunk.length;
        if (mounted) {
          setState(() {
            _progress = _total > 0 ? _received / _total : 0;
          });
        }
      }
      await sink.flush();
      await sink.close();

      if (!mounted) return;
      await _install(file);
    } catch (e) {
      if (mounted) {
        setState(() {
          _state = _DownloadState.error;
          _errorMsg = e.toString().split('\n').first;
        });
      }
    }
  }

  static const _installChannel =
      MethodChannel('chat.pyramid.pyramid/install');

  Future<void> _install(File file) async {
    setState(() => _state = _DownloadState.installing);

    try {
      if (Platform.isWindows) {
        await Process.start(file.path, [], runInShell: false);
        if (mounted) Navigator.of(context).pop();
        exit(0);
      } else if (Platform.isAndroid) {
        await _installChannel
            .invokeMethod('installApk', {'path': file.path});
        if (mounted) setState(() => _state = _DownloadState.done);
      }
    } on PlatformException catch (e) {
      if (e.code == 'PERMISSION_REQUIRED') {
        if (mounted) {
          setState(() {
            _state = _DownloadState.error;
            _errorMsg = 'Bitte "Unbekannte Apps installieren" für Pyramid erlauben (Einstellungen geöffnet) — dann erneut versuchen.';
          });
        }
      } else {
        if (mounted) {
          setState(() {
            _state = _DownloadState.error;
            _errorMsg = e.message ?? e.toString();
          });
        }
      }
    } catch (e) {
      if (mounted) {
        setState(() {
          _state = _DownloadState.error;
          _errorMsg = e.toString().split('\n').first;
        });
      }
    }
  }

  // ─── Helpers ────────────────────────────────────────────────────────────────

  String _formatBytes(int bytes) {
    if (bytes < 1024 * 1024) return '${(bytes / 1024).toStringAsFixed(1)} KB';
    return '${(bytes / (1024 * 1024)).toStringAsFixed(1)} MB';
  }

  // ─── UI ─────────────────────────────────────────────────────────────────────

  @override
  Widget build(BuildContext context) {
    final pt = PyramidTheme.of(context);
    return Dialog(
      backgroundColor: Colors.transparent,
      elevation: 0,
      child: Container(
        width: 320,
        padding: const EdgeInsets.fromLTRB(32, 36, 32, 28),
        decoration: BoxDecoration(
          color: pt.bg1,
          borderRadius: BorderRadius.circular(20),
          border: Border.all(color: pt.border),
          boxShadow: [
            BoxShadow(
              color: Colors.black.withAlpha(120),
              blurRadius: 40,
              spreadRadius: 4,
            ),
          ],
        ),
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            // ── Loading animation ──
            const PyramidLoader(size: 72),
            const SizedBox(height: 24),

            // ── Title (hidden while actively downloading) ──
            if (_state != _DownloadState.downloading &&
                _state != _DownloadState.installing) ...[
              Text(
                _titleText(),
                style: TextStyle(
                  color: pt.fg,
                  fontSize: 16,
                  fontWeight: FontWeight.w700,
                ),
                textAlign: TextAlign.center,
              ),
              const SizedBox(height: 6),
            ],
            Text(
              widget.info.tagName,
              style: TextStyle(color: pt.accent, fontSize: 13),
            ),
            const SizedBox(height: 24),

            // ── Progress / Status ──
            if (_state == _DownloadState.downloading) ...[
              _ProgressBar(progress: _progress, pt: pt),
              const SizedBox(height: 10),
              Text(
                _progressLabel(),
                style: TextStyle(color: pt.fgMuted, fontSize: 12),
              ),
            ] else if (_state == _DownloadState.installing) ...[
              _ProgressBar(progress: 1.0, pt: pt),
              const SizedBox(height: 10),
              Text(
                'Wird installiert…',
                style: TextStyle(color: pt.fgMuted, fontSize: 12),
              ),
            ] else if (_state == _DownloadState.done) ...[
              Icon(Icons.check_circle_rounded, color: pt.accent, size: 32),
              const SizedBox(height: 8),
              Text(
                'Update installiert',
                style: TextStyle(color: pt.fgMuted, fontSize: 12),
              ),
            ] else if (_state == _DownloadState.error) ...[
              Icon(Icons.error_outline_rounded,
                  color: pt.danger, size: 32),
              const SizedBox(height: 8),
              Text(
                _errorMsg,
                style: TextStyle(color: pt.danger, fontSize: 11),
                textAlign: TextAlign.center,
                maxLines: 3,
                overflow: TextOverflow.ellipsis,
              ),
            ],

            const SizedBox(height: 24),

            // ── Action buttons ──
            if (_state == _DownloadState.error)
              Row(
                children: [
                  Expanded(
                    child: _DialogBtn(
                      label: 'Abbrechen',
                      pt: pt,
                      onTap: () => Navigator.of(context).pop(),
                    ),
                  ),
                  const SizedBox(width: 10),
                  Expanded(
                    child: _DialogBtn(
                      label: 'Erneut',
                      pt: pt,
                      primary: true,
                      onTap: _startDownload,
                    ),
                  ),
                ],
              )
            else if (_state == _DownloadState.done)
              _DialogBtn(
                label: 'Schließen',
                pt: pt,
                onTap: () => Navigator.of(context).pop(),
              )
            else if (_state == _DownloadState.downloading)
              _DialogBtn(
                label: 'Abbrechen',
                pt: pt,
                onTap: () => Navigator.of(context).pop(),
              ),
          ],
        ),
      ),
    );
  }

  String _titleText() => switch (_state) {
        _DownloadState.idle => 'Vorbereitung…',
        _DownloadState.downloading => 'Update wird geladen',
        _DownloadState.installing => 'Wird installiert',
        _DownloadState.done => 'Fertig!',
        _DownloadState.error => 'Fehler beim Download',
      };

  String _progressLabel() {
    final pct = (_progress * 100).toStringAsFixed(0);
    if (_total > 0) {
      return '$pct% · ${_formatBytes(_received)} / ${_formatBytes(_total)}';
    }
    return '$pct% · ${_formatBytes(_received)}';
  }
}

// ─── Progress bar ─────────────────────────────────────────────────────────────

class _ProgressBar extends StatelessWidget {
  final double progress;
  final PyramidTheme pt;
  const _ProgressBar({required this.progress, required this.pt});

  @override
  Widget build(BuildContext context) {
    return Container(
      height: 6,
      decoration: BoxDecoration(
        color: pt.bg3,
        borderRadius: BorderRadius.circular(3),
      ),
      child: FractionallySizedBox(
        alignment: Alignment.centerLeft,
        widthFactor: progress.clamp(0.0, 1.0),
        child: AnimatedContainer(
          duration: const Duration(milliseconds: 200),
          decoration: BoxDecoration(
            color: pt.accent,
            borderRadius: BorderRadius.circular(3),
            boxShadow: [
              BoxShadow(
                color: pt.accent.withAlpha(100),
                blurRadius: 6,
                spreadRadius: 1,
              ),
            ],
          ),
        ),
      ),
    );
  }
}

// ─── Dialog button ────────────────────────────────────────────────────────────

class _DialogBtn extends StatelessWidget {
  final String label;
  final PyramidTheme pt;
  final bool primary;
  final VoidCallback onTap;

  const _DialogBtn({
    required this.label,
    required this.pt,
    required this.onTap,
    this.primary = false,
  });

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: onTap,
      child: Container(
        height: 36,
        decoration: BoxDecoration(
          color: primary ? pt.accent : pt.bg3,
          borderRadius: BorderRadius.circular(8),
        ),
        child: Center(
          child: Text(
            label,
            style: TextStyle(
              color: primary ? pt.accentFg : pt.fgMuted,
              fontSize: 13,
              fontWeight: FontWeight.w600,
            ),
          ),
        ),
      ),
    );
  }
}
