import { rpc } from '@/api/request';
import type { AuthSocSTUType, ShmSocialType } from '@/api/types';
import { Lang } from '@/lang/Lang';
import {
    generateUUID,
    getAlphaNumericRandom,
} from '@/utils/helpers';

/**
 * UI codes and ?soc= values for auth4app (see f3-auth4app AuthFormController::auth).
 */
export const SOCIAL_NETWORK_TYPES = ['vk', 'ya', 'google', 'ok', 'mailru'] as const;
export type SocialNetworkType = (typeof SOCIAL_NETWORK_TYPES)[number];

/**
 * Canonical type/soc stored in DB after OAuth callback (AuthFormController::callback).
 */
export const AUTH4APP_STORED_SOC_TYPES: Record<SocialNetworkType, string> = {
    vk: 'vk',
    ya: 'yandex',
    google: 'google',
    ok: 'ok',
    mailru: 'mail',
};

/**
 * Maps auth4app input aliases and stored canonical values → UI SocialNetworkType.
 *
 * Input aliases (auth):  vk/vkontakte, ya/yandex, ok/odnoklassniki, mail/mailru, google
 * Stored (callback):     vk, yandex, ok, mail, google
 */
const SOCIAL_NETWORK_ALIASES: Record<string, SocialNetworkType> = {
    vk: 'vk',
    vkontakte: 'vk',
    ya: 'ya',
    yandex: 'ya',
    google: 'google',
    ok: 'ok',
    odnoklassniki: 'ok',
    mailru: 'mailru',
    mail: 'mailru',
};

export const normalizeSocialNetworkType = (value: string): SocialNetworkType | null => {
    const normalized = value.trim().toLowerCase();
    if ((SOCIAL_NETWORK_TYPES as readonly string[]).includes(normalized)) {
        return normalized as SocialNetworkType;
    }
    return SOCIAL_NETWORK_ALIASES[normalized] ?? null;
};

export const getSocialTypeKey = (social: ShmSocialType): SocialNetworkType | '' => {
    const raw = social.type ?? social.soc ?? '';
    if (!raw) return '';
    return normalizeSocialNetworkType(raw) ?? '';
};

export const findSocialByType = (socials: ShmSocialType[], type: SocialNetworkType) =>
    socials.find((social) => getSocialTypeKey(social) === type);

export const getSocialDisplayLabel = (social: ShmSocialType) => {
    const typeKey = getSocialTypeKey(social);
    return social.mail?.trim()
        || [social.name, social.surname].filter(Boolean).join(' ')
        || (typeKey ? Lang.key('social_' + typeKey) : '');
};

export const unlinkSocialAccount = (unsetId: string) =>
    rpc.authSoc({ unsetId }).then((data) => {
        const result = data?.result;
        return !!(
            result?.unsetResult
            ?? (result as { deleteResult?: boolean } | null | undefined)?.deleteResult
        );
    });

const createSocialAuthKey = () =>
    `${new Date().getTime()}-${generateUUID(256)}-${getAlphaNumericRandom(100)}`;

const waitForSocialAuthWindow = (
    win: Window | null,
    key: string,
    set: boolean,
): Promise<AuthSocSTUType | null> => {
    return new Promise((resolve) => {
        const interval = setInterval(() => {
            if (win && win.closed) {
                clearInterval(interval);
                rpc.authSoc(set ? { key, set: true } : { key })
                    .then((data) => resolve(data?.result ?? null))
                    .catch(() => resolve(null));
            }
        }, 500);
    });
};

export const openSocialAuth = (
    type: SocialNetworkType,
    mode: 'login' | 'link',
): Promise<AuthSocSTUType | null> => {
    const key = createSocialAuthKey();
    const win = window.open(
        `https://auth4app.com/auth?soc=${type}&key=${key}`,
        '_blank',
    );
    return waitForSocialAuthWindow(win, key, mode === 'link');
};

export const loginViaSocial = (type: SocialNetworkType) => openSocialAuth(type, 'login');

export const linkSocialAccount = (type: SocialNetworkType) =>
    openSocialAuth(type, 'link').then((result) => !!result?.setResult);
