import $ from "jquery";

import { __ } from "../utils/i18n.js";
import { getStaticOptions } from "../utils/options.js";
import { request } from "../utils/request.js";
import { locationRestFeedbackPost } from "../wp-api/feedback.post.js";

import type {
    ParamsRestFeedbackPost,
    RequestRestFeedbackPost,
    ResponseRestFeedbackPost,
} from "../wp-api/feedback.post.js";

class FeedbackPointer {
    public readonly slug: string;

    public readonly href?: string;

    public readonly $handler: JQuery<HTMLElement> & {
        pointer?: (...args: any[]) => FeedbackPointer["$handler"];
    };

    public constructor(slug: string, href: string, $handler: FeedbackPointer["$handler"]) {
        this.slug = slug;
        this.$handler = $handler;
        this.href = href;

        this.init();
    }

    public async close(e: JQuery.ClickEvent, skip = false) {
        e.preventDefault();

        // Indicate loading
        this.$handler.pointer("widget").find("input, .button").attr("disabled", "disabled");

        if (!skip) {
            const { choice, note, email } = this.getValidInput();
            try {
                choice !== "none" &&
                    (await request<RequestRestFeedbackPost, ParamsRestFeedbackPost, ResponseRestFeedbackPost>({
                        location: locationRestFeedbackPost,
                        request: {
                            reason: choice,
                            note,
                            email,
                        },
                        params: {
                            slug: this.slug,
                        },
                    }));
            } catch (e) {
                // Silence is golden.
            } finally {
                // Ignore any errors and redirect
                window.open(this.href, "_self");
            }
        } else {
            window.open(this.href, "_self");
        }
    }

    public buttons() {
        const support = $(`<a class="button" href="#">${__("Contact support")}</a>`).click(() => {
            window.open("https://devowl.io/support/", "_blank");
        });
        const skip = $(`<a class="button" href="#">${__("Skip & Deactivate")}</a>`).click((e) => {
            this.close(e, true);
        });
        const deactivate = $(`<a class="hidden button button-primary" href="#">${__("Deactivate")}</a>`).click((e) => {
            if (this.validate()) {
                this.close(e, false);
            }
        });

        return $('<div class="real-utils-pointer-buttons" />').append(deactivate, skip, support);
    }

    private validate() {
        return this.validateNote() && this.validatePrivacy() && this.validateEmail();
    }

    private validateNote() {
        const skipNote = $(`[name="${this.slug}-skip-note"]`).is(":checked");
        const noticeNote = $(`.notice-${this.slug}-note`);
        const { choice, note } = this.getValidInput();

        if (!skipNote && !note && ["upgrade-to-pro", "temp", "none"].indexOf(choice) === -1) {
            noticeNote.show();
            return false;
        } else {
            noticeNote.hide();
        }

        return true;
    }

    private validatePrivacy() {
        const privacyChecked = $(`[name="${this.slug}-privacy"]`).is(":checked");
        const noticePrivacy = $(`.notice-${this.slug}-privacy`);
        const { email } = this.getValidInput();

        if (email && !privacyChecked) {
            noticePrivacy.show();
            return false;
        } else {
            noticePrivacy.hide();
        }

        return true;
    }

    private validateEmail() {
        const noticeEmail = $(`.notice-${this.slug}-email`);
        const { email } = this.getValidInput();

        if (
            email &&
            !/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(
                email.toLowerCase(),
            )
        ) {
            noticeEmail.show();
            return false;
        } else {
            noticeEmail.hide();
        }

        return true;
    }

    private getValidInput() {
        const choice = $(`[name="${this.slug}-deactivate-choice"]:checked`).val() as string;
        const note = $(`[name="${this.slug}-note"]`).val() as string;
        const email = note ? ($(`[name="${this.slug}-email"]`).val() as string) : "";

        if (!choice && note) {
            return { choice: "other", note, email };
        } else if (choice) {
            return { choice, note, email };
        }
        return undefined;
    }

    private init() {
        const headline = __("Too bad you are leaving");
        const name = getStaticOptions().names[this.slug];
        const desc = __("Please give us feedback why you deactivate <strong>%s</strong>.", name);
        const choices = {
            "upgrade-to-pro": __("Upgrade to PRO Version"),
            "not-working": __("Plugin did not work"),
            "missing-features": __("Not the features I want"),
            incompatible: __("Incompatible with other themes or plugins"),
            "missing-doc": __("Lack of documentation"),
            "found-better-plugin": __("Found a better plugin"),
            temp: __("Temporary deactivation"),
            none: __("I do not want to give feedback"),
            other: __("Other"),
        } as any;

        const $widget = this.$handler
            .pointer({
                pointerClass: `wp-pointer real-utils-feedback-pointer`,
                content: `<h3>${headline}</h3><p>${desc}</p>
<fieldset>
    ${Object.keys(choices)
        .map(
            (choice) =>
                `<label class="col-2"><input type="radio" name="${this.slug}-deactivate-choice" value="${choice}" /> ${choices[choice]}</label>`,
        )
        .join("")}
        <div class="clear"></div>
        <br />
    <label class="${this.slug}-section-note">
        <strong>${__("What could we do better?")}</strong>
        <input type="text" class="regular-text" name="${this.slug}-note" />
        <div class="notice notice-${this.slug}-note notice-error notice-alt hidden"><p>${__(
            "Please enter a text here or check the box below.",
        )}</p></div>
    </label>
    <label class="${this.slug}-section-note">
        <input type="checkbox" name="${this.slug}-skip-note" /> ${__(
            "I don't want to add a comment and hence not help to make %s better.",
            name,
        )}
    </label>
    <label class="${this.slug}-section-email" style="display:none">
        <br /><strong>${__("Email for answer/solution (optional)?")}</strong>
        <input type="text" class="regular-text" name="${this.slug}-email" />
        <div class="notice notice-${this.slug}-email notice-error notice-alt hidden"><p>${__(
            "Please provide a valid email.",
        )}</p></div>
    </label>
    <label class="${this.slug}-section-email" style="display:none">
        <input type="checkbox" name="${this.slug}-privacy" /> ${__(
            'I would like to receive an answer for my issue. For this purpose I agree to the data processing of my feedback and my email address. I have read the devowl.io <a href="https://devowl.io/privacy-policy/" target="_blank">privacy policy</a> and agree to it.',
            name,
        )}
        <div class="notice notice-${this.slug}-privacy notice-error notice-alt hidden"><p>${__(
            "If you would like to be contacted by us, please accept the privacy policy. If you prefer not to be contacted, leave the email field blank.",
        )}</p></div>
    </label>
</fieldset>`,
                buttons: this.buttons.bind(this),
            })
            .pointer("open")
            .pointer("widget") as JQuery<HTMLDivElement>;

        // Listen to changes and show the "Skip & Deactivate" button
        $widget.find("input").on("input", () => {
            const valid = this.getValidInput();
            const isNoneChoice = valid?.choice === "none";
            $widget.find(".button:eq(0)").css("display", valid ? "inline-block" : "none"); // .toggleClass does not work as expected, see jQuery bug tracker
            $widget.find(".button:eq(1)").css("display", !valid ? "inline-block" : "none");
            $widget.find(".button:eq(1)").css("display", !valid ? "inline-block" : "none");
            $(`[name="${this.slug}-skip-note"]`)
                .parent()
                .css("display", valid?.note ? "none" : "block");
            $(`.${this.slug}-section-email`).css("display", valid?.note && !isNoneChoice ? "block" : "none");
            $(`.${this.slug}-section-note`).css("display", isNoneChoice ? "none" : "block");
        });
    }
}

export { FeedbackPointer };
