import { useMutation, useSuspenseQuery } from '@tanstack/react-query';
import { Link, useNavigate, useParams } from '@tanstack/react-router';
import { useMemo } from 'react';
import z from 'zod';
import { m } from '../../paraglide/messages';
import api from '../../shared/api/api';
import type { Gateway } from '../../shared/api/types';
import { EditPage } from '../../shared/components/EditPage/EditPage';
import { EditPageControls } from '../../shared/components/EditPageControls/EditPageControls';
import { EditPageFormSection } from '../../shared/components/EditPageFormSection/EditPageFormSection';
import { SizedBox } from '../../shared/defguard-ui/components/SizedBox/SizedBox';
import { Snackbar } from '../../shared/defguard-ui/providers/snackbar/snackbar';
import { ThemeSpacing } from '../../shared/defguard-ui/types';
import { useAppForm } from '../../shared/form';
import { formChangeLogic } from '../../shared/formLogic';
import { openModal } from '../../shared/hooks/modalControls/modalsSubjects';
import { ModalName } from '../../shared/hooks/modalControls/modalTypes';
import {
  getGatewayQueryOptions,
  getGatewaysQueryOptions,
  getLocationQueryOptions,
} from '../../shared/query';

export const EditGatewayPage = () => {
  const { gatewayId } = useParams({
    from: '/_authorized/_default/gateway/$gatewayId/edit',
  });
  const { data: gateway } = useSuspenseQuery(getGatewayQueryOptions(Number(gatewayId)));
  const breadcrumbsLinks = [
    <Link key={0} to="/locations">
      {m.gateway_title()}
    </Link>,
    <Link key={1} to="/gateway/$gatewayId/edit" params={{ gatewayId }}>
      {gateway.name}
    </Link>,
  ];
  return (
    <EditPage
      pageTitle={m.gateway_title()}
      links={breadcrumbsLinks}
      headerProps={{ title: m.gateway_edit_title() }}
    >
      <EditGatewayForm gateway={gateway} />
    </EditPage>
  );
};

const EditGatewayForm = ({ gateway }: { gateway: Gateway }) => {
  const navigate = useNavigate();
  const { data: gateways } = useSuspenseQuery(getGatewaysQueryOptions);
  const { data: location } = useSuspenseQuery(
    getLocationQueryOptions(gateway.location_id),
  );

  const isConnected = useMemo(() => {
    if (gateway.connected_at == null) {
      return false;
    }
    if (gateway.disconnected_at == null) {
      return true;
    }
    return gateway.connected_at >= gateway.disconnected_at;
  }, [gateway.connected_at, gateway.disconnected_at]);

  const getDeleteModalContent = () => {
    if (!gateway.enabled) {
      return m.modal_delete_gateway_disabled_body({ name: gateway.name });
    }
    if (!isConnected) {
      return m.modal_delete_gateway_disconnected_body({ name: gateway.name });
    }
    return m.modal_delete_gateway_body({
      name: gateway.name,
      locationName: location.name,
    });
  };

  const { mutateAsync: editGateway } = useMutation({
    mutationFn: api.gateway.editGateway,
    meta: {
      invalidate: ['gateway'],
    },
    onSuccess: () => {
      Snackbar.default(m.gateway_edit_success());
    },
    onError: () => {
      Snackbar.error(m.gateway_edit_failed());
    },
  });

  const formSchema = useMemo(
    () =>
      z.object({
        name: z
          .string(m.form_error_required())
          .min(1, m.form_error_required())
          .refine(
            (val) => val === gateway.name || !gateways?.some((g) => g.name === val),
            m.gateway_edit_error_name_duplicate(),
          ),
        address: z.string().nullable(),
        port: z.number().nullable(),
        connected_at: z.string().nullable(),
        disconnected_at: z.string().nullable(),
        enabled: z.boolean(),
        modified_at: z.string(),
        modified_by: z.string(),
        version: z.string().nullable(),
        location_id: z.number(),
      }),
    [gateways, gateway.name],
  );

  type FormFields = z.infer<typeof formSchema>;

  const defaultValues = useMemo((): FormFields => ({ ...gateway }), [gateway]);

  const form = useAppForm({
    defaultValues,
    validationLogic: formChangeLogic,
    validators: {
      onSubmit: formSchema,
      onChange: formSchema,
    },
    onSubmit: async ({ value }) => {
      await editGateway({
        id: gateway.id,
        name: value.name,
        enabled: value.enabled,
      });
      form.reset(value);
    },
  });

  return (
    <form
      onSubmit={(e) => {
        e.stopPropagation();
        e.preventDefault();
        form.handleSubmit();
      }}
    >
      <form.AppForm>
        <EditPageFormSection label={m.gateway_edit_general_info()}>
          <form.AppField name="name">
            {(field) => (
              <field.FormInput
                required
                label={m.gateway_edit_name()}
                helper={m.gateway_helper_name()}
              />
            )}
          </form.AppField>
          <SizedBox height={ThemeSpacing.Xl2} />
          <form.AppField name="address">
            {(field) => (
              <field.FormInput
                disabled
                label={m.gateway_edit_address()}
                helper={m.gateway_helper_address()}
              />
            )}
          </form.AppField>
          <SizedBox height={ThemeSpacing.Xl2} />
          <form.AppField name="port">
            {(field) => (
              <field.FormInput
                disabled
                label={m.gateway_edit_port()}
                helper={m.gateway_helper_port()}
              />
            )}
          </form.AppField>
          <SizedBox height={ThemeSpacing.Xl2} />
          <form.AppField name="enabled">
            {(field) => <field.FormCheckbox text={m.controls_enable()} />}
          </form.AppField>
          <SizedBox height={ThemeSpacing.Xl2} />
        </EditPageFormSection>
        <form.Subscribe
          selector={(form) => ({
            isSubmitting: form.isSubmitting,
            isDefault: form.isPristine || form.isDefaultValue,
          })}
        >
          {({ isDefault, isSubmitting }) => (
            <EditPageControls
              deleteProps={{
                text: m.gateway_edit_delete(),
                onClick: () => {
                  openModal(ModalName.ConfirmAction, {
                    title: m.modal_delete_gateway_title(),
                    contentMd: getDeleteModalContent(),
                    actionPromise: () => api.gateway.deleteGateway(gateway.id),
                    invalidateKeys: [['gateway'], ['network']],
                    submitProps: { text: m.gateway_edit_delete(), variant: 'critical' },
                    onSuccess: () => {
                      navigate({ to: '/locations', replace: true });
                      Snackbar.default(m.gateway_delete_success());
                    },
                    onError: () => Snackbar.error(m.gateway_delete_failed()),
                  });
                },
                disabled: isSubmitting,
              }}
              submitProps={{
                loading: isSubmitting,
                disabled: isDefault,
                onClick: () => {
                  form.handleSubmit();
                },
              }}
            />
          )}
        </form.Subscribe>
      </form.AppForm>
    </form>
  );
};
