import { CoreApi, Group, User } from "authentik-api";
import { t } from "@lingui/macro";
import { customElement } from "lit-element";
import { html, TemplateResult } from "lit-html";
import { DEFAULT_CONFIG } from "../../api/Config";
import { ifDefined } from "lit-html/directives/if-defined";
import "../../elements/forms/HorizontalFormElement";
import "../../elements/CodeMirror";
import "./GroupSelectModal";
import YAML from "yaml";
import { first } from "../../utils";
import { ModelForm } from "../../elements/forms/ModelForm";
import { until } from "lit-html/directives/until";

@customElement("ak-user-form")
export class UserForm extends ModelForm<User, number> {
    loadInstance(pk: number): Promise<User> {
        return new CoreApi(DEFAULT_CONFIG).coreUsersRetrieve({
            id: pk,
        });
    }

    getSuccessMessage(): string {
        if (this.instance) {
            return t`Successfully updated user.`;
        } else {
            return t`Successfully created user.`;
        }
    }

    send = (data: User): Promise<User> => {
        if (this.instance?.pk) {
            return new CoreApi(DEFAULT_CONFIG).coreUsersUpdate({
                id: this.instance.pk,
                userRequest: data,
            });
        } else {
            return new CoreApi(DEFAULT_CONFIG).coreUsersCreate({
                userRequest: data,
            });
        }
    };

    renderForm(): TemplateResult {
        return html`<form class="pf-c-form pf-m-horizontal">
            <ak-form-element-horizontal label=${t`Username`} ?required=${true} name="username">
                <input
                    type="text"
                    value="${ifDefined(this.instance?.username)}"
                    class="pf-c-form-control"
                    required
                />
                <p class="pf-c-form__helper-text">
                    ${t`Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.`}
                </p>
            </ak-form-element-horizontal>
            <ak-form-element-horizontal label=${t`Name`} ?required=${true} name="name">
                <input
                    type="text"
                    value="${ifDefined(this.instance?.name)}"
                    class="pf-c-form-control"
                    required
                />
                <p class="pf-c-form__helper-text">${t`User's display name.`}</p>
            </ak-form-element-horizontal>
            <ak-form-element-horizontal label=${t`Email`} name="email">
                <input
                    type="email"
                    autocomplete="off"
                    value="${ifDefined(this.instance?.email)}"
                    class="pf-c-form-control"
                />
            </ak-form-element-horizontal>
            <ak-form-element-horizontal name="isActive">
                <div class="pf-c-check">
                    <input
                        type="checkbox"
                        class="pf-c-check__input"
                        ?checked=${first(this.instance?.isActive, true)}
                    />
                    <label class="pf-c-check__label"> ${t`Is active`} </label>
                </div>
                <p class="pf-c-form__helper-text">
                    ${t`Designates whether this user should be treated as active. Unselect this instead of deleting accounts.`}
                </p>
            </ak-form-element-horizontal>
            <ak-form-element-horizontal label=${t`Groups`} name="groups">
                <div class="pf-c-input-group">
                    <ak-user-group-select-table
                        .confirm=${(items: Group[]) => {
                            // Because the model only has the IDs, map the group list to IDs
                            const ids = items.map((g) => g.pk);
                            if (!this.instance) this.instance = {} as User;
                            this.instance.groups = Array.from(this.instance?.groups || []).concat(
                                ids,
                            );
                            this.requestUpdate();
                            return Promise.resolve();
                        }}
                    >
                        <button slot="trigger" class="pf-c-button pf-m-control" type="button">
                            <i class="fas fa-plus" aria-hidden="true"></i>
                        </button>
                    </ak-user-group-select-table>
                    <div class="pf-c-form-control">
                        <ak-chip-group>
                            ${until(
                                new CoreApi(DEFAULT_CONFIG)
                                    .coreGroupsList({
                                        ordering: "name",
                                    })
                                    .then((groups) => {
                                        return groups.results.map((group) => {
                                            const selected = Array.from(
                                                this.instance?.groups || [],
                                            ).some((sg) => {
                                                return sg == group.pk;
                                            });
                                            if (!selected) return;
                                            return html`<ak-chip
                                                .removable=${true}
                                                value=${ifDefined(group.pk)}
                                                @remove=${() => {
                                                    if (!this.instance) return;
                                                    const groups = Array.from(
                                                        this.instance?.groups || [],
                                                    );
                                                    const idx = groups.indexOf(group.pk);
                                                    groups.splice(idx, 1);
                                                    this.instance.groups = groups;
                                                    this.requestUpdate();
                                                }}
                                            >
                                                ${group.name}
                                            </ak-chip>`;
                                        });
                                    }),
                                html`<option>${t`Loading...`}</option>`,
                            )}
                        </ak-chip-group>
                    </div>
                </div>
            </ak-form-element-horizontal>
            <ak-form-element-horizontal label=${t`Attributes`} ?required=${true} name="attributes">
                <ak-codemirror
                    mode="yaml"
                    value="${YAML.stringify(first(this.instance?.attributes, {}))}"
                >
                </ak-codemirror>
                <p class="pf-c-form__helper-text">
                    ${t`Set custom attributes using YAML or JSON.`}
                </p>
            </ak-form-element-horizontal>
        </form>`;
    }
}