import { Show, createEffect, createSignal } from "solid-js";
import { JSX } from "solid-js/jsx-runtime";
import QR from "qrcode";
import { CopyIcon } from "../../icons/CopyIcon";
import { XIcon } from "../../icons/XIcon";
import { Person } from "../../types/Person";
import { PersonDisplay } from "./PersonDisplay";
import { PersonRegister } from "./PersonRegister";
import { backend, wait } from "../../utils/functions";
import { JsonResult } from "../../types/JsonResult";
import { LoadingIcon } from "../../icons/LoadingIcon";

type HTMLButtonEvent = JSX.EventHandlerUnion<HTMLButtonElement, MouseEvent>;

/*
    Form that retrieves a user from the DB given an ID
*/
export function Search(props: {setPerson: (p: Person | null) => void}) {
    const [dni, setDni] = createSignal("");
    const [loading, setLoading] = createSignal(false);
    const [error, setError] = createSignal("");
    const [qrBase64, setQrBase64] = createSignal<string | null>(null);
    const [person, setPerson] = createSignal<Person | null>(null);
    const [manualCreate, setManualCreate] = createSignal(false);

    // Update QR and automatically search when DNI is changed
    createEffect(() => {
        const dniT = dni();

        if (dniT.length >= 8) {
            search();
            QR.toDataURL(`https://eegsac.com/certificado/${dniT}`, {margin: 1}, (err, res) => {
                if (err) {
                    console.error("Error creating QR code");
                    return;
                }

                setQrBase64(res);
            });
        } else {
            setQrBase64(null);
            setPerson(null);
            props.setPerson(null);
        }
    });

    /*
      Get the user data from the DB
    */
    const search = async() => {
        setLoading(true);
        setError("");

        if (import.meta.env.DEV) await wait(1500);

        backend.get<JsonResult<Person>>(`/api/person/${dni()}`)
            .then((response) => {
                if (response.status === 200) {
                    setPerson(response.data.Ok);
                    props.setPerson(response.data.Ok);
                    setManualCreate(false);
                } else if (response.status === 404) {
                    console.error(response.data);

                    setError("No encontrado. Ingresar datos manualmente.");
                    setManualCreate(true);
                    props.setPerson(null);
                } else {
                    setError(response.data.Err.reason);
                    setManualCreate(false);
                }
            })
            .catch((err) => {
                setError(`Error fatal: ${err.message}`);
                console.error(err);
            })
            .finally(() => {
                setLoading(false);
            })
        ;
    };


    return (
        <div>
            <div class="text-center">
                <div class="my-4 inline-block w-[10rem] h-[10rem] rounded-lg bg-c-surface-variant overflow-hidden">
                    <img class={`${qrBase64() === null ? "hidden" : ""} inline-block w-[10rem] h-[10rem]`} src={qrBase64() ?? ""} />
                </div>
            </div>
            <div>
                <form onSubmit={(ev) => ev.preventDefault()} class="px-4">
                    <InputBox value={dni()} setValue={setDni} loading={loading()} />
                </form>

                <p
                    class="relative max-w-[14rem] mx-auto p-1 text-c-error text-sm select-none"
                    style={{opacity: error() === "" ? "0" : "1"}}
                >
                    Error: {error()}
                </p>


                <Show when={person() !== null}>
                    <PersonDisplay person={person()!} />
                </Show>
                <Show when={manualCreate()}>
                    <PersonRegister dni={dni()} onRegister={search} />
                </Show>

            </div>
        </div>
    );
}


function InputBox(props: {
    loading: boolean,
    value: string,
    setValue: (v: string) => void,
}) {
    let inputElement: HTMLInputElement | undefined;

    const copyToClipboard: HTMLButtonEvent = (ev) => {
        ev.preventDefault();

        if (props.value.length === 8) {
            navigator.clipboard.writeText(props.value);
        }
    };

    const clearDni: HTMLButtonEvent = (ev) => {
        ev.preventDefault();

        props.setValue("");
        (inputElement as HTMLInputElement).focus();
    };

    return (
        <div class="relative max-w-[14rem] mx-auto">
            <input
                ref={inputElement}
                id="search-dni"
                class="bg-c-background text-c-on-background border-c-outline border-2 rounded px-2 py-1 w-full
                        invalid:border-c-error invalid:text-c-error
                        focus:border-c-primary outline-none font-mono
                        disabled:opacity-50 disabled:cursor-not-allowed"
                type="text"
                minLength={8}
                maxLength={8}
                pattern="[0-9]{8}"
                placeholder="Número de DNI"
                value={props.value}
                required
                onInput={(e) => props.setValue(e.target.value)}
                disabled={props.loading}
            />


            <label for="search-dni" class="absolute -top-2 left-2 text-xs bg-c-surface px-1 select-none">DNI</label>

            <span
                class="absolute top-[2px] right-14 rounded hover:bg-c-surface-variant"
                style={{display: props.loading ? "inline-block" : "none"}}
            >
                <LoadingIcon class="animate-spin" fill="var(--c-on-surface)" />
            </span>
            <button
                type="button"
                class="absolute top-1 right-8 rounded hover:bg-c-surface-variant"
                onclick={copyToClipboard}
            >
                <CopyIcon fill="var(--c-on-surface)" />
            </button>
            <button
                type="button"
                class="absolute top-1 right-1 rounded hover:bg-c-surface-variant"
                onclick={clearDni}
            >
                <XIcon fill="var(--c-on-surface)" />
            </button>
        </div>
    );
}


