import 'package:flutter/material.dart';
import 'package:get_it/get_it.dart';
import 'package:lucide_icons_flutter/lucide_icons.dart' as lucide;
import 'package:shadcn_ui/shadcn_ui.dart';

import '../../../../../core/network/failure.dart';
import '../../../../../widgets/components/feedback.dart';
import '../../../domain/entities/approval_template.dart';
import '../../../domain/repositories/approval_template_repository.dart';
import '../../../domain/usecases/save_approval_template_use_case.dart';
import '../controllers/approval_request_controller.dart';

/// 템플릿을 불러오고 적용/저장할 수 있는 결재 템플릿 선택 위젯.
class ApprovalTemplatePicker extends StatefulWidget {
  const ApprovalTemplatePicker({
    super.key,
    required this.controller,
    this.repository,
    this.saveUseCase,
    this.onTemplateApplied,
    this.onTemplatesChanged,
  });

  /// 결재 단계 상태를 제어하는 컨트롤러.
  final ApprovalRequestController controller;

  /// 템플릿 저장소. 지정하지 않으면 [GetIt]에서 조회한다.
  final ApprovalTemplateRepository? repository;

  /// 템플릿 저장 유즈케이스. 지정하지 않으면 [GetIt]에서 조회한다.
  final SaveApprovalTemplateUseCase? saveUseCase;

  /// 템플릿 적용이 완료됐을 때 호출되는 콜백.
  final void Function(ApprovalTemplate template)? onTemplateApplied;

  /// 템플릿 목록이 갱신됐을 때 호출되는 콜백.
  final void Function(List<ApprovalTemplate> templates)? onTemplatesChanged;

  @override
  State<ApprovalTemplatePicker> createState() => _ApprovalTemplatePickerState();
}

class _ApprovalTemplatePickerState extends State<ApprovalTemplatePicker> {
  List<ApprovalTemplate> _templates = const <ApprovalTemplate>[];
  int? _selectedTemplateId;
  bool _isLoading = false;
  bool _isSaving = false;
  String? _error;

  ApprovalTemplateRepository? get _repository =>
      widget.repository ??
      (GetIt.I.isRegistered<ApprovalTemplateRepository>()
          ? GetIt.I<ApprovalTemplateRepository>()
          : null);

  SaveApprovalTemplateUseCase? get _saveUseCase =>
      widget.saveUseCase ??
      (GetIt.I.isRegistered<SaveApprovalTemplateUseCase>()
          ? GetIt.I<SaveApprovalTemplateUseCase>()
          : null);

  @override
  void initState() {
    super.initState();
    _selectedTemplateId = widget.controller.templateSnapshot?.templateId;
    WidgetsBinding.instance.addPostFrameCallback((_) {
      _loadTemplates();
    });
  }

  @override
  void didUpdateWidget(covariant ApprovalTemplatePicker oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (widget.controller.templateSnapshot?.templateId !=
        oldWidget.controller.templateSnapshot?.templateId) {
      setState(() {
        _selectedTemplateId = widget.controller.templateSnapshot?.templateId;
      });
    }
  }

  Future<void> _loadTemplates() async {
    final repository = _repository;
    if (repository == null) {
      setState(() {
        _error = '결재 템플릿 저장소가 등록되지 않아 목록을 불러올 수 없습니다.';
      });
      return;
    }
    setState(() {
      _isLoading = true;
      _error = null;
    });
    try {
      final result = await repository.list(
        page: 1,
        pageSize: 30,
        isActive: true,
      );
      setState(() {
        _templates = result.items;
        if (_selectedTemplateId != null &&
            !_templates.any((template) => template.id == _selectedTemplateId)) {
          _selectedTemplateId = null;
        }
      });
      widget.onTemplatesChanged?.call(result.items);
    } catch (error) {
      final failure = Failure.from(error);
      setState(() {
        _error = failure.describe();
      });
    } finally {
      if (mounted) {
        setState(() => _isLoading = false);
      }
    }
  }

  Future<void> _applyTemplate(BuildContext context) async {
    final repository = _repository;
    final templateId = _selectedTemplateId;
    if (repository == null || templateId == null) {
      return;
    }
    setState(() {
      _isLoading = true;
      _error = null;
    });
    try {
      final detail = await repository.fetchDetail(
        templateId,
        includeSteps: true,
      );
      if (!context.mounted) {
        return;
      }
      if (detail.steps.isEmpty) {
        throw StateError('단계가 없는 템플릿은 적용할 수 없습니다.');
      }
      final steps = detail.steps
          .map(
            (step) => ApprovalRequestStep(
              stepOrder: step.stepOrder,
              approver: ApprovalRequestParticipant(
                id: step.approver.id,
                name: step.approver.name,
                employeeNo: step.approver.employeeNo,
              ),
              note: step.note,
            ),
          )
          .toList(growable: false);
      widget.controller.applyTemplateSteps(steps);
      widget.controller.setTemplateSnapshot(
        ApprovalTemplateSnapshot(
          templateId: detail.id,
          updatedAt: detail.updatedAt,
        ),
      );
      widget.onTemplateApplied?.call(detail);
      SuperportToast.success(context, '템플릿 "${detail.name}"을(를) 적용했습니다.');
    } catch (error) {
      final failure = Failure.from(error);
      if (!mounted) {
        return;
      }
      setState(() {
        _error = failure.describe();
      });
      if (context.mounted) {
        SuperportToast.error(context, failure.describe());
      }
    } finally {
      if (mounted) {
        setState(() => _isLoading = false);
      }
    }
  }

  Future<void> _openTemplatePreview(BuildContext context) async {
    final repository = _repository;
    final templateId = _selectedTemplateId;
    if (repository == null || templateId == null) {
      SuperportToast.info(context, '미리볼 템플릿을 먼저 선택하세요.');
      return;
    }
    try {
      final detail = await repository.fetchDetail(
        templateId,
        includeSteps: true,
      );
      if (!context.mounted) return;
      await showDialog<void>(
        context: context,
        builder: (_) {
          final theme = ShadTheme.of(context);
          return Dialog(
            insetPadding: const EdgeInsets.all(24),
            child: ConstrainedBox(
              constraints: const BoxConstraints(maxWidth: 480),
              child: Padding(
                padding: const EdgeInsets.all(20),
                child: Column(
                  mainAxisSize: MainAxisSize.min,
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text(
                      '템플릿 미리보기',
                      style: theme.textTheme.h4.copyWith(
                        fontWeight: FontWeight.w700,
                      ),
                    ),
                    const SizedBox(height: 12),
                    Text(detail.name, style: theme.textTheme.small),
                    if (detail.description?.isNotEmpty ?? false) ...[
                      const SizedBox(height: 4),
                      Text(detail.description!, style: theme.textTheme.muted),
                    ],
                    const SizedBox(height: 16),
                    if (detail.steps.isEmpty)
                      Text('등록된 단계가 없습니다.', style: theme.textTheme.muted)
                    else
                      Column(
                        children: [
                          for (final step in detail.steps) ...[
                            Row(
                              children: [
                                Container(
                                  width: 36,
                                  height: 36,
                                  decoration: BoxDecoration(
                                    borderRadius: BorderRadius.circular(10),
                                    color: theme.colorScheme.secondary
                                        .withValues(alpha: 0.12),
                                  ),
                                  alignment: Alignment.center,
                                  child: Text(
                                    step.stepOrder.toString(),
                                    style: theme.textTheme.small.copyWith(
                                      fontWeight: FontWeight.w700,
                                    ),
                                  ),
                                ),
                                const SizedBox(width: 12),
                                Expanded(
                                  child: Column(
                                    crossAxisAlignment:
                                        CrossAxisAlignment.start,
                                    children: [
                                      Text(
                                        step.approver.name,
                                        style: theme.textTheme.small.copyWith(
                                          fontWeight: FontWeight.w600,
                                        ),
                                      ),
                                      Text(
                                        '사번 ${step.approver.employeeNo}',
                                        style: theme.textTheme.muted,
                                      ),
                                      if (step.note?.isNotEmpty ?? false)
                                        Text(
                                          step.note!,
                                          style: theme.textTheme.muted,
                                        ),
                                    ],
                                  ),
                                ),
                              ],
                            ),
                            const SizedBox(height: 12),
                          ],
                        ],
                      ),
                    Align(
                      alignment: Alignment.centerRight,
                      child: TextButton(
                        onPressed: () => Navigator.of(context).pop(),
                        child: const Text('닫기'),
                      ),
                    ),
                  ],
                ),
              ),
            ),
          );
        },
      );
    } catch (error) {
      final failure = Failure.from(error);
      if (!context.mounted) {
        return;
      }
      SuperportToast.error(context, failure.describe());
    }
  }

  Future<void> _openSaveTemplateDialog(BuildContext context) async {
    final steps = widget.controller.steps;
    if (steps.isEmpty) {
      SuperportToast.warning(context, '저장할 결재 단계가 없습니다.');
      return;
    }
    final saveUseCase = _saveUseCase;
    if (saveUseCase == null) {
      SuperportToast.error(context, '템플릿 저장 유즈케이스가 등록되지 않았습니다.');
      return;
    }

    final nameController = TextEditingController();
    final codeController = TextEditingController();
    final descriptionController = TextEditingController();
    final noteController = TextEditingController();
    String? errorText;

    await showDialog<bool>(
      context: context,
      barrierDismissible: !_isSaving,
      builder: (dialogContext) {
        final theme = ShadTheme.of(dialogContext);
        return StatefulBuilder(
          builder: (context, setModalState) {
            Future<void> handleSubmit() async {
              if (_isSaving) return;
              final nameText = nameController.text.trim();
              if (nameText.isEmpty) {
                setModalState(() {
                  errorText = '템플릿명을 입력해주세요.';
                });
                return;
              }
              final stepInputs = steps
                  .map(
                    (step) => ApprovalTemplateStepInput(
                      stepOrder: step.stepOrder,
                      approverId: step.approverId,
                      note: step.note,
                    ),
                  )
                  .toList(growable: false);
              final input = ApprovalTemplateInput(
                code: codeController.text.trim().isEmpty
                    ? null
                    : codeController.text.trim(),
                name: nameText,
                description: descriptionController.text.trim().isEmpty
                    ? null
                    : descriptionController.text.trim(),
                note: noteController.text.trim().isEmpty
                    ? null
                    : noteController.text.trim(),
                isActive: true,
              );
              setModalState(() {
                _isSaving = true;
                errorText = null;
              });
              try {
                final template = await saveUseCase.call(
                  templateId: null,
                  input: input,
                  steps: stepInputs,
                );
                if (!context.mounted) return;
                Navigator.of(dialogContext).pop(true);
                if (!context.mounted) return;
                SuperportToast.success(
                  context,
                  '템플릿 "${template.name}"을(를) 저장했습니다.',
                );
                widget.controller.setTemplateSnapshot(
                  ApprovalTemplateSnapshot(
                    templateId: template.id,
                    updatedAt: template.updatedAt,
                  ),
                );
                await _loadTemplates();
                if (mounted) {
                  setState(() {
                    _selectedTemplateId = template.id;
                    _error = null;
                  });
                }
              } catch (error) {
                final failure = Failure.from(error);
                setModalState(() {
                  _isSaving = false;
                  errorText = failure.describe();
                });
                if (context.mounted) {
                  SuperportToast.error(context, failure.describe());
                }
              }
            }

            return Dialog(
              insetPadding: const EdgeInsets.all(24),
              child: ConstrainedBox(
                constraints: const BoxConstraints(maxWidth: 520),
                child: Padding(
                  padding: const EdgeInsets.all(20),
                  child: Column(
                    mainAxisSize: MainAxisSize.min,
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      Text(
                        '템플릿으로 저장',
                        style: theme.textTheme.h4.copyWith(
                          fontWeight: FontWeight.w700,
                        ),
                      ),
                      const SizedBox(height: 12),
                      ShadInput(
                        controller: nameController,
                        placeholder: const Text('템플릿명 (필수)'),
                      ),
                      const SizedBox(height: 12),
                      ShadInput(
                        controller: codeController,
                        placeholder: const Text('템플릿 코드 (선택)'),
                      ),
                      const SizedBox(height: 12),
                      ShadTextarea(
                        controller: descriptionController,
                        minHeight: 80,
                        maxHeight: 160,
                        placeholder: const Text('설명 (선택)'),
                      ),
                      const SizedBox(height: 12),
                      ShadTextarea(
                        controller: noteController,
                        minHeight: 80,
                        maxHeight: 160,
                        placeholder: const Text('비고/안내 문구 (선택)'),
                      ),
                      if (errorText != null) ...[
                        const SizedBox(height: 12),
                        Text(
                          errorText!,
                          style: theme.textTheme.small.copyWith(
                            color: theme.colorScheme.destructive,
                          ),
                        ),
                      ],
                      const SizedBox(height: 20),
                      Row(
                        mainAxisAlignment: MainAxisAlignment.end,
                        children: [
                          TextButton(
                            onPressed: _isSaving
                                ? null
                                : () => Navigator.of(dialogContext).pop(false),
                            child: const Text('취소'),
                          ),
                          const SizedBox(width: 12),
                          ShadButton(
                            onPressed: _isSaving ? null : handleSubmit,
                            child: _isSaving
                                ? const SizedBox(
                                    width: 16,
                                    height: 16,
                                    child: CircularProgressIndicator(
                                      strokeWidth: 2,
                                    ),
                                  )
                                : const Text('저장'),
                          ),
                        ],
                      ),
                    ],
                  ),
                ),
              ),
            );
          },
        );
      },
    );

    nameController.dispose();
    codeController.dispose();
    descriptionController.dispose();
    noteController.dispose();
    if (mounted) {
      setState(() {
        _isSaving = false;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    final theme = ShadTheme.of(context);
    final snapshot = widget.controller.templateSnapshot;
    ApprovalTemplate? selectedTemplate;
    for (final template in _templates) {
      if (template.id == _selectedTemplateId) {
        selectedTemplate = template;
        break;
      }
    }
    final isUpToDate = selectedTemplate == null
        ? true
        : widget.controller.isTemplateUpToDate(selectedTemplate.updatedAt);

    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Row(
          children: [
            Expanded(
              child: ShadSelect<int?>(
                placeholder: const Text('템플릿 선택'),
                initialValue: selectedTemplate?.id,
                enabled: !_isLoading,
                onChanged: (value) {
                  setState(() {
                    _selectedTemplateId = value;
                  });
                },
                selectedOptionBuilder: (context, value) {
                  if (value == null) {
                    return const Text('템플릿 선택');
                  }
                  ApprovalTemplate? match;
                  for (final template in _templates) {
                    if (template.id == value) {
                      match = template;
                      break;
                    }
                  }
                  match ??= selectedTemplate;
                  return Text(match?.name ?? '템플릿 선택');
                },
                options: _templates
                    .map(
                      (template) => ShadOption<int?>(
                        value: template.id,
                        child: Text(template.name),
                      ),
                    )
                    .toList(),
              ),
            ),
            const SizedBox(width: 12),
            ShadButton.outline(
              onPressed: _isLoading ? null : () => _loadTemplates(),
              child: Row(
                mainAxisSize: MainAxisSize.min,
                children: const [
                  Icon(lucide.LucideIcons.refreshCw, size: 16),
                  SizedBox(width: 6),
                  Text('새로고침'),
                ],
              ),
            ),
            const SizedBox(width: 12),
            ShadButton.ghost(
              onPressed: () => _openTemplatePreview(context),
              child: const Text('미리보기'),
            ),
            const SizedBox(width: 12),
            ShadButton(
              onPressed: (_isLoading || _selectedTemplateId == null)
                  ? null
                  : () => _applyTemplate(context),
              child: _isLoading && _selectedTemplateId != null
                  ? const SizedBox(
                      width: 16,
                      height: 16,
                      child: CircularProgressIndicator(strokeWidth: 2),
                    )
                  : const Text('템플릿 적용'),
            ),
          ],
        ),
        const SizedBox(height: 8),
        Row(
          children: [
            ShadButton.outline(
              onPressed: _isSaving
                  ? null
                  : () => _openSaveTemplateDialog(context),
              child: Row(
                mainAxisSize: MainAxisSize.min,
                children: const [
                  Icon(lucide.LucideIcons.save, size: 16),
                  SizedBox(width: 6),
                  Text('현재 단계를 템플릿으로 저장'),
                ],
              ),
            ),
            if (snapshot != null) ...[
              const SizedBox(width: 12),
              Text(
                '선택됨: #${snapshot.templateId}',
                style: theme.textTheme.small,
              ),
            ],
          ],
        ),
        if (_error != null) ...[
          const SizedBox(height: 12),
          Text(
            _error!,
            style: theme.textTheme.small.copyWith(
              color: theme.colorScheme.destructive,
            ),
          ),
        ] else if (selectedTemplate != null) ...[
          const SizedBox(height: 12),
          Text(
            isUpToDate
                ? '템플릿 "${selectedTemplate.name}"이(가) 적용 대기 중입니다.'
                : '템플릿 "${selectedTemplate.name}"이(가) 서버 버전과 달라져 재적용이 필요합니다.',
            style: theme.textTheme.small.copyWith(
              color: isUpToDate
                  ? theme.colorScheme.mutedForeground
                  : theme.colorScheme.destructive,
            ),
          ),
        ],
      ],
    );
  }
}
