import { hasModuleAccess, hasPermission, type AppSession } from '$lib/session';

export type WorkspaceRole = 'admin' | 'operations' | 'full' | 'client' | 'unknown';

type RouteAccessRule = {
  path: string;
  roles: WorkspaceRole[];
  matches: (pathname: string) => boolean;
};

function hasPathPrefix(pathname: string, prefix: string) {
  return pathname === prefix || pathname.startsWith(`${prefix}/`);
}

function canAccessWorkspaceArea(
  session: AppSession | null | undefined,
  moduleKey: string,
  permissionKeys: string[],
  minimumLevel: 'view' | 'edit' | 'manage' = 'view'
) {
  if (!session) {
    return false;
  }

  if (session.role === 'internal') {
    return permissionKeys.some((permissionKey) => hasPermission(session, permissionKey));
  }

  return hasModuleAccess(session, moduleKey, minimumLevel);
}

function isLeanAdminRole(session: AppSession | null | undefined) {
  return session?.role === 'admin' || (session?.role === 'internal' && ['admin', 'lean'].includes(session.role_name?.toLowerCase() ?? ''));
}

export function getWorkspaceRole(session: AppSession | null | undefined): WorkspaceRole {
  if (!session) {
    return 'unknown';
  }

  if (session.role === 'admin') {
    return 'admin';
  }

  if (session.role !== 'internal') {
    return 'client';
  }

  if (isLeanAdminRole(session)) {
    return 'admin';
  }

  if (session.role_name === 'Operations') {
    return 'operations';
  }

  if (session.role_name === 'Full Access') {
    return 'full';
  }

  return 'unknown';
}

export function canOpenDashboard(session: AppSession | null | undefined) {
  return canAccessWorkspaceArea(session, 'dashboard', ['view_dashboard']);
}

export function canOpenRawMaterials(session: AppSession | null | undefined) {
  return canAccessWorkspaceArea(session, 'raw_materials', ['view_raw_materials', 'edit_raw_materials']);
}

export function canOpenMixMaster(session: AppSession | null | undefined) {
  return canAccessWorkspaceArea(session, 'mix_master', ['view_mixes', 'edit_mixes']);
}

export function canCreateMixWorksheet(session: AppSession | null | undefined) {
  return canAccessWorkspaceArea(session, 'mix_master', ['edit_mixes'], 'edit');
}

export function canOpenMixCalculator(session: AppSession | null | undefined) {
  return canAccessWorkspaceArea(session, 'mix_calculator', ['view_mix_calculator', 'use_mix_calculator']);
}

export function canCreateMixSession(session: AppSession | null | undefined) {
  return canAccessWorkspaceArea(session, 'mix_calculator', ['use_mix_calculator', 'save_mix_calculator_session'], 'edit');
}

export function canOpenProducts(session: AppSession | null | undefined) {
  return canAccessWorkspaceArea(session, 'products', ['view_products', 'edit_products']);
}

export function canOpenProductCosting(session: AppSession | null | undefined) {
  return canOpenProducts(session);
}

export function canOpenEditor(session: AppSession | null | undefined) {
  if (!session) {
    return false;
  }

  return isLeanAdminRole(session);
}

export function canOpenScenarios(session: AppSession | null | undefined) {
  return !!session && hasModuleAccess(session, 'scenarios');
}

export function canOpenThroughput(session: AppSession | null | undefined) {
  return canAccessWorkspaceArea(session, 'operations_throughput', ['view_throughput', 'edit_throughput']);
}

export function canEditThroughput(session: AppSession | null | undefined) {
  return canAccessWorkspaceArea(session, 'operations_throughput', ['edit_throughput'], 'edit');
}

export function canOpenReporting(session: AppSession | null | undefined) {
  return canOpenProducts(session);
}

// Internal staff who manage the customer ordering portal (catalogue, pricing,
// order lifecycle). These are Hunter Stock Feeds users signing in via the
// internal access system — not customers.
export function canManageOrdering(session: AppSession | null | undefined) {
  return !!session && session.role === 'internal' && hasPermission(session, 'manage_ordering');
}

// B2B customers (ClientUser accounts) who browse the catalogue and place orders.
export function canOpenCustomerOrdering(session: AppSession | null | undefined) {
  return !!session && session.role !== 'internal' && hasModuleAccess(session, 'ordering');
}

// Either audience may open the Ordering area (the nav/route resolves which view).
export function canOpenOrdering(session: AppSession | null | undefined) {
  return canManageOrdering(session) || canOpenCustomerOrdering(session);
}

export function canPlaceOrders(session: AppSession | null | undefined) {
  return !!session && session.role !== 'internal' && hasModuleAccess(session, 'ordering', 'edit');
}

// A "customer portal" session is a B2B ordering customer (ClientUser) whose
// access is limited to ordering — they get the dedicated, stripped-down
// Customer Ordering Portal shell rather than the internal staff workspace.
// Internal staff and costing-portal client users (who also have mix/product/
// throughput access) keep the full workspace.
const STAFF_ONLY_MODULES = [
  'mix_calculator',
  'products',
  'mix_master',
  'operations_throughput',
  'scenarios',
  'raw_materials',
  'client_access'
];

export function isCustomerPortalSession(session: AppSession | null | undefined) {
  if (!session || session.role !== 'client') {
    return false;
  }
  if (!canOpenCustomerOrdering(session)) {
    return false;
  }
  return !STAFF_ONLY_MODULES.some((moduleKey) => hasModuleAccess(session, moduleKey));
}

export function canOpenSettings(session: AppSession | null | undefined) {
  if (!session) {
    return false;
  }

  return session.role === 'internal'
    ? hasPermission(session, 'view_settings') || hasPermission(session, 'edit_settings')
    : true;
}

export function canOpenClientAccess(session: AppSession | null | undefined) {
  return !!session && hasModuleAccess(session, 'client_access', 'manage');
}

export const routeAccessRules: RouteAccessRule[] = [
  { path: '/', roles: ['admin', 'full', 'client'], matches: (pathname) => pathname === '/' },
  {
    path: '/mix-calculator',
    roles: ['admin', 'operations', 'full', 'client'],
    matches: (pathname) => hasPathPrefix(pathname, '/mix-calculator')
  },
  {
    path: '/raw-materials',
    roles: ['admin', 'full', 'client'],
    matches: (pathname) => hasPathPrefix(pathname, '/raw-materials')
  },
  { path: '/mixes', roles: ['admin', 'full', 'client'], matches: (pathname) => hasPathPrefix(pathname, '/mixes') },
  {
    path: '/product-costing',
    roles: ['admin', 'full', 'client'],
    matches: (pathname) => hasPathPrefix(pathname, '/product-costing')
  },
  { path: '/products', roles: ['admin', 'full', 'client'], matches: (pathname) => hasPathPrefix(pathname, '/products') },
  { path: '/editor', roles: ['admin'], matches: (pathname) => hasPathPrefix(pathname, '/editor') },
  { path: '/reporting', roles: ['admin', 'full', 'client'], matches: (pathname) => hasPathPrefix(pathname, '/reporting') },
  { path: '/scenarios', roles: ['admin', 'full', 'client'], matches: (pathname) => hasPathPrefix(pathname, '/scenarios') },
  {
    path: '/settings',
    roles: ['admin', 'full', 'operations', 'client'],
    matches: (pathname) => hasPathPrefix(pathname, '/settings')
  },
  {
    path: '/client-access',
    roles: ['admin', 'client'],
    matches: (pathname) => hasPathPrefix(pathname, '/client-access')
  },
  {
    path: '/throughput',
    roles: ['admin', 'operations', 'full', 'client'],
    matches: (pathname) => hasPathPrefix(pathname, '/throughput')
  },
  {
    path: '/ordering',
    roles: ['admin', 'full', 'client'],
    matches: (pathname) => hasPathPrefix(pathname, '/ordering')
  }
];

export function getDefaultRouteForRole(session: AppSession | null | undefined) {
  // B2B ordering customers land directly in the ordering portal.
  if (isCustomerPortalSession(session)) {
    return '/ordering';
  }

  const role = getWorkspaceRole(session);

  if (role === 'operations') {
    return '/mix-calculator';
  }

  if (role === 'admin' || role === 'full' || role === 'client') {
    if (canOpenDashboard(session)) return '/';
    if (canOpenMixCalculator(session)) return '/mix-calculator';
    if (canOpenRawMaterials(session)) return '/raw-materials';
    if (canOpenMixMaster(session)) return '/mixes';
    if (canOpenProducts(session)) return '/products';
    if (canOpenScenarios(session)) return '/scenarios';
    if (canOpenSettings(session)) return '/settings';
  }

  return '/';
}

export function canAccessRoute(session: AppSession | null | undefined, pathname: string) {
  const rule = routeAccessRules.find((candidate) => candidate.matches(pathname));
  if (!rule) {
    return true;
  }

  const role = getWorkspaceRole(session);
  if (!rule.roles.includes(role)) {
    return false;
  }

  if (pathname === '/') return canOpenDashboard(session);
  if (pathname.startsWith('/mix-calculator')) return canOpenMixCalculator(session);
  if (pathname.startsWith('/raw-materials')) return canOpenRawMaterials(session);
  if (pathname.startsWith('/mixes')) return canOpenMixMaster(session);
  if (pathname.startsWith('/product-costing')) return canOpenProductCosting(session);
  if (pathname.startsWith('/products')) return canOpenProducts(session);
  if (pathname.startsWith('/editor')) return canOpenEditor(session);
  if (pathname.startsWith('/ingredients')) return canOpenEditor(session);
  if (pathname.startsWith('/scenarios')) return canOpenScenarios(session);
  if (pathname.startsWith('/reporting')) return canOpenReporting(session);
  if (pathname.startsWith('/settings')) return canOpenSettings(session);
  if (pathname.startsWith('/client-access')) return canOpenClientAccess(session);
  if (pathname.startsWith('/throughput')) return canOpenThroughput(session);
  if (pathname.startsWith('/ordering')) return canOpenOrdering(session);
  return true;
}

export function canUseWorkspaceSearch(session: AppSession | null | undefined) {
  return (
    canOpenDashboard(session) ||
    canOpenRawMaterials(session) ||
    canOpenMixMaster(session) ||
    canOpenEditor(session) ||
    canOpenMixCalculator(session) ||
    canOpenProducts(session) ||
    canOpenScenarios(session)
  );
}

export const getWorkspaceHomeHref = getDefaultRouteForRole;
export const isWorkspaceRouteAllowed = canAccessRoute;
