import { createEffect, createSignal, Show } from "solid-js";
import { JSX } from "solid-js/jsx-runtime";
// import { Person } from "../../types/Person";
// import { RegisterPerson } from "./Search/RegisterPerson";
import QR from "qrcode";
import { CopyIcon } from "../icons/CopyIcon";
import { MagnifyingGlassIcon } from "../icons/MagnifyingGlassIcon";
import { XIcon } from "../icons/XIcon";

type HTMLEventFn = JSX.EventHandlerUnion<HTMLFormElement, Event & {
    submitter: HTMLElement;
}>;
type HTMLButtonEvent = JSX.EventHandlerUnion<HTMLButtonElement, MouseEvent>;

// eslint-disable-next-line @typescript-eslint/no-explicit-any
type Person = any;

/*
    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 [warning, setWarning] = createSignal("");
    const [qrBase64, setQrBase64] = createSignal<string | null>(null);
    const [persona, setPersona] = createSignal<Person | null>(null);

    // Update QR
    createEffect(() => {
        if (dni() !== "") {
            // Old URL: https://www.eegsac.com/alumnoscertificados.php?DNI=${dni()}
            // New URL: https://eegsac.com/certificado/${dni()}
            QR.toDataURL(`https://eegsac.com/certificado/${dni()}`, {margin: 1}, (err, res) => {
                if (err) {
                    console.error("Error creating QR code");
                    return;
                }

                setQrBase64(res);
            });
        }
    });

    /*
      Get the user data from the DB
    */
    const searchDNI: HTMLEventFn = (ev) => {
        ev.preventDefault();
        search();
    };

    const search = async() => {
        setLoading(true);
        setError("");
        setWarning("");

        try {
            const response = await fetch(`/person/${dni()}`);
            const body = await response.json();
            if (response.ok) {
                setPersona(body);
                props.setPerson(body);
            } else if (response.status === 404) {
                console.error(body);

                setWarning("Persona no encontrada. Se debe insertar manualmente sus datos.");
                props.setPerson(null);
            } else {
                setError(body);
            }
        } catch (e) {
            setError(JSON.stringify(e));
        }

        setLoading(false);
    };

    const nombresYApellidos = () => {
        const p = persona();
        if (p === null) {
            return "";
        }
        return `${p.nombres} ${p.apellidoPaterno} ${p.apellidoMaterno}`;
    };

    const apellidosYNombres = () => {
        const p = persona();
        if (p === null) {
            return "";
        }
        return `${p.apellidoPaterno} ${p.apellidoMaterno} ${p.nombres}`;
    };

    const apellidos = () => {
        const p = persona();
        if (p === null) {
            return "";
        }
        return `${p.apellidoPaterno} ${p.apellidoMaterno}`;
    };

    const nombres = () => {
        const p = persona();
        if (p === null) {
            return "";
        }
        return p.nombres;
    };

    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={searchDNI} 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"
                    style={{display: error() === "" ? "none" : "block"}}
                >
                    Error:
                    <br />
                    {error()}
                </p>

                <br />

                <div class={`${persona() === null ? "opacity-50 cursor-not-allowed" : ""}`}>
                    <MaterialLabel text={persona()?.apellidoPaterno ?? null} resource="Apellido Paterno" />
                    <MaterialLabel text={persona()?.apellidoMaterno ?? null} resource="Apellido Materno" />
                    <MaterialLabel text={persona()?.nombres ?? null} resource="Nombres" />

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

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

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

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

function InputBox(props: {
    loading: boolean,
    dni: string,
    setDni: (v: string) => void,
}) {
    const inputElement = (
        <input
            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
            onChange={(e) => props.setDni(e.target.value)}
            disabled={props.loading}
        />
    );

    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">
            {inputElement}
            <label for="search-dni" class="absolute -top-2 left-2 text-xs bg-c-surface px-1">DNI</label>
            <button
                class="absolute top-1 right-[3.75rem] rounded hover:bg-c-surface-variant"
            >
                <MagnifyingGlassIcon fill="var(--c-on-surface)" />
            </button>
            <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 | null, resource: string}) {
    const copyToClipboard: HTMLButtonEvent = (ev) => {
        ev.preventDefault();

        if (props.text !== null) {
            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 text-c-on-primary"
                } rounded-lg transition-colors py-1 my-1 relative overflow-hidden inline-block w-full`
            }
        >
            {props.children}
        </button>
    );
}

