import 'package:auto_route/auto_route.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/extensions/build_context_extensions.dart';
import 'package:immich_mobile/models/shared_link/shared_link.model.dart';
import 'package:immich_mobile/providers/server_info.provider.dart';
import 'package:immich_mobile/providers/shared_link.provider.dart';
import 'package:immich_mobile/services/shared_link.service.dart';
import 'package:immich_mobile/utils/url_helper.dart';
import 'package:immich_mobile/widgets/common/immich_toast.dart';

@RoutePage()
class SharedLinkEditPage extends HookConsumerWidget {
  final SharedLink? existingLink;
  final List<String>? assetsList;
  final String? albumId;

  const SharedLinkEditPage({super.key, this.existingLink, this.assetsList, this.albumId});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    const padding = 20.0;
    final themeData = context.themeData;
    final colorScheme = context.colorScheme;
    final descriptionController = useTextEditingController(text: existingLink?.description ?? "");
    final descriptionFocusNode = useFocusNode();
    final passwordController = useTextEditingController(text: existingLink?.password ?? "");
    final slugController = useTextEditingController(text: existingLink?.slug ?? "");
    final slugFocusNode = useFocusNode();
    final showMetadata = useState(existingLink?.showMetadata ?? true);
    final allowDownload = useState(existingLink?.allowDownload ?? true);
    final allowUpload = useState(existingLink?.allowUpload ?? false);
    final editExpiry = useState(false);
    final expiryAfter = useState(0);
    final newShareLink = useState("");

    Widget buildLinkTitle() {
      if (existingLink != null) {
        if (existingLink!.type == SharedLinkSource.album) {
          return Row(
            children: [
              const Text('public_album', style: TextStyle(fontWeight: FontWeight.bold)).tr(),
              const Text(" | ", style: TextStyle(fontWeight: FontWeight.bold)),
              Text(
                existingLink!.title,
                style: TextStyle(color: colorScheme.primary, fontWeight: FontWeight.bold),
              ),
            ],
          );
        }

        if (existingLink!.type == SharedLinkSource.individual) {
          return Row(
            children: [
              const Text('shared_link_individual_shared', style: TextStyle(fontWeight: FontWeight.bold)).tr(),
              const Text(" | ", style: TextStyle(fontWeight: FontWeight.bold)),
              Expanded(
                child: Text(
                  existingLink!.description ?? "--",
                  style: TextStyle(color: colorScheme.primary, fontWeight: FontWeight.bold),
                  overflow: TextOverflow.ellipsis,
                ),
              ),
            ],
          );
        }
      }

      return const Text("create_link_to_share_description", style: TextStyle(fontWeight: FontWeight.bold)).tr();
    }

    Widget buildDescriptionField() {
      return TextField(
        controller: descriptionController,
        enabled: newShareLink.value.isEmpty,
        focusNode: descriptionFocusNode,
        textInputAction: TextInputAction.done,
        autofocus: false,
        decoration: InputDecoration(
          labelText: 'description'.tr(),
          labelStyle: TextStyle(fontWeight: FontWeight.bold, color: colorScheme.primary),
          floatingLabelBehavior: FloatingLabelBehavior.always,
          border: const OutlineInputBorder(),
          hintText: 'shared_link_edit_description_hint'.tr(),
          hintStyle: const TextStyle(fontWeight: FontWeight.normal, fontSize: 14),
          disabledBorder: OutlineInputBorder(borderSide: BorderSide(color: Colors.grey.withValues(alpha: 0.5))),
        ),
        onTapOutside: (_) => descriptionFocusNode.unfocus(),
      );
    }

    Widget buildPasswordField() {
      return TextField(
        controller: passwordController,
        enabled: newShareLink.value.isEmpty,
        autofocus: false,
        decoration: InputDecoration(
          labelText: 'password'.tr(),
          labelStyle: TextStyle(fontWeight: FontWeight.bold, color: colorScheme.primary),
          floatingLabelBehavior: FloatingLabelBehavior.always,
          border: const OutlineInputBorder(),
          hintText: 'shared_link_edit_password_hint'.tr(),
          hintStyle: const TextStyle(fontWeight: FontWeight.normal, fontSize: 14),
          disabledBorder: OutlineInputBorder(borderSide: BorderSide(color: Colors.grey.withValues(alpha: 0.5))),
        ),
      );
    }

    Widget buildSlugField() {
      return TextField(
        controller: slugController,
        enabled: newShareLink.value.isEmpty,
        focusNode: slugFocusNode,
        textInputAction: TextInputAction.done,
        autofocus: false,
        decoration: InputDecoration(
          labelText: 'custom_url'.tr(),
          labelStyle: TextStyle(fontWeight: FontWeight.bold, color: colorScheme.primary),
          floatingLabelBehavior: FloatingLabelBehavior.always,
          border: const OutlineInputBorder(),
          hintText: 'custom_url'.tr(),
          hintStyle: const TextStyle(fontWeight: FontWeight.normal, fontSize: 14),
          disabledBorder: OutlineInputBorder(borderSide: BorderSide(color: Colors.grey.withValues(alpha: 0.5))),
        ),
        onTapOutside: (_) => slugFocusNode.unfocus(),
      );
    }

    Widget buildShowMetaButton() {
      return SwitchListTile.adaptive(
        value: showMetadata.value,
        onChanged: newShareLink.value.isEmpty ? (value) => showMetadata.value = value : null,
        activeThumbColor: colorScheme.primary,
        dense: true,
        title: Text("show_metadata", style: themeData.textTheme.labelLarge?.copyWith(fontWeight: FontWeight.bold)).tr(),
      );
    }

    Widget buildAllowDownloadButton() {
      return SwitchListTile.adaptive(
        value: allowDownload.value,
        onChanged: newShareLink.value.isEmpty ? (value) => allowDownload.value = value : null,
        activeThumbColor: colorScheme.primary,
        dense: true,
        title: Text(
          "allow_public_user_to_download",
          style: themeData.textTheme.labelLarge?.copyWith(fontWeight: FontWeight.bold),
        ).tr(),
      );
    }

    Widget buildAllowUploadButton() {
      return SwitchListTile.adaptive(
        value: allowUpload.value,
        onChanged: newShareLink.value.isEmpty ? (value) => allowUpload.value = value : null,
        activeThumbColor: colorScheme.primary,
        dense: true,
        title: Text(
          "allow_public_user_to_upload",
          style: themeData.textTheme.labelLarge?.copyWith(fontWeight: FontWeight.bold),
        ).tr(),
      );
    }

    Widget buildEditExpiryButton() {
      return SwitchListTile.adaptive(
        value: editExpiry.value,
        onChanged: newShareLink.value.isEmpty ? (value) => editExpiry.value = value : null,
        activeThumbColor: colorScheme.primary,
        dense: true,
        title: Text(
          "change_expiration_time",
          style: themeData.textTheme.labelLarge?.copyWith(fontWeight: FontWeight.bold),
        ).tr(),
      );
    }

    Widget buildExpiryAfterButton() {
      return DropdownMenu(
        label: Text(
          "expire_after",
          style: TextStyle(fontWeight: FontWeight.bold, color: colorScheme.primary),
        ).tr(),
        enableSearch: false,
        enableFilter: false,
        width: context.width - 40,
        initialSelection: expiryAfter.value,
        enabled: newShareLink.value.isEmpty && (existingLink == null || editExpiry.value),
        onSelected: (value) {
          expiryAfter.value = value!;
        },
        dropdownMenuEntries: [
          DropdownMenuEntry(value: 0, label: "never".tr()),
          DropdownMenuEntry(
            value: 30,
            label: "shared_link_edit_expire_after_option_minutes".tr(namedArgs: {'count': "30"}),
          ),
          DropdownMenuEntry(value: 60, label: "shared_link_edit_expire_after_option_hour".tr()),
          DropdownMenuEntry(
            value: 60 * 6,
            label: "shared_link_edit_expire_after_option_hours".tr(namedArgs: {'count': "6"}),
          ),
          DropdownMenuEntry(value: 60 * 24, label: "shared_link_edit_expire_after_option_day".tr()),
          DropdownMenuEntry(
            value: 60 * 24 * 7,
            label: "shared_link_edit_expire_after_option_days".tr(namedArgs: {'count': "7"}),
          ),
          DropdownMenuEntry(
            value: 60 * 24 * 30,
            label: "shared_link_edit_expire_after_option_days".tr(namedArgs: {'count': "30"}),
          ),
          DropdownMenuEntry(
            value: 60 * 24 * 30 * 3,
            label: "shared_link_edit_expire_after_option_months".tr(namedArgs: {'count': "3"}),
          ),
          DropdownMenuEntry(
            value: 60 * 24 * 30 * 12,
            label: "shared_link_edit_expire_after_option_year".tr(namedArgs: {'count': "1"}),
          ),
        ],
      );
    }

    void copyLinkToClipboard() {
      Clipboard.setData(ClipboardData(text: newShareLink.value)).then((_) {
        context.scaffoldMessenger.showSnackBar(
          SnackBar(
            content: Text(
              "shared_link_clipboard_copied_massage",
              style: context.textTheme.bodyLarge?.copyWith(color: context.primaryColor),
            ).tr(),
            duration: const Duration(seconds: 2),
          ),
        );
      });
    }

    Widget buildNewLinkField() {
      return Column(
        children: [
          const Padding(padding: EdgeInsets.only(top: 20, bottom: 20), child: Divider()),
          TextFormField(
            readOnly: true,
            initialValue: newShareLink.value,
            decoration: InputDecoration(
              border: const OutlineInputBorder(),
              enabledBorder: themeData.inputDecorationTheme.focusedBorder,
              suffixIcon: IconButton(onPressed: copyLinkToClipboard, icon: const Icon(Icons.copy)),
            ),
          ),
          Padding(
            padding: const EdgeInsets.only(top: 16.0),
            child: Align(
              alignment: Alignment.bottomRight,
              child: ElevatedButton(
                onPressed: () {
                  context.maybePop();
                },
                child: const Text("done", style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold)).tr(),
              ),
            ),
          ),
        ],
      );
    }

    DateTime calculateExpiry() {
      return DateTime.now().add(Duration(minutes: expiryAfter.value));
    }

    Future<void> handleNewLink() async {
      final newLink = await ref
          .read(sharedLinkServiceProvider)
          .createSharedLink(
            albumId: albumId,
            assetIds: assetsList,
            showMeta: showMetadata.value,
            allowDownload: allowDownload.value,
            allowUpload: allowUpload.value,
            description: descriptionController.text.isEmpty ? null : descriptionController.text,
            password: passwordController.text.isEmpty ? null : passwordController.text,
            slug: slugController.text.isEmpty ? null : slugController.text,
            expiresAt: expiryAfter.value == 0 ? null : calculateExpiry(),
          );
      ref.invalidate(sharedLinksStateProvider);

      await ref.read(serverInfoProvider.notifier).getServerConfig();
      final externalDomain = ref.read(serverInfoProvider.select((s) => s.serverConfig.externalDomain));

      var serverUrl = externalDomain.isNotEmpty ? externalDomain : getServerUrl();
      if (serverUrl != null && !serverUrl.endsWith('/')) {
        serverUrl += '/';
      }

      if (newLink != null && serverUrl != null) {
        final hasSlug = newLink.slug?.isNotEmpty == true;
        final urlPath = hasSlug ? newLink.slug : newLink.key;
        final basePath = hasSlug ? 's' : 'share';
        newShareLink.value = "$serverUrl$basePath/$urlPath";
        copyLinkToClipboard();
      } else if (newLink == null) {
        ImmichToast.show(
          context: context,
          gravity: ToastGravity.BOTTOM,
          toastType: ToastType.error,
          msg: 'shared_link_create_error'.tr(),
        );
      }
    }

    Future<void> handleEditLink() async {
      bool? download;
      bool? upload;
      bool? meta;
      String? desc;
      String? password;
      String? slug;
      DateTime? expiry;
      bool? changeExpiry;

      if (allowDownload.value != existingLink!.allowDownload) {
        download = allowDownload.value;
      }

      if (allowUpload.value != existingLink!.allowUpload) {
        upload = allowUpload.value;
      }

      if (showMetadata.value != existingLink!.showMetadata) {
        meta = showMetadata.value;
      }

      if (descriptionController.text != existingLink!.description) {
        desc = descriptionController.text;
      }

      if (passwordController.text != existingLink!.password) {
        password = passwordController.text;
      }

      if (slugController.text != (existingLink!.slug ?? "")) {
        slug = slugController.text.isEmpty ? null : slugController.text;
      } else {
        slug = existingLink!.slug;
      }

      if (editExpiry.value) {
        expiry = expiryAfter.value == 0 ? null : calculateExpiry();
        changeExpiry = true;
      }

      await ref
          .read(sharedLinkServiceProvider)
          .updateSharedLink(
            existingLink!.id,
            showMeta: meta,
            allowDownload: download,
            allowUpload: upload,
            description: desc,
            password: password,
            slug: slug,
            expiresAt: expiry,
            changeExpiry: changeExpiry,
          );
      ref.invalidate(sharedLinksStateProvider);
      await context.maybePop();
    }

    return Scaffold(
      appBar: AppBar(
        title: Text(existingLink == null ? "create_link_to_share" : "edit_link").tr(),
        elevation: 0,
        leading: const CloseButton(),
        centerTitle: false,
      ),
      body: SafeArea(
        child: ListView(
          children: [
            Padding(padding: const EdgeInsets.all(padding), child: buildLinkTitle()),
            Padding(padding: const EdgeInsets.all(padding), child: buildDescriptionField()),
            Padding(padding: const EdgeInsets.all(padding), child: buildPasswordField()),
            Padding(padding: const EdgeInsets.all(padding), child: buildSlugField()),
            Padding(
              padding: const EdgeInsets.only(left: padding, right: padding, bottom: padding),
              child: buildShowMetaButton(),
            ),
            Padding(
              padding: const EdgeInsets.only(left: padding, right: padding, bottom: padding),
              child: buildAllowDownloadButton(),
            ),
            Padding(
              padding: const EdgeInsets.only(left: padding, right: 20, bottom: 20),
              child: buildAllowUploadButton(),
            ),
            if (existingLink != null)
              Padding(
                padding: const EdgeInsets.only(left: padding, right: padding, bottom: padding),
                child: buildEditExpiryButton(),
              ),
            Padding(
              padding: const EdgeInsets.only(left: padding, right: padding, bottom: padding),
              child: buildExpiryAfterButton(),
            ),
            if (newShareLink.value.isEmpty)
              Align(
                alignment: Alignment.bottomRight,
                child: Padding(
                  padding: const EdgeInsets.only(right: padding + 10, bottom: padding),
                  child: ElevatedButton(
                    onPressed: existingLink != null ? handleEditLink : handleNewLink,
                    child: Text(
                      existingLink != null ? "shared_link_edit_submit_button" : "create_link",
                      style: const TextStyle(fontSize: 14, fontWeight: FontWeight.bold),
                    ).tr(),
                  ),
                ),
              ),
            if (newShareLink.value.isNotEmpty)
              Padding(
                padding: const EdgeInsets.only(left: padding, right: padding, bottom: padding),
                child: buildNewLinkField(),
              ),
          ],
        ),
      ),
    );
  }
}
