/**
 * API scope matrix — tenant-public-api (wave-11 leaf-D) + oauth-authorization-code (wave-12).
 * Scope check logic: write scope implies read scope, but not vice versa.
 */

export type ApiScope =
  | 'customers:read' | 'customers:write'
  | 'invoices:read'  | 'invoices:write'
  | 'tasks:read'     | 'tasks:write'
  | 'events:read'
  // wave-12: OAuth scopes (resource:action format, same enforcement as API keys)
  | 'leads:read'     | 'leads:write'
  | 'time:read'      | 'time:write'
  | 'projects:read'
  | 'expenses:read'

/**
 * Human-readable labels for OAuth consent screen display.
 * Keys match ApiScope strings; values are shown to users during authorization.
 */
export const OAUTH_SCOPE_DEFINITIONS: Record<ApiScope, { label: string; description: string }> = {
  'customers:read':  { label: 'Read customers',  description: 'View customer profiles and contact info' },
  'customers:write': { label: 'Manage customers', description: 'Create and update customers' },
  'invoices:read':   { label: 'Read invoices',   description: 'View invoices and payment status' },
  'invoices:write':  { label: 'Manage invoices',  description: 'Create, update and send invoices' },
  'tasks:read':      { label: 'Read tasks',       description: 'View tasks and project boards' },
  'tasks:write':     { label: 'Manage tasks',     description: 'Create and update tasks' },
  'events:read':     { label: 'Read events',      description: 'View calendar events' },
  'leads:read':      { label: 'Read leads',       description: 'View leads and pipeline data' },
  'leads:write':     { label: 'Manage leads',     description: 'Create and update leads' },
  'time:read':       { label: 'Read time entries', description: 'View time tracking records' },
  'time:write':      { label: 'Manage time entries', description: 'Log and update time entries' },
  'projects:read':   { label: 'Read projects',    description: 'View projects and milestones' },
  'expenses:read':   { label: 'Read expenses',    description: 'View expense records' },
}

/** If a key holds the write scope, it also satisfies the read scope. */
function impliedScopes(scope: string): string[] {
  if (scope.endsWith(':write')) {
    return [scope, scope.replace(':write', ':read')]
  }
  return [scope]
}

export function hasScope(granted: string[], required: ApiScope): boolean {
  const expanded = new Set(granted.flatMap(impliedScopes))
  return expanded.has(required)
}

/** Mapping from (METHOD, pathPattern) to required scope. */
export const SCOPE_MAP: Record<string, ApiScope> = {
  'GET /v1/customers':          'customers:read',
  'GET /v1/customers/:id':      'customers:read',
  'POST /v1/customers':         'customers:write',
  'PATCH /v1/customers/:id':    'customers:write',
  'GET /v1/invoices':           'invoices:read',
  'GET /v1/invoices/:id':       'invoices:read',
  'POST /v1/invoices':          'invoices:write',
  'PATCH /v1/invoices/:id/status': 'invoices:write',
  'GET /v1/tasks':              'tasks:read',
  'GET /v1/tasks/:id':          'tasks:read',
  'POST /v1/tasks':             'tasks:write',
  'PATCH /v1/tasks/:id':        'tasks:write',
  'GET /v1/events':             'events:read',
  // wave-13: zapier-make-integration
  'GET /v1/leads':              'leads:read',
  'GET /v1/leads/:id':          'leads:read',
  'POST /v1/leads':             'leads:write',
  'PATCH /v1/leads/:id':        'leads:write',
  'POST /v1/time':              'time:write',
  'GET /v1/projects':           'projects:read',
  'GET /v1/projects/:id':       'projects:read',
  'POST /v1/invoices/:id/send': 'invoices:write',
  'GET /v1/webhooks':           'events:read',
  'POST /v1/webhooks':          'events:read',
  'DELETE /v1/webhooks/:id':    'events:read',
}
