'use strict';

import {Controller} from '@hotwired/stimulus';
// @ts-ignore
import {Component, getComponent} from '@symfony/ux-live-component';

const RETURNING_KEY = 'ferienpass.returningUser';
const METHOD_KEY = 'ferienpass.lastLoginMethod';

export default class extends Controller {
    static targets = [
        "methodInput", "passkeyButton", "passwordButton",
        "passwordField", "password", "passkeyInfo",
        "submitPassword", "submitPasskey", "passwordEye", "passwordEyeOff",
    ];

    declare readonly hasMethodInputTarget: boolean;
    declare readonly methodInputTarget: HTMLInputElement;
    declare readonly hasPasskeyButtonTarget: boolean;
    declare readonly passkeyButtonTarget: HTMLElement;
    declare readonly passwordButtonTarget: HTMLElement;
    declare readonly hasPasswordFieldTarget: boolean;
    declare readonly passwordFieldTarget: HTMLElement;
    declare readonly hasPasswordTarget: boolean;
    declare readonly passwordTarget: HTMLInputElement;
    declare readonly hasPasskeyInfoTarget: boolean;
    declare readonly passkeyInfoTarget: HTMLElement;
    declare readonly hasSubmitPasswordTarget: boolean;
    declare readonly submitPasswordTarget: HTMLElement;
    declare readonly hasSubmitPasskeyTarget: boolean;
    declare readonly submitPasskeyTarget: HTMLElement;
    declare readonly hasPasswordEyeTarget: boolean;
    declare readonly passwordEyeTarget: HTMLElement;
    declare readonly hasPasswordEyeOffTarget: boolean;
    declare readonly passwordEyeOffTarget: HTMLElement;

    declare component?: Component;

    // Kept as a plain property (not a Stimulus value) so it survives
    // LiveComponent re-renders — morphdom would reset a value-backed attribute.
    method = 'passkey';
    pwVisible = false;

    async initialize() {
        if (!(this.element instanceof HTMLElement)) {
            return;
        }
        try {
            this.component = await getComponent(this.element);
            this.component.on('render:finished', () => this.applyState());
        } catch (e) {
        }
    }

    connect() {
        this.applyState();
    }

    usePasskey() {
        this.method = 'passkey';
        this.applyState();
        this.syncMethodModel();
    }

    usePassword() {
        this.method = 'password';
        this.applyState();
        this.syncMethodModel();
    }

    // Remember the chosen sign-in method for this browser so a returning
    // registrant is greeted with the matching login view next time (the reader
    // side lives in the cms-signin / cms-signin-login controllers). Fired on
    // form submit — like sendMagicLink, this is optimistic: we record the
    // intent at the point of the user's action. No name or e-mail is stored.
    remember() {
        try {
            localStorage.setItem(RETURNING_KEY, '1');
            localStorage.setItem(METHOD_KEY, this.method);
        } catch (e) {
        }
    }

    // The form is a LiveComponent: programmatically setting the hidden field's
    // value does not fire a change event, so the live data store keeps the old
    // value. Dispatch one so the submitted method matches the picker.
    private syncMethodModel() {
        if (this.hasMethodInputTarget) {
            this.methodInputTarget.dispatchEvent(new Event('change', {bubbles: true}));
        }
    }

    togglePassword() {
        this.pwVisible = !this.pwVisible;
        this.applyState();
    }

    applyState() {
        const passkey = 'passkey' === this.method;

        if (this.hasMethodInputTarget) {
            this.methodInputTarget.value = this.method;
        }
        if (this.hasPasskeyButtonTarget) {
            this.setSegment(this.passkeyButtonTarget, passkey);
            this.setSegment(this.passwordButtonTarget, !passkey);
        }
        this.toggle(this.hasPasswordFieldTarget ? this.passwordFieldTarget : null, !passkey);
        this.toggle(this.hasPasskeyInfoTarget ? this.passkeyInfoTarget : null, passkey);
        this.toggle(this.hasSubmitPasswordTarget ? this.submitPasswordTarget : null, !passkey);
        this.toggle(this.hasSubmitPasskeyTarget ? this.submitPasskeyTarget : null, passkey);

        if (this.hasPasswordTarget) {
            this.passwordTarget.type = this.pwVisible ? 'text' : 'password';
        }
        this.toggle(this.hasPasswordEyeTarget ? this.passwordEyeTarget : null, !this.pwVisible);
        this.toggle(this.hasPasswordEyeOffTarget ? this.passwordEyeOffTarget : null, this.pwVisible);
    }

    private toggle(el: HTMLElement | null, visible: boolean) {
        if (el) {
            el.style.display = visible ? '' : 'none';
        }
    }

    private setSegment(el: HTMLElement, active: boolean) {
        el.setAttribute('aria-checked', active ? 'true' : 'false');
        ['bg-white', 'text-gray-900', 'shadow-sm', 'dark:bg-gray-800', 'dark:text-gray-100'].forEach((c) => el.classList.toggle(c, active));
        ['text-gray-500', 'dark:text-gray-300'].forEach((c) => el.classList.toggle(c, !active));
    }
}
