import { createForm } from '@felte/solid';
import { Component, createSignal, Match, Switch } from 'solid-js';
import { TextField, Button, Dialog } from '@kobalte/core';

import './style.css';
import { createServerAction$ } from 'solid-start/server';
import PouchDb from 'pouchdb';
import { v4 as uuid } from 'uuid';
import { put } from '~/lib/db';
import { useNavigate } from 'solid-start';
import { toHex } from '~/lib/to-hex';
import { cloneDeep } from 'lodash';

interface Props {
  values?: any;
}

const Invitation: Component<Props> = (props) => {
  const navigate = useNavigate();

  const [openDialog, setOpenDialog] = createSignal(false);

  const [status, setStatus] = createSignal<string>();

  const [saving, save] = createServerAction$(async (args: any) => {
    const { props, values } = args;
    console.log({
      caller: 'Invitation / save',
      props,
      values,
      args,
      id: props.values?._id,
    });
    const db = new PouchDb('.db');
    const id = props.values?._id ?? `invitation/${uuid()}`;
    await put({
      db,
      doc: {
        _id: id,
        date: new Date().toISOString(),
        type: 'invitation',
        ...values,
      },
    });
    return id;
  });

  const [dbChecking, dbCheck] = createServerAction$(async (args: any) => {
    console.log({
      caller: 'Invitation / dbCheck',
      args,
    });
    let baseDbInfoAuth;
    try {
      const baseDb = new PouchDb(cloneDeep(args));
      baseDbInfoAuth = await baseDb.info();
    } catch (error) {
      baseDbInfoAuth = { error };
    }
    let baseDbInfoAnon;
    try {
      const baseDb = new PouchDb(args.name);
      baseDbInfoAnon = await baseDb.info();
    } catch (error) {
      baseDbInfoAnon = { error };
    }
    const name = `${args.name}/userdb-${toHex(args.auth.username)}`;
    let userDbInfo;
    try {
      const userDb = new PouchDb({ ...args, name });
      userDbInfo = await userDb.info();
    } catch (error) {
      userDbInfo = { error };
    }
    let userDbInfoAnon;
    try {
      const userDb = new PouchDb(name);
      userDbInfoAnon = await userDb.info();
    } catch (error) {
      userDbInfoAnon = { error };
    }
    return { baseDbInfoAuth, baseDbInfoAnon, userDbInfo, userDbInfoAnon };
  });

  const submitHandler = async (values: any, context: any) => {
    console.log({
      caller: 'Invitation / submitHandler',
      props,
      values,
      context,
    });
    const id = await save({ values, props });
    if (!props.values) {
      navigate(`/invitations/${encodeURIComponent(id)}`);
    }
  };

  const cancelHandler = () => {
    navigate(`/invitations/`);
  };

  const deleteHandler = async () => {
    console.log({
      caller: 'Invitation / deleteHandler',
      props,
    });
    await save({ props, values: { _deleted: true } });
    navigate(`/invitations/`);
  };

  const { form, data } = createForm({
    onSubmit: submitHandler,
    initialValues: props?.values,
  });

  const dbCheckHandler = async () => {
    const result = await dbCheck({
      name: data('database'),
      auth: { username: data('username'), password: data('password') },
    });
    console.log({
      caller: 'Invitation / dbCheckHandler',
      props,
      data: data(),
      result,
    });
    if (result.baseDbInfoAnon.error) {
      setStatus('baseError');
    } else if (!result.userDbInfo.error) {
      setStatus('OK');
    } else if (
      result.userDbInfoAnon.error.reason ===
      'You are not authorized to access this db.'
    ) {
      setStatus('passwordError');
    } else {
      setStatus('notFound');
    }
    setOpenDialog(true);
  };

  console.log({
    caller: 'Invitation ',
    props,
  });

  return (
    <>
      <form use:form>
        <TextField.Root>
          <TextField.Label>Mail address</TextField.Label>
          <TextField.Input
            type='mail'
            name='mail'
            required={true}
            placeholder='Email address'
          />
          <TextField.ErrorMessage>
            Please provide a valid URL
          </TextField.ErrorMessage>
        </TextField.Root>
        <TextField.Root>
          <TextField.Label>Database</TextField.Label>
          <TextField.Input
            type='url'
            name='database'
            required={true}
            placeholder='Database URL'
          />
          <TextField.ErrorMessage>
            Please provide a valid URL
          </TextField.ErrorMessage>
        </TextField.Root>
        <TextField.Root>
          <TextField.Label>User name</TextField.Label>
          <TextField.Input
            type='text'
            name='username'
            required={true}
            placeholder='user name'
          />
        </TextField.Root>
        <TextField.Root>
          <TextField.Label>Password</TextField.Label>
          <TextField.Input
            type='text'
            name='password'
            required={true}
            placeholder='Password'
            autocomplete='off'
          />
          <TextField.ErrorMessage>
            Please provide a valid password
          </TextField.ErrorMessage>
        </TextField.Root>
        <Switch>
          <Match when={!!props.values}>
            <Button.Root type='submit'>Save</Button.Root>
            <Button.Root onclick={deleteHandler}>Delete</Button.Root>
          </Match>
          <Match when={!props.values}>
            <Button.Root type='submit'>Create</Button.Root>
          </Match>
        </Switch>
        <Button.Root onclick={dbCheckHandler}>DB check</Button.Root>
        <Button.Root onclick={cancelHandler}>Cancel</Button.Root>
      </form>
      <Dialog.Root isOpen={openDialog()} onOpenChange={setOpenDialog}>
        <Dialog.Portal>
          <Dialog.Overlay class='dialog__overlay' />
          <div class='dialog__positioner'>
            <Dialog.Content class='dialog__content'>
              <div class='dialog__header'>
                <Dialog.Title class='dialog__title'>
                  Database check
                </Dialog.Title>
                <Dialog.CloseButton class='dialog__close-button'>
                  X
                </Dialog.CloseButton>
              </div>
              <Dialog.Description class='dialog__description'>
                <Switch>
                  <Match when={status() === 'baseError'}>
                    The database address seems to be wrong !!
                  </Match>{' '}
                  <Match when={status() === 'OK'}>
                    The user is already existing.
                  </Match>
                  <Match when={status() === 'notFound'}>
                    The user must be created.
                  </Match>
                  <Match when={status() === 'passwordError'}>
                    The user seems to exist but the password is wrong.
                  </Match>
                </Switch>
              </Dialog.Description>
            </Dialog.Content>
          </div>
        </Dialog.Portal>
      </Dialog.Root>
    </>
  );
};

export default Invitation;
