"use client";

import {
    SettingsContainer,
    SettingsSection,
    SettingsSectionBody,
    SettingsSectionDescription,
    SettingsSectionForm,
    SettingsSectionHeader,
    SettingsSectionTitle
} from "@app/components/Settings";
import { useEnvContext } from "@app/hooks/useEnvContext";
import { useOrgContext } from "@app/hooks/useOrgContext";
import { usePaidStatus } from "@app/hooks/usePaidStatus";
import { getUserDisplayName } from "@app/lib/getUserDisplayName";
import { orgQueries } from "@app/lib/queries";
import { zodResolver } from "@hookform/resolvers/zod";
import { build } from "@server/build";
import { UserType } from "@server/types/UserTypes";
import { useQuery } from "@tanstack/react-query";
import { useTranslations } from "next-intl";
import { type PolicyFormValues, createPolicySchema } from ".";
import { toast } from "@app/hooks/useToast";
import { createApiClient, formatAxiosError } from "@app/lib/api";
import { orgs, type ResourcePolicy } from "@server/db";
import type { AxiosResponse } from "axios";
import { useRouter } from "next/navigation";
import { Button } from "@app/components/ui/button";
import {
    Form,
    FormControl,
    FormField,
    FormItem,
    FormLabel,
    FormMessage
} from "@app/components/ui/form";
import { Input } from "@app/components/ui/input";
import { useMemo, useTransition } from "react";
import { useForm } from "react-hook-form";
import { CreatePolicyUsersRolesSectionForm } from "./CreatePolicyUserRolesSectionForm";
import { CreatePolicyAuthMethodsSectionForm } from "./CreatePolicyAuthMethodsSectionForm";
import { CreatePolicyOtpEmailSectionForm } from "./CreatePolicyOtpEmailSectionForm";
import { CreatePolicyRulesSectionForm } from "./CreatePolicyRulesSectionForm";
import { PaidFeaturesAlert } from "@app/components/PaidFeaturesAlert";
import { tierMatrix, TierFeature } from "@server/lib/billing/tierMatrix";

// ─── CreatePolicyForm ─────────────────────────────────────────────────────────

export type CreatePolicyFormProps = {};

export function CreatePolicyForm({}: CreatePolicyFormProps) {
    const { org } = useOrgContext();
    const t = useTranslations();
    const { env } = useEnvContext();
    const api = createApiClient({ env });
    const [isSubmitting, startTransition] = useTransition();
    const { isPaidUser } = usePaidStatus();

    const router = useRouter();

    const isMaxmindAvailable = !!(
        env.server.maxmind_db_path && env.server.maxmind_db_path.length > 0
    );
    const isMaxmindAsnAvailable = !!(
        env.server.maxmind_asn_path && env.server.maxmind_asn_path.length > 0
    );

    const { data: orgRoles = [], isLoading: isLoadingOrgRoles } = useQuery(
        orgQueries.roles({ orgId: org.org.orgId })
    );
    const { data: orgUsers = [], isLoading: isLoadingOrgUsers } = useQuery(
        orgQueries.users({ orgId: org.org.orgId })
    );
    const { data: orgIdps = [], isLoading: isLoadingOrgIdps } = useQuery(
        orgQueries.identityProviders({
            orgId: org.org.orgId,
            useOrgOnlyIdp: env.app.identityProviderMode === "org"
        })
    );

    const form = useForm<PolicyFormValues>({
        resolver: zodResolver(createPolicySchema) as any,
        defaultValues: {
            name: "",
            sso: true,
            skipToIdpId: null,
            emailWhitelistEnabled: false,
            roles: [],
            users: [],
            emails: [],
            applyRules: false,
            rules: [],
            password: null,
            headerAuth: null,
            pincode: null
        }
    });

    async function onSubmit() {
        const isValid = await form.trigger();

        if (!isValid) return;

        const payload = form.getValues();

        try {
            const res = await api
                .post<AxiosResponse<ResourcePolicy>>(
                    `/org/${org.org.orgId}/resource-policy/`,
                    {
                        name: payload.name,
                        // access control
                        sso: payload.sso,
                        roleIds: payload.roles.map((r) => r.id),
                        userIds: payload.users.map((u) => u.id),
                        skipToIdpId: payload.skipToIdpId,
                        // auth methods
                        password: payload.password?.password,
                        pincode: payload.pincode?.pincode,
                        headerAuth: payload.headerAuth,
                        // email OTP
                        emailWhitelistEnabled: payload.emailWhitelistEnabled,
                        emails: payload.emails.map((email) => email.text),
                        // rules
                        applyRules: payload.applyRules,
                        rules: payload.rules
                    }
                )
                .catch((e) => {
                    toast({
                        variant: "destructive",
                        title: t("policyErrorCreate"),
                        description: formatAxiosError(
                            e,
                            t("policyErrorCreateDescription")
                        )
                    });
                });

            if (res && res.status === 201) {
                const niceId = res.data.data.niceId;
                router.push(
                    `/${org.org.orgId}/settings/policies/resource/${niceId}`
                );
                toast({
                    title: t("success"),
                    description: t("policyCreatedSuccess")
                });
            }
        } catch (e) {
            toast({
                variant: "destructive",
                title: t("policyErrorCreate"),
                description: t("policyErrorCreateMessageDescription")
            });
        }
    }

    const allRoles = useMemo(
        () =>
            orgRoles
                .map((role) => ({
                    id: role.roleId.toString(),
                    text: role.name
                }))
                .filter((role) => role.text !== "Admin"),
        [orgRoles]
    );

    const allUsers = useMemo(
        () =>
            orgUsers.map((user) => ({
                id: user.id.toString(),
                text: `${getUserDisplayName({ email: user.email, username: user.username })}${user.type !== UserType.Internal ? ` (${user.idpName})` : ""}`
            })),
        [orgUsers]
    );

    const allIdps = useMemo(() => {
        if (build === "saas") {
            if (isPaidUser(tierMatrix.orgOidc)) {
                return orgIdps.map((idp) => ({
                    id: idp.idpId,
                    text: idp.name
                }));
            }
        } else {
            return orgIdps.map((idp) => ({ id: idp.idpId, text: idp.name }));
        }
        return [];
    }, [orgIdps, isPaidUser]);

    if (isLoadingOrgRoles || isLoadingOrgUsers || isLoadingOrgIdps) {
        return <></>;
    }

    const policyTiers = tierMatrix[TierFeature.ResourcePolicies];
    const isDisabled = !isPaidUser(policyTiers);

    return (
        <>
            <PaidFeaturesAlert tiers={policyTiers} />
            <Form {...form}>
                <div
                    className={
                        isDisabled
                            ? "pointer-events-none opacity-50"
                            : undefined
                    }
                >
                    <SettingsContainer>
                        {/* Name */}
                        <SettingsSection>
                            <SettingsSectionHeader>
                                <SettingsSectionTitle>
                                    {t("resourcePolicyName")}
                                </SettingsSectionTitle>
                                <SettingsSectionDescription>
                                    {t("resourcePolicyNameDescription")}
                                </SettingsSectionDescription>
                            </SettingsSectionHeader>
                            <SettingsSectionBody>
                                <SettingsSectionForm>
                                    <FormField
                                        control={form.control}
                                        name="name"
                                        render={({ field }) => (
                                            <FormItem>
                                                <FormLabel>
                                                    {t("name")}
                                                </FormLabel>
                                                <FormControl>
                                                    <Input
                                                        {...field}
                                                        placeholder={t(
                                                            "resourcePolicyNamePlaceholder"
                                                        )}
                                                    />
                                                </FormControl>
                                                <FormMessage />
                                            </FormItem>
                                        )}
                                    />
                                </SettingsSectionForm>
                            </SettingsSectionBody>
                        </SettingsSection>

                        <CreatePolicyUsersRolesSectionForm
                            form={form}
                            allRoles={allRoles}
                            allUsers={allUsers}
                            allIdps={allIdps}
                        />
                        <CreatePolicyAuthMethodsSectionForm form={form} />
                        <CreatePolicyOtpEmailSectionForm
                            form={form}
                            emailEnabled={env.email.emailEnabled}
                        />
                        <CreatePolicyRulesSectionForm
                            form={form}
                            isMaxmindAvailable={isMaxmindAvailable}
                            isMaxmindAsnAvailable={isMaxmindAsnAvailable}
                        />
                    </SettingsContainer>
                </div>

                <div className="flex py-6 justify-end">
                    <Button
                        type="button"
                        onClick={() => startTransition(onSubmit)}
                        loading={isSubmitting}
                        disabled={isSubmitting || isDisabled}
                    >
                        {t("resourcePoliciesCreate")}
                    </Button>
                </div>
            </Form>
        </>
    );
}
