import * as React from 'react';
import { createRoot } from 'react-dom/client';
import { useForm } from '@tanstack/react-form';
import { z } from 'zod';
import { FieldError } from './field-error';
import './index.css';

interface Role {
  external: External;
  name: string;
}

interface Person {
  name: string;
  age: number;
  roles: Role[];
}

enum External {
  True = 'true',
  False = 'false',
}

const defaultPerson: Person = {
  name: 'John Doe',
  age: 30,
  roles: [
    { name: 'Admin', external: External.False },
    { name: 'User', external: External.False },
  ],
};

const roles: Role[] = [
  { name: 'Admin', external: External.False },
  { name: 'User', external: External.False },
];

function App() {
  const form = useForm({
    defaultValues: defaultPerson,
    onSubmit({ value }) {
      alert(JSON.stringify(value));
    },
  });

  return (
    <div>
      <form
        onSubmit={(e) => {
          e.preventDefault();
          e.stopPropagation();
          form.handleSubmit();
        }}
      >
        <form.Field
          name="roles"
          mode="array"
          validators={{
            onChange: z
              .array(
                z.object({
                  external: z.nativeEnum(External, {
                    required_error: 'role.external is required',
                  }),
                  name: z.string({ required_error: 'role.name is required' }),
                })
              )
              .min(1, 'Minimum 1 role should be selected'),
          }}
        >
          {(field) => {
            return (
              <>
                {roles.map((role, idx) => (
                  <React.Fragment key={idx}>
                    <form.Field name={`roles[${idx}].name`}>
                      {(subField) => (
                        <div className="checkbox">
                          <label htmlFor={`input-${idx}`}>{role.name}</label>
                          <input
                            className="switch"
                            id={`input-${idx}`}
                            type="checkbox"
                            checked={field.state.value.some(
                              (stateRole) => stateRole.name === role.name
                            )}
                            name={subField.state.value}
                            onBlur={subField.handleBlur}
                            onChange={(event) => {
                              if (event.target.checked) {
                                field.pushValue(role);
                              } else {
                                const roleIdx = field.state.value.findIndex(
                                  (stateRole) => stateRole.name === role.name
                                );
                                field.removeValue(roleIdx);
                              }
                            }}
                            value={role.name}
                          />
                        </div>
                      )}
                    </form.Field>
                  </React.Fragment>
                ))}
                <FieldError field={field} />
              </>
            );
          }}
        </form.Field>
        <form.Subscribe
          selector={(state) => [state.canSubmit, state.isSubmitting]}
          children={([canSubmit, isSubmitting]) => (
            <button
              type="submit"
              disabled={!canSubmit}
              className="submit-button"
            >
              {isSubmitting ? '...' : 'Submit'}
            </button>
          )}
        />
        <form.Subscribe selector={(state) => state.values}>
          {(values) => (
            <>
              <button
                type="button"
                className="submit-button"
                style={{ marginLeft: '8px' }}
                onClick={() => {
                  console.log(values);
                }}
              >
                Log
              </button>
              <pre style={{ marginBottom: '1rem' }}>
                <code>{JSON.stringify(values, null, 4)}</code>
              </pre>
            </>
          )}
        </form.Subscribe>
      </form>
    </div>
  );
}

const rootElement = document.getElementById('root')!;

createRoot(rootElement).render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);
