import 'dart:convert' show base64Decode;

import 'package:flutter/material.dart';
import 'package:fotodocumentation/controller/base_controller.dart';
import 'package:fotodocumentation/controller/customer_controller.dart';
import 'package:fotodocumentation/controller/picture_controller.dart';
import 'package:fotodocumentation/dto/customer_dto.dart';
import 'package:fotodocumentation/dto/picture_dto.dart';
import 'package:fotodocumentation/l10n/app_localizations.dart';
import 'package:fotodocumentation/pages/ui_utils/component/customer_back_button.dart';
import 'package:fotodocumentation/pages/customer/picture_fullscreen_dialog.dart';
import 'package:fotodocumentation/pages/ui_utils/component/general_error_widget.dart';
import 'package:fotodocumentation/pages/ui_utils/component/page_header_widget.dart';
import 'package:fotodocumentation/pages/ui_utils/component/waiting_widget.dart';
import 'package:fotodocumentation/pages/ui_utils/general_style.dart';
import 'package:fotodocumentation/utils/di_container.dart';
import 'package:fotodocumentation/utils/global_router.dart';
import 'package:intl/intl.dart';

class PictureWidget extends StatefulWidget {
  final int customerId;
  final int pictureId;
  const PictureWidget({super.key, required this.customerId, required this.pictureId});

  @override
  State<PictureWidget> createState() => _PictureWidgetState();
}

class _PictureWidgetState extends State<PictureWidget> {
  GeneralStyle get _generalStyle => DiContainer.get();
  CustomerController get _customerController => DiContainer.get();
  PictureController get _pictureController => DiContainer.get();

  late CustomerDto _customerDto;
  PictureDto? _selectedPicture;
  late DateFormat _dateFormat;
  final ScrollController _commentScrollController = ScrollController();

  late Future<CustomerDto?> _dto;

  @override
  void initState() {
    super.initState();
    _dateFormat = DateFormat('dd.MM.yyyy, hh:mm');
    _dto = _customerController.get(id: widget.customerId);
  }

  @override
  void dispose() {
    _commentScrollController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
        color: _generalStyle.pageBackgroundColor,
        child: Padding(
          padding: const EdgeInsets.only(top: 8.0, left: 50.0, right: 50.0, bottom: 8.0),
          child: _future(context),
        ),
      ),
    );
  }

  Widget _future(BuildContext context) {
    return FutureBuilder<CustomerDto?>(
      future: _dto,
      builder: (BuildContext context, AsyncSnapshot<CustomerDto?> snapshot) {
        if (snapshot.connectionState != ConnectionState.done) {
          return const WaitingWidget();
        }
        if (snapshot.hasData) {
          CustomerDto? dto = snapshot.data;
          if (dto == null) {
            return GeneralErrorWidget(error: "FIXME"); // FIXME: set error text data not found
          }
          _customerDto = dto;
          _selectedPicture ??= dto.pictures.firstWhere((p) => p.id == widget.pictureId);
          _selectedPicture ??= _customerDto.pictures.firstOrNull;
          if (_selectedPicture == null) {
            return GeneralErrorWidget(error: "FIXME"); // FIXME: set error text data not found
          }
          return _body(context, _selectedPicture!);
        } else if (snapshot.hasError) {
          var error = snapshot.error;
          return (error is ServerError) ? GeneralErrorWidget.fromServerError(error) : GeneralErrorWidget(error: snapshot.error.toString());
        }
        return const WaitingWidget();
      },
    );
  }

  Widget _body(BuildContext context, PictureDto selectedPicture) {
    final pictures = _customerDto.pictures;
    return Column(
      mainAxisAlignment: MainAxisAlignment.start,
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        PageHeaderWidget(text: _customerDto.name),
        CustomerBackButton(path: GlobalRouter.pathCustomer),
        const SizedBox(height: 24),
        Expanded(
          child: _mainWidget(context, selectedPicture),
        ),
        _bottomNavigationWidget(pictures, selectedPicture),
      ],
    );
  }

  Widget _mainWidget(BuildContext context, PictureDto selectedPicture) {
    return LayoutBuilder(
      builder: (context, constraints) {
        final isNarrow = constraints.maxWidth < 800;
        return SingleChildScrollView(
          child: isNarrow
              ? Column(
                  mainAxisAlignment: MainAxisAlignment.start,
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    _imageWidget(selectedPicture),
                    const SizedBox(height: 32),
                    _contentWidget(selectedPicture),
                  ],
                )
              : Row(
                  mainAxisAlignment: MainAxisAlignment.start,
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    _imageWidget(selectedPicture),
                    const SizedBox(width: 32),
                    Expanded(child: _contentWidget(selectedPicture)),
                  ],
                ),
        );
      },
    );
  }

  Widget _imageWidget(PictureDto dto) {
    return GestureDetector(
      key: const Key("image"),
      behavior: HitTestBehavior.opaque,
      onTap: () => _showFullscreenImage(dto),
      child: MouseRegion(
        cursor: SystemMouseCursors.click,
        child: ConstrainedBox(
          constraints: const BoxConstraints(minWidth: 100, minHeight: 100),
          child: Image.memory(
            base64Decode(dto.image),
            fit: BoxFit.contain,
          ),
        ),
      ),
    );
  }

  void _showFullscreenImage(PictureDto dto) {
    showDialog(
      context: context,
      builder: (BuildContext context) {
        return PictureFullscreenDialog(dto: dto);
      },
    );
  }

  Widget _contentWidget(PictureDto dto) {
    final labelStyle = TextStyle(
      fontWeight: FontWeight.normal,
      fontSize: 16,
      fontFamily: _generalStyle.fontFamily,
      color: _generalStyle.primaryTextLabelColor,
    );

    final contentStyle = TextStyle(
      fontWeight: FontWeight.bold,
      fontSize: 16,
      fontFamily: _generalStyle.fontFamily,
      color: _generalStyle.secondaryTextLabelColor,
    );

    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Text(
          _dateFormat.format(dto.pictureDate),
          style: TextStyle(
            fontWeight: FontWeight.bold,
            fontSize: 44,
            fontFamily: _generalStyle.fontFamily,
            color: _generalStyle.primaryTextLabelColor,
          ),
        ),
        const SizedBox(height: 20),
        Row(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Expanded(
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text(
                    AppLocalizations.of(context)!.pictureWidgetLabelCustomerNumber,
                    style: labelStyle,
                  ),
                  Padding(
                    padding: const EdgeInsets.only(top: 4.0),
                    child: Text(
                      _customerDto.customerNumber,
                      style: contentStyle,
                    ),
                  ),
                  Text(
                    AppLocalizations.of(context)!.pictureWidgetLabelZip,
                    style: labelStyle,
                  ),
                  Padding(
                    padding: const EdgeInsets.only(top: 4.0),
                    child: Text(
                      _customerDto.zip ?? "",
                      style: contentStyle,
                    ),
                  ),
                  Text(
                    AppLocalizations.of(context)!.pictureWidgetLabelCity,
                    style: labelStyle,
                  ),
                  Padding(
                    padding: const EdgeInsets.only(top: 4.0),
                    child: Text(
                      _customerDto.city ?? "",
                      style: contentStyle,
                    ),
                  ),
                  Padding(
                    padding: const EdgeInsets.only(top: 20.0),
                    child: Text(
                      AppLocalizations.of(context)!.pictureWidgetLabelComment,
                      style: labelStyle,
                    ),
                  ),
                  Padding(
                    padding: const EdgeInsets.only(top: 4.0),
                    child: SizedBox(
                      width: double.infinity,
                      height: 150,
                      child: Scrollbar(
                        controller: _commentScrollController,
                        thumbVisibility: true,
                        child: SingleChildScrollView(
                          controller: _commentScrollController,
                          padding: const EdgeInsets.all(8.0),
                          child: Text(
                            dto.comment ?? "",
                            style: contentStyle,
                          ),
                        ),
                      ),
                    ),
                  ),
                ],
              ),
            ),
            const SizedBox(width: 24),
            _evaluationCard(dto),
          ],
        ),
      ],
    );
  }

  Widget _evaluationCard(PictureDto dto) {
    return Card(
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.circular(12),
      ),
      child: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            Text(
              AppLocalizations.of(context)!.pictureWidgetLabelEvaluation,
              style: TextStyle(
                fontWeight: FontWeight.normal,
                fontSize: 16,
                fontFamily: _generalStyle.fontFamily,
                color: _generalStyle.primaryTextLabelColor,
              ),
            ),
            const SizedBox(height: 16),
            Row(
              mainAxisSize: MainAxisSize.min,
              children: [
                _evaluationCircle(
                  key: const Key("evaluation_good"),
                  color: _generalStyle.evaluationGoodColor,
                  value: 1,
                  selected: dto.evaluation == 1,
                ),
                const SizedBox(width: 12),
                _evaluationCircle(
                  key: const Key("evaluation_middle"),
                  color: _generalStyle.evaluationMiddleColor,
                  value: 2,
                  selected: dto.evaluation == 2,
                ),
                const SizedBox(width: 12),
                _evaluationCircle(
                  key: const Key("evaluation_bad"),
                  color: _generalStyle.evaluationBadColor,
                  value: 3,
                  selected: dto.evaluation == 3,
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }

  Widget _evaluationCircle({
    required Key key,
    required Color color,
    required int value,
    required bool selected,
  }) {
    return InkWell(
      key: key,
      onTap: () async => _actionUpdateEvaluation(value),
      customBorder: const CircleBorder(),
      child: Container(
        width: 32,
        height: 32,
        decoration: BoxDecoration(
          color: color,
          shape: BoxShape.circle,
          border: selected ? Border.all(color: _generalStyle.secondaryWidgetBackgroundColor, width: 3) : null,
        ),
      ),
    );
  }

  // Bottom navigation buttons
  Widget _bottomNavigationWidget(List<PictureDto> pictures, PictureDto selectedPicture) {
    final currentIndex = pictures.indexWhere((p) => p.id == selectedPicture.id);
    final hasPrevious = currentIndex > 0;
    final hasNext = currentIndex < pictures.length - 1;

    return Padding(
      padding: const EdgeInsets.only(bottom: 24.0),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          // Previous button
          IconButton(
            key: Key("navigate_left"),
            onPressed: hasPrevious ? () => _actionNavigateToPicture(currentIndex - 1) : null,
            icon: Icon(Icons.chevron_left, color: _generalStyle.nextTextColor, size: 32),
          ),
          const SizedBox(width: 24),
          // Picture counter text
          Row(
            mainAxisSize: MainAxisSize.min,
            children: [
              Container(
                padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
                decoration: BoxDecoration(
                  color: Colors.white,
                  borderRadius: BorderRadius.circular(8),
                ),
                child: Text(
                  '${currentIndex + 1}',
                  style: TextStyle(
                    fontFamily: _generalStyle.fontFamily,
                    fontSize: 16,
                    fontWeight: FontWeight.bold,
                    color: _generalStyle.nextTextColor,
                  ),
                ),
              ),
              const SizedBox(width: 8),
              Text(
                'von ${pictures.length}',
                style: TextStyle(
                  fontFamily: _generalStyle.fontFamily,
                  fontSize: 16,
                  fontWeight: FontWeight.normal,
                  color: _generalStyle.nextTextColor,
                ),
              ),
            ],
          ),
          const SizedBox(width: 24),
          // Next button
          IconButton(
            key: Key("navigate_right"),
            onPressed: hasNext ? () => _actionNavigateToPicture(currentIndex + 1) : null,
            icon: Icon(Icons.chevron_right, color: _generalStyle.nextTextColor, size: 32),
          ),
        ],
      ),
    );
  }

  Future<void> _actionUpdateEvaluation(int value) async {
    _selectedPicture?.evaluation = value;
    _pictureController.updateEvaluation(_selectedPicture!);
    setState(() {});
  }

  void _actionNavigateToPicture(int index) {
    final pictures = _customerDto.pictures;
    if (index >= 0 && index < pictures.length) {
      setState(() {
        _selectedPicture = pictures[index];
      });
    }
  }
}
