/**
 * This file is part of the NocoBase (R) project.
 * Copyright (c) 2020-2024 NocoBase Co., Ltd.
 * Authors: NocoBase Team.
 *
 * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
 * For more information, please refer to: https://www.nocobase.com/agreement.
 */

import { SchemaComponent } from '@nocobase/client';
import { ISchema } from '@formily/react';
import React, { useMemo } from 'react';
import { uid } from '@formily/shared';
import { useAuthTranslation } from '../locale';
import { useAPIClient } from '@nocobase/client';
import { useForm } from '@formily/react';
import { useNavigate, Navigate } from 'react-router-dom';
import { message } from 'antd';
import { useTranslation } from 'react-i18next';
import { useAuthenticator } from '../authenticator';

export interface UseSignupProps {
  authenticator?: string;
  message?: {
    success?: string;
  };
}

const schemas = {
  username: {
    type: 'string',
    'x-component': 'Input',
    'x-validator': { username: true },
    'x-decorator': 'FormItem',
    'x-component-props': { placeholder: '{{t("Username")}}', style: {} },
  },
  email: {
    type: 'string',
    'x-component': 'Input',
    'x-validator': 'email',
    'x-decorator': 'FormItem',
    'x-component-props': { placeholder: '{{t("Email")}}', style: {} },
  },
};

export const useSignUp = (props?: UseSignupProps) => {
  const navigate = useNavigate();
  const form = useForm();
  const api = useAPIClient();
  const { t } = useTranslation();
  return {
    async run() {
      await form.submit();
      await api.auth.signUp(form.values, props?.authenticator);
      message.success(props?.message?.success || t('Sign up successfully, and automatically jump to the sign in page'));
      setTimeout(() => {
        navigate('/signin');
      }, 2000);
    },
  };
};

const getSignupPageSchema = (fieldSchemas: any): ISchema => ({
  type: 'object',
  name: uid(),
  'x-component': 'FormV2',
  properties: {
    ...fieldSchemas,
    password: {
      type: 'string',
      required: true,
      'x-component': 'Password',
      'x-decorator': 'FormItem',
      'x-component-props': { placeholder: '{{t("Password")}}', checkStrength: true, style: {} },
      'x-reactions': [
        {
          dependencies: ['.confirm_password'],
          fulfill: {
            state: {
              selfErrors: '{{$deps[0] && $self.value && $self.value !== $deps[0] ? t("Password mismatch") : ""}}',
            },
          },
        },
      ],
    },
    confirm_password: {
      type: 'string',
      required: true,
      'x-component': 'Password',
      'x-decorator': 'FormItem',
      'x-component-props': { placeholder: '{{t("Confirm password")}}', style: {} },
      'x-reactions': [
        {
          dependencies: ['.password'],
          fulfill: {
            state: {
              selfErrors: '{{$deps[0] && $self.value && $self.value !== $deps[0] ? t("Password mismatch") : ""}}',
            },
          },
        },
      ],
    },
    actions: {
      type: 'void',
      'x-component': 'div',
      properties: {
        submit: {
          title: '{{t("Sign up")}}',
          type: 'void',
          'x-component': 'Action',
          'x-component-props': {
            block: true,
            type: 'primary',
            htmlType: 'submit',
            useAction: '{{ useBasicSignUp }}',
            style: { width: '100%' },
          },
        },
      },
    },
    link: {
      type: 'void',
      'x-component': 'div',
      properties: {
        link: {
          type: 'void',
          'x-component': 'Link',
          'x-component-props': { to: '/signin' },
          'x-content': '{{t("Log in with an existing account")}}',
        },
      },
    },
  },
});

export const SignUpForm = ({ authenticatorName: name }: { authenticatorName: string }) => {
  const { t } = useAuthTranslation();
  const useBasicSignUp = () => {
    return useSignUp({ authenticator: name });
  };
  const authenticator = useAuthenticator(name);
  const { options } = authenticator;
  let { signupForm } = options;
  if (!(signupForm?.length && signupForm.some((item: any) => item.show && item.required))) {
    signupForm = [{ field: 'username', show: true, required: true }];
  }
  const fieldSchemas = useMemo(() => {
    return signupForm
      .filter((field: { show: boolean }) => field.show)
      .reduce((prev: any, item: { field: string; required: boolean }) => {
        const field = item.field;
        if (schemas[field]) {
          prev[field] = schemas[field];
          if (item.required) {
            prev[field].required = true;
          }
          return prev;
        }
      }, {});
  }, [signupForm]);
  if (!options?.allowSignUp) {
    return <Navigate to="/not-found" replace={true} />;
  }
  const schema = getSignupPageSchema(fieldSchemas);
  return <SchemaComponent schema={schema} scope={{ useBasicSignUp, t }} />;
};
