import { ROUTES } from '@/constants';
import { isAdminRole, resolvePostLoginDestination, resolveRoleDestination, toAppRoles } from './routing';
import type { RoleCode } from './types';

describe('toAppRoles', () => {
  it('collapses all admin sub-roles to the single admin actor', () => {
    expect(toAppRoles(['support'])).toEqual(['admin']);
    expect(toAppRoles(['super_admin', 'finance'])).toEqual(['admin']);
  });

  it('keeps customer and nurse and de-duplicates', () => {
    expect(toAppRoles(['customer', 'nurse'])).toEqual(['customer', 'nurse']);
    expect(toAppRoles(['nurse', 'nurse'])).toEqual(['nurse']);
  });

  it('drops unknown/empty codes', () => {
    expect(toAppRoles([])).toEqual([]);
    expect(toAppRoles(['unknown' as RoleCode])).toEqual([]);
  });
});

describe('isAdminRole', () => {
  it('flags every internal admin sub-role', () => {
    (['admin', 'support', 'finance', 'moderation', 'super_admin'] as RoleCode[]).forEach((role) =>
      expect(isAdminRole(role)).toBe(true),
    );
  });
  it('does not flag public roles', () => {
    expect(isAdminRole('customer')).toBe(false);
    expect(isAdminRole('nurse')).toBe(false);
  });
});

describe('resolveRoleDestination (role-router branches)', () => {
  it('sends a customer to the family app home', () => {
    expect(resolveRoleDestination({ roles: ['customer'] })).toBe(ROUTES.HOME);
  });

  it('sends a nurse to the nurse app', () => {
    expect(resolveRoleDestination({ roles: ['nurse'] })).toBe(ROUTES.NURSE);
  });

  it('sends a role-less (brand-new) user to role selection', () => {
    expect(resolveRoleDestination({ roles: [] })).toBe(ROUTES.SELECT_ROLE);
  });

  it('sends any admin-family role to the admin console', () => {
    expect(resolveRoleDestination({ roles: ['support'] })).toBe(ROUTES.ADMIN);
    expect(resolveRoleDestination({ roles: ['customer', 'super_admin'] })).toBe(ROUTES.ADMIN);
  });

  it('uses the login intent to disambiguate a dual customer+nurse user', () => {
    expect(resolveRoleDestination({ roles: ['customer', 'nurse'] }, 'nurse')).toBe(ROUTES.NURSE);
    expect(resolveRoleDestination({ roles: ['customer', 'nurse'] }, 'customer')).toBe(ROUTES.HOME);
    // Defaults to the family app when no intent is carried.
    expect(resolveRoleDestination({ roles: ['customer', 'nurse'] })).toBe(ROUTES.HOME);
  });
});

describe('resolvePostLoginDestination (returnUrl)', () => {
  it('honors a safe same-origin next path the session is allowed to reach', () => {
    expect(resolvePostLoginDestination({ roles: ['customer'] }, undefined, '/bookings/42')).toBe('/bookings/42');
  });

  it('honors a nurse-owned next path for a nurse session', () => {
    expect(resolvePostLoginDestination({ roles: ['nurse'] }, undefined, '/nurse/requests')).toBe('/nurse/requests');
  });

  it('falls back to the role destination for a protocol-relative next (open-redirect guard)', () => {
    expect(resolvePostLoginDestination({ roles: ['customer'] }, undefined, '//evil.com')).toBe(ROUTES.HOME);
  });

  it('falls back to the role destination for an absolute-URL next (open-redirect guard)', () => {
    expect(resolvePostLoginDestination({ roles: ['customer'] }, undefined, 'https://evil.com')).toBe(ROUTES.HOME);
  });

  it('falls back when next belongs to a role the session does not hold', () => {
    expect(resolvePostLoginDestination({ roles: ['customer'] }, undefined, '/nurse/requests')).toBe(ROUTES.HOME);
    expect(resolvePostLoginDestination({ roles: ['customer'] }, undefined, '/admin/audit')).toBe(ROUTES.HOME);
  });

  it('falls back to select-role for a role-less user regardless of next', () => {
    expect(resolvePostLoginDestination({ roles: [] }, undefined, '/bookings')).toBe(ROUTES.SELECT_ROLE);
  });

  it('falls back to the role destination when next is absent', () => {
    expect(resolvePostLoginDestination({ roles: ['customer'] }, undefined, null)).toBe(ROUTES.HOME);
  });
});
