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";

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);

    // 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("");

        try {
            const response = await fetch(`${import.meta.env.VITE_BACKEND_URL}/api/person/${dni()}`);
            const body = await response.json();

            if (response.ok) {
                setPerson(body);
                props.setPerson(body);
            } else if (response.status === 404) {
                console.error(body);

                setError("No encontrado. Ingresar datos manualmente.");
                props.setPerson(null);
            } else {
                setError(body);
            }
        } catch (e) {
            setError(JSON.stringify(e));
        }

        setLoading(false);
    };

    const namesAndSurnames = () => {
        const p = person();
        if (p === null) {
            return "";
        }
        return `${p.person_names} ${p.person_paternal_surname} ${p.person_maternal_surname}`;
    };

    const surnamesAndNames = () => {
        const p = person();
        if (p === null) {
            return "";
        }
        return `${p.person_paternal_surname} ${p.person_maternal_surname} ${p.person_names}`;
    };

    const surnames = () => {
        const p = person();
        if (p === null) {
            return "";
        }
        return `${p.person_paternal_surname} ${p.person_maternal_surname}`;
    };

    const personNames = () => {
        const p = person();
        if (p === null) {
            return "";
        }
        return p.person_names;
    };

    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 dni={dni()} setDni={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>


                <div class={`${person() === null ? "opacity-50 cursor-not-allowed" : ""}`}>
                    <MaterialLabel text={person()?.person_paternal_surname ?? ""} resource="Apellido Paterno" />
                    <MaterialLabel text={person()?.person_maternal_surname ?? ""} resource="Apellido Materno" />
                    <MaterialLabel text={personNames()} resource="Nombres" />

                    <Show when={person() !== null}>
                        <div class={"relative max-w-[14rem] mx-auto my-6"}>
                            <CopyButton copyText={namesAndSurnames()}>
                                <CopyIcon fill="var(--c-on-primary)" />
                                &nbsp;
                                Nombres y <b>Apellidos</b>
                            </CopyButton>

                            <CopyButton copyText={surnamesAndNames()}>
                                <CopyIcon fill="var(--c-on-primary)" />
                                &nbsp;
                                <b>Apellidos</b> y Nombres
                            </CopyButton>

                            <div class="grid grid-cols-2 gap-2">
                                <CopyButton copyText={surnames()}>
                                    <CopyIcon fill="var(--c-on-primary)" />
                                    &nbsp;
                                    <b>Apellidos</b>
                                </CopyButton>
                                <CopyButton copyText={personNames()}>
                                    <CopyIcon fill="var(--c-on-primary)" />
                                    &nbsp;
                                    Nombres
                                </CopyButton>
                            </div>
                        </div>
                    </Show>
                </div>

                {/*
                <Show when={warning() !== ""}>
                    <RegisterPerson dni={dni()} onSuccess={search} />
                </Show>
                */}
            </div>
        </div>
    );
}

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

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

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

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

        props.setDni("");
        (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.dni}
                required
                onInput={(e) => props.setDni(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>
            <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>
    );
}


function MaterialLabel(props: {text: string, resource: string}) {
    const copyToClipboard: HTMLButtonEvent = (ev) => {
        ev.preventDefault();

        if (props.text !== "") {
            navigator.clipboard.writeText(props.text);
        }
    };

    return (
        <div class="relative max-w-[14rem] mx-auto my-6">
            <label for="search-dni" class="absolute -top-2 left-2 text-xs bg-c-surface px-1 select-none">
                {props.resource}
            </label>
            <span
                class="bg-c-background text-c-on-background border-c-outline
                border-2 rounded px-2 py-1 w-full inline-block font-mono
                disabled:opacity-50 disabled:cursor-not-allowed"
            >
                {props.text}
                <span class="select-none">&nbsp;</span>
            </span>

            <button
                type="button"
                class="absolute top-1 right-1 rounded hover:bg-c-surface-variant"
                onclick={copyToClipboard}
            >
                <CopyIcon fill="var(--c-on-surface)" />
            </button>
        </div>
    );
}

function CopyButton(props: {copyText: string, children: Array<JSX.Element> | JSX.Element}) {
    const [successAnimation, setSuccessAnimation] = createSignal(false);

    const onclick = () => {
        if (props.copyText !== "") {
            navigator.clipboard.writeText(props.copyText);
            setSuccessAnimation(true);
            setTimeout(() => setSuccessAnimation(false), 500);
        }
    };

    return (
        <button
            onclick={onclick}
            class={
                `${successAnimation() ? "bg-c-success text-c-on-success" : "bg-c-primary-container text-c-on-primary-container"
                } rounded-lg transition-colors py-1 my-1 relative overflow-hidden inline-block w-full`
            }
        >
            {props.children}
        </button>
    );
}

