import { RoleIdEnums } from '../../enums/unitySystemEnums';
function assertNonEmptyString(value, fieldName) {
    if (typeof value !== 'string' || value.trim().length === 0) {
        throw new Error(`User is missing required field: ${fieldName}`);
    }
}
function getHttpStatusCodeFromError() {
    return 401;
}
function isApiResponse(value) {
    if (!value || typeof value !== 'object')
        return false;
    const v = value;
    return (typeof v.userId === 'string' &&
        typeof v.externalUUID === 'string' &&
        typeof v.name === 'string' &&
        Array.isArray(v.roles));
}
/**
 * Canonical User model.
 *
 * - Construct from the new API response (preferred)
 * - Or rehydrate from a previously-serialized User instance
 *
 * NOTE: This model intentionally does NOT read from storage or config.
 */
export class User {
    // --- Canonical fields (new API) ---
    userId;
    externalUUID;
    name;
    firstName;
    familyName;
    jobTitle;
    email;
    mobile;
    phone;
    location;
    isUnitySystemAdmin;
    roles;
    permissions;
    can;
    defaultTenantId;
    currentTenantId;
    /**
     * @deprecated Do not use `user.accessToken`.
     * This value is not reliably refreshed/updated when the session is refreshed.
     * Use token acquisition helpers instead.
     */
    accessToken;
    /** @deprecated Legacy/unused. use the TenantProvider i.e.
     * `const tenant = useTenant()` to get TenantContext
     * `tenant.activeTenant` to get the current tenant, and
     * `tenant.activeTenant.products` for the product list.
     */
    products;
    /** @deprecated Legacy/unused. Prefer TenantProvider i.e.
     *  `const tenant = useTenant()` to get TenantContext
     * `tenant.tenantsList` for the full list of tenants available to the user.
     */
    tenantIds;
    /** @deprecated Legacy/unused. Do not use User model to store arbitrary data */
    additionalProperties;
    /** @deprecated Legacy/unused. Prefer HTTP status handling outside the model */
    statusCode;
    constructor(arg, currentTenantIdParam) {
        var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w;
        // Deliberately ignored when the API response includes `currentTenantId` (response wins).
        void currentTenantIdParam;
        if (isApiResponse(arg)) {
            assertNonEmptyString(arg.defaultTenantId, 'defaultTenantId');
            assertNonEmptyString(arg.currentTenantId, 'currentTenantId');
            assertNonEmptyString(arg.userId, 'userId');
            assertNonEmptyString(arg.externalUUID, 'externalUUID');
            this.userId = arg.userId;
            this.externalUUID = arg.externalUUID;
            this.name = (_a = arg.name) !== null && _a !== void 0 ? _a : '';
            this.firstName = (_b = arg.firstName) !== null && _b !== void 0 ? _b : '';
            this.familyName = (_c = arg.familyName) !== null && _c !== void 0 ? _c : '';
            this.jobTitle = (_d = arg.jobTitle) !== null && _d !== void 0 ? _d : null;
            this.email = (_e = arg.email) !== null && _e !== void 0 ? _e : '';
            this.mobile = (_f = arg.mobile) !== null && _f !== void 0 ? _f : null;
            this.phone = (_g = arg.phone) !== null && _g !== void 0 ? _g : null;
            this.location = (_h = arg.location) !== null && _h !== void 0 ? _h : null;
            this.isUnitySystemAdmin = Boolean(arg.isUnitySystemAdmin);
            this.roles = Array.isArray(arg.roles) ? arg.roles : [];
            this.permissions = Array.isArray(arg.permissions) ? arg.permissions : [];
            this.can = (_j = arg.can) !== null && _j !== void 0 ? _j : {};
            this.defaultTenantId = arg.defaultTenantId;
            this.currentTenantId = arg.currentTenantId;
            // Legacy fields - intentionally minimized
            this.accessToken = undefined;
            this.products = undefined;
            this.tenantIds = undefined;
            this.additionalProperties = undefined;
            // Deprecated: populate for legacy flows. Treat missing/invalid API response fields as unauthorized.
            // If required fields are present, consider it a successful fetch.
            this.statusCode = typeof arg.statusCode === 'number' ? arg.statusCode : 200;
            return;
        }
        // Rehydrate path
        const u = arg;
        assertNonEmptyString(u.defaultTenantId, 'defaultTenantId');
        assertNonEmptyString(u.currentTenantId, 'currentTenantId');
        assertNonEmptyString(u.userId, 'userId');
        assertNonEmptyString(u.externalUUID, 'externalUUID');
        this.userId = u.userId;
        this.externalUUID = u.externalUUID;
        this.name = (_k = u.name) !== null && _k !== void 0 ? _k : '';
        this.firstName = (_l = u.firstName) !== null && _l !== void 0 ? _l : '';
        this.familyName = (_m = u.familyName) !== null && _m !== void 0 ? _m : '';
        this.jobTitle = (_o = u.jobTitle) !== null && _o !== void 0 ? _o : null;
        this.email = (_p = u.email) !== null && _p !== void 0 ? _p : '';
        this.mobile = (_q = u.mobile) !== null && _q !== void 0 ? _q : null;
        this.phone = (_r = u.phone) !== null && _r !== void 0 ? _r : null;
        this.location = (_s = u.location) !== null && _s !== void 0 ? _s : null;
        this.isUnitySystemAdmin = Boolean((_t = u.isUnitySystemAdmin) !== null && _t !== void 0 ? _t : this.hasRole(RoleIdEnums.Unity_System_Administrator));
        this.roles = (_u = u.roles) !== null && _u !== void 0 ? _u : [];
        this.permissions = (_v = u.permissions) !== null && _v !== void 0 ? _v : [];
        this.can = (_w = u.can) !== null && _w !== void 0 ? _w : {};
        this.defaultTenantId = u.defaultTenantId;
        this.currentTenantId = u.currentTenantId;
        // Legacy pass-through (still deprecated)
        this.accessToken = u.accessToken;
        this.products = u.products;
        this.tenantIds = u.tenantIds;
        this.additionalProperties = u.additionalProperties;
        this.statusCode = typeof u.statusCode === 'number' ? u.statusCode : 200;
    }
    // --- Deprecated legacy accessors (derived) ---
    /** @deprecated Prefer `userId` */
    get id() {
        return this.userId;
    }
    /** @deprecated Prefer `userId` */
    get unityId() {
        return this.userId;
    }
    /** @deprecated Prefer `externalUUID` */
    get aadId() {
        return this.externalUUID;
    }
    /** @deprecated Prefer `roles` */
    get roleIds() {
        var _a;
        return ((_a = this.roles) !== null && _a !== void 0 ? _a : []).map((r) => r.roleId);
    }
    /** @deprecated Prefer `roles` */
    get roleNames() {
        var _a;
        return ((_a = this.roles) !== null && _a !== void 0 ? _a : []).map((r) => r.name);
    }
    hasRole(roleId) {
        return this.roleIds.includes(roleId);
    }
    toJSON() {
        // Ensure JSON.stringify(new User(...)) produces a plain object with stable keys.
        return {
            userId: this.userId,
            externalUUID: this.externalUUID,
            name: this.name,
            firstName: this.firstName,
            familyName: this.familyName,
            jobTitle: this.jobTitle,
            email: this.email,
            mobile: this.mobile,
            phone: this.phone,
            location: this.location,
            isUnitySystemAdmin: this.isUnitySystemAdmin,
            roles: this.roles,
            permissions: this.permissions,
            can: this.can,
            defaultTenantId: this.defaultTenantId,
            currentTenantId: this.currentTenantId,
            // Deprecated legacy
            accessToken: this.accessToken,
            products: this.products,
            tenantIds: this.tenantIds,
            additionalProperties: this.additionalProperties,
            statusCode: this.statusCode
        };
    }
}
/**
 * @deprecated Prefer `new User(apiResponse)`.
 * This wrapper exists to reduce migration churn.
 */
export function createUser(userInfo) {
    try {
        return new User(userInfo);
    }
    catch (_a) {
        // Legacy wrapper: surface a best-effort User instance with statusCode=401.
        // Callers should migrate to handling HTTP errors outside the model.
        return new User({
            userId: 'unknown',
            externalUUID: 'unknown',
            name: '',
            firstName: '',
            familyName: '',
            jobTitle: null,
            email: '',
            mobile: null,
            phone: null,
            location: null,
            isUnitySystemAdmin: false,
            roles: [],
            permissions: [],
            can: {},
            defaultTenantId: 'unknown',
            currentTenantId: 'unknown',
            statusCode: getHttpStatusCodeFromError()
        });
    }
}
/**
 * @deprecated Prefer `new User(userLike)`.
 * This wrapper exists to reduce migration churn.
 */
export function createUserFromUserObject(userObject) {
    return new User(userObject);
}
//# sourceMappingURL=user.js.map