import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:userfront/i18n.dart';
import 'package:userfront/core/i18n/locale_utils.dart';
import 'package:userfront/core/services/auth_proxy_service.dart';
import 'package:userfront/core/services/web_window.dart';
import 'package:userfront/core/ui/toast_service.dart';
import 'package:userfront/features/auth/domain/consent_error_routing.dart';
import 'package:userfront/features/auth/domain/consent_scope_policy.dart';

class ConsentScreen extends StatefulWidget {
  final String consentChallenge;
  final Future<Map<String, dynamic>> Function(String consentChallenge)?
  consentInfoLoader;

  const ConsentScreen({
    super.key,
    required this.consentChallenge,
    this.consentInfoLoader,
  });

  @override
  State<ConsentScreen> createState() => _ConsentScreenState();
}

class _ConsentScreenState extends State<ConsentScreen> {
  Map<String, dynamic>? _consentInfo;
  bool _isLoading = true;
  bool _isSubmitting = false;
  String? _error;

  final Set<String> _selectedScopes = {};
  final Map<String, String> _scopeDescriptions = {};
  final Set<String> _mandatoryScopes = {'openid'};

  @override
  void initState() {
    super.initState();
    _scopeDescriptions.addAll(_defaultScopeDescriptions());
    _fetchConsentInfo();
  }

  Map<String, String> _defaultScopeDescriptions() {
    return {
      'openid': tr(
        'msg.userfront.consent.scope.openid',
        fallback: 'OpenID authentication information (signin session check)',
      ),
      'profile': tr(
        'msg.userfront.consent.scope.profile',
        fallback: 'Basic profile information (name, user identifier)',
      ),
      'email': tr(
        'msg.userfront.consent.scope.email',
        fallback: 'Email address (account identification and notifications)',
      ),
      'phone': tr(
        'msg.userfront.consent.scope.phone',
        fallback: 'Phone number (identity verification and notifications)',
      ),
    };
  }

  String _renderConsentText(String key, {String? fallback}) {
    return tr(
      key,
      fallback: fallback,
    ).replaceAll(r'\\n', '\n').replaceAll(r'\n', '\n').replaceAll('\\\n', '\n');
  }

  String _renderScopeCountLabel(int count) {
    return tr(
      'msg.userfront.consent.scope_count',
      fallback: 'Total {{count}}',
      params: {'count': '$count'},
    ).replaceAll('{$count}', '$count');
  }

  String _scopeDisplayLabel(String scope) {
    return scope.replaceAll('_', ' ');
  }

  String _renderClientIdLabel(String clientId) {
    final raw = tr(
      'msg.userfront.consent.client_id',
      fallback: 'Client ID: {{id}}',
    );
    final normalized = raw
        .replaceAll('{{id}}', '')
        .replaceAll('{id}', '')
        .trimRight();
    return '$normalized $clientId';
  }

  Future<void> _fetchConsentInfo() async {
    try {
      final loader =
          widget.consentInfoLoader ?? AuthProxyService.getConsentInfo;
      final info = await loader(widget.consentChallenge);

      // [Skip Logic] 백엔드에서 자동 승인되어 리다이렉트 URL이 온 경우 즉시 이동
      if (info['redirectTo'] != null) {
        webWindow.redirectTo(info['redirectTo']);
        return;
      }

      // 백엔드에서 전달받은 커스텀 스코프 정보(scope_details) 적용
      if (info['scope_details'] != null) {
        final details = info['scope_details'] as Map<String, dynamic>;

        details.forEach((scope, detail) {
          if (detail is Map<String, dynamic>) {
            // 설명 업데이트
            if (detail['description'] != null &&
                detail['description'].toString().isNotEmpty) {
              _scopeDescriptions[scope] = detail['description'].toString();
            }
            // 필수 여부 업데이트
            if (detail['mandatory'] == true) {
              _mandatoryScopes.add(scope);
            } else {
              // openid는 기본적으로 필수지만 설정에서 굳이 껐다면?
              // 안전을 위해 openid는 항상 필수로 유지하는 것이 좋지만,
              // 여기서는 서버 설정을 존중하되 openid는 예외처리 할 수도 있음.
              // 우선 서버 설정이 있으면 반영 (단, openid는 제거하지 않음)
              if (scope != 'openid') {
                _mandatoryScopes.remove(scope);
              }
            }
          }
        });
      }

      // 초기 선택 상태 설정: 모든 요청된 스코프를 기본 선택
      final requestedScopes = filterConsentScopes(
        (info['requested_scope'] as List<dynamic>?)?.cast<String>() ?? [],
      );
      _selectedScopes.addAll(requestedScopes);
      info['requested_scope'] = requestedScopes;

      setState(() {
        _consentInfo = info;
        _isLoading = false;
      });
    } on AuthProxyException catch (e) {
      if (shouldRouteConsentErrorToErrorScreen(e)) {
        if (!mounted) {
          return;
        }
        final target = buildTenantAccessErrorPath(e, Uri.base);
        context.go(target);
        return;
      }
      setState(() {
        _error = tr(
          'msg.userfront.consent.load_error',
          fallback: 'Failed to load consent information: {{error}}',
          params: {'error': e.message},
        );
        _isLoading = false;
      });
    } catch (e) {
      setState(() {
        _error = tr(
          'msg.userfront.consent.load_error',
          fallback: 'Failed to load consent information: {{error}}',
          params: {'error': '$e'},
        );
        _isLoading = false;
      });
    }
  }

  Future<void> _acceptConsent() async {
    setState(() {
      _isSubmitting = true;
      _error = null;
    });
    try {
      // 선택된 스코프만 리스트로 변환하여 전송
      final result = await AuthProxyService.acceptConsent(
        widget.consentChallenge,
        grantScope: _selectedScopes.toList(),
      );

      if (result['redirectTo'] != null) {
        webWindow.redirectTo(result['redirectTo']);
      } else {
        setState(() {
          _error = tr(
            'msg.userfront.consent.missing_redirect',
            fallback:
                'Consent was processed, but the redirect URL was missing.',
          );
          _isSubmitting = false;
        });
      }
    } catch (e) {
      setState(() {
        _error = tr(
          'msg.userfront.consent.accept_error',
          fallback: 'Failed to process consent: {{error}}',
          params: {'error': '$e'},
        );
        _isSubmitting = false;
      });
    }
  }

  Future<void> _onCancel() async {
    final confirmed = await showDialog<bool>(
      context: context,
      builder: (context) => AlertDialog(
        title: Text(tr('ui.userfront.consent.cancel.title')),
        content: Text(tr('msg.userfront.consent.cancel.confirm')),
        actions: [
          TextButton(
            onPressed: () => Navigator.pop(context, false),
            child: Text(tr('ui.common.cancel')),
          ),
          TextButton(
            onPressed: () => Navigator.pop(context, true),
            style: TextButton.styleFrom(foregroundColor: Colors.red),
            child: Text(tr('ui.userfront.consent.cancel.confirm_button')),
          ),
        ],
      ),
    );

    if (confirmed == true) {
      setState(() => _isSubmitting = true);
      try {
        final resp = await AuthProxyService.rejectConsent(
          widget.consentChallenge,
        );
        final redirectTo = resp['redirectTo'];
        if (redirectTo != null) {
          webWindow.redirectTo(redirectTo);
        } else {
          if (mounted) context.go(buildLocalizedHomePath(Uri.base));
        }
      } catch (e) {
        setState(() => _isSubmitting = false);
        if (mounted) {
          ToastService.error(
            tr(
              'msg.userfront.consent.cancel.error',
              fallback: 'An error occurred while cancelling consent: {{error}}',
              params: {'error': '$e'},
            ),
          );
        }
      }
    }
  }

  @override
  Widget build(BuildContext context) {
    // 배경색을 약간 어둡게 처리하거나, 전체적인 테마 색상을 사용
    return Scaffold(
      backgroundColor: Colors.grey[100],
      body: Center(
        child: _isLoading
            ? const CircularProgressIndicator()
            : _error != null
            ? _buildErrorCard()
            : _buildConsentCard(context),
      ),
    );
  }

  Widget _buildErrorCard() {
    return Card(
      margin: const EdgeInsets.all(24),
      child: Padding(
        padding: const EdgeInsets.all(24),
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            const Icon(Icons.error_outline, color: Colors.red, size: 48),
            const SizedBox(height: 16),
            Text(_error!, textAlign: TextAlign.center),
          ],
        ),
      ),
    );
  }

  Widget _buildConsentCard(BuildContext context) {
    final clientRawName = _consentInfo?['client']?['client_name'] as String?;
    final clientId = _consentInfo?['client']?['client_id'] as String? ?? '-';
    final clientName = (clientRawName != null && clientRawName.isNotEmpty)
        ? clientRawName
        : (clientId != '-'
              ? clientId
              : tr('msg.userfront.consent.client_unknown'));
    final clientLogo = _consentInfo?['client']?['logo_uri'];
    final requestedScopes = filterConsentScopes(
      (_consentInfo?['requested_scope'] as List<dynamic>?)?.cast<String>() ??
          [],
    );

    return SingleChildScrollView(
      child: Container(
        constraints: const BoxConstraints(maxWidth: 520),
        margin: const EdgeInsets.all(16),
        child: Card(
          elevation: 8,
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(16),
          ),
          child: Padding(
            padding: const EdgeInsets.all(32.0),
            child: Column(
              mainAxisSize: MainAxisSize.min,
              crossAxisAlignment: CrossAxisAlignment.stretch,
              children: [
                // 1. 헤더 영역
                Text(
                  tr('ui.userfront.consent.title'),
                  style: const TextStyle(
                    fontSize: 24,
                    fontWeight: FontWeight.bold,
                  ),
                  textAlign: TextAlign.center,
                ),
                const SizedBox(height: 12),
                Text(
                  _renderConsentText('msg.userfront.consent.description'),
                  style: TextStyle(fontSize: 14, color: Colors.grey[600]),
                  textAlign: TextAlign.center,
                ),
                const SizedBox(height: 32),

                // 2. 서비스 정보 영역
                Container(
                  padding: const EdgeInsets.all(16),
                  decoration: BoxDecoration(
                    color: Colors.grey[50],
                    borderRadius: BorderRadius.circular(12),
                    border: Border.all(color: Colors.grey[200]!),
                  ),
                  child: Row(
                    children: [
                      if (clientLogo != null &&
                          clientLogo.toString().isNotEmpty)
                        Padding(
                          padding: const EdgeInsets.only(right: 16),
                          child: CircleAvatar(
                            radius: 24,
                            backgroundImage: NetworkImage(clientLogo),
                            backgroundColor: Colors.transparent,
                          ),
                        )
                      else
                        const Padding(
                          padding: EdgeInsets.only(right: 16),
                          child: CircleAvatar(
                            radius: 24,
                            child: Icon(Icons.apps),
                          ),
                        ),
                      Expanded(
                        child: Column(
                          crossAxisAlignment: CrossAxisAlignment.start,
                          children: [
                            Text(
                              clientName,
                              style: const TextStyle(
                                fontSize: 18,
                                fontWeight: FontWeight.w600,
                              ),
                            ),
                            const SizedBox(height: 4),
                            Text(
                              _renderClientIdLabel(clientId),
                              style: TextStyle(
                                fontSize: 12,
                                color: Colors.grey[500],
                                fontFamily: 'monospace',
                              ),
                            ),
                          ],
                        ),
                      ),
                    ],
                  ),
                ),
                const SizedBox(height: 32),

                // 3. 권한 선택 영역
                Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  children: [
                    Text(
                      tr('ui.userfront.consent.requested_scopes'),
                      style: const TextStyle(
                        fontSize: 16,
                        fontWeight: FontWeight.bold,
                      ),
                    ),
                    Text(
                      _renderScopeCountLabel(requestedScopes.length),
                      style: TextStyle(
                        fontSize: 14,
                        color: Theme.of(context).primaryColor,
                        fontWeight: FontWeight.w500,
                      ),
                    ),
                  ],
                ),
                const SizedBox(height: 8),
                const Divider(),
                ...requestedScopes.map((scope) {
                  final isMandatory = _mandatoryScopes.contains(scope);
                  final description = _scopeDescriptions[scope] ?? scope;
                  final isSelected = _selectedScopes.contains(scope);

                  return CheckboxListTile(
                    title: Text(
                      _scopeDisplayLabel(scope),
                      style: const TextStyle(fontWeight: FontWeight.w500),
                    ),
                    subtitle: Text(description),
                    value: isSelected,
                    onChanged: isMandatory
                        ? null // 필수 항목은 변경 불가 (비활성화 상태로 체크됨)
                        : (bool? value) {
                            setState(() {
                              if (value == true) {
                                _selectedScopes.add(scope);
                              } else {
                                _selectedScopes.remove(scope);
                              }
                            });
                          },
                    controlAffinity: ListTileControlAffinity.leading,
                    contentPadding: EdgeInsets.zero,
                    activeColor: Theme.of(context).primaryColor,
                  );
                }),
                const Divider(),
                const SizedBox(height: 32),

                // 4. 버튼 영역
                ElevatedButton(
                  onPressed: _isSubmitting ? null : _acceptConsent,
                  style: ElevatedButton.styleFrom(
                    padding: const EdgeInsets.symmetric(vertical: 16),
                    backgroundColor: const Color(0xFF1A1F2C), // 브랜드 컬러
                    foregroundColor: Colors.white,
                    shape: RoundedRectangleBorder(
                      borderRadius: BorderRadius.circular(8),
                    ),
                    elevation: 0,
                  ),
                  child: _isSubmitting
                      ? const SizedBox(
                          height: 20,
                          width: 20,
                          child: CircularProgressIndicator(
                            strokeWidth: 2,
                            color: Colors.white,
                          ),
                        )
                      : Text(
                          tr('ui.userfront.consent.accept'),
                          style: const TextStyle(
                            fontSize: 16,
                            fontWeight: FontWeight.bold,
                          ),
                        ),
                ),
                const SizedBox(height: 12),
                OutlinedButton(
                  onPressed: _isSubmitting ? null : _onCancel,
                  style: OutlinedButton.styleFrom(
                    padding: const EdgeInsets.symmetric(vertical: 16),
                    shape: RoundedRectangleBorder(
                      borderRadius: BorderRadius.circular(8),
                    ),
                  ),
                  child: Text(tr('ui.common.cancel')),
                ),
                const SizedBox(height: 16),
                Text(
                  tr('msg.userfront.consent.redirect_notice'),
                  style: TextStyle(fontSize: 12, color: Colors.grey[500]),
                  textAlign: TextAlign.center,
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}
