import { CORTEX_PATHS, AGENT_PATHS } from './paths.js';

export const CONFIG_FOCUS_SECTION_PARAM = 'configSection';
export const CONFIG_FOCUS_FIELD_PARAM = 'configField';
export const CONFIG_FOCUS_TAB_PARAM = 'tab';

const FIELD_ID_PREFIX = 'config-field-';

export const CONFIG_SECTION_IDS = {
  appearance: 'config-section-appearance',
  cortexInstructions: 'config-section-cortex-instructions',
  cortexBuilder: 'config-section-cortex-builder',
  cortexDigest: 'config-section-cortex-digest',
  settingsAgent: 'config-section-settings-agent',
  settingsEmbedding: 'config-section-settings-embedding',
  settingsNotifications: 'config-section-settings-notifications',
  settingsPlanCapture: 'config-section-settings-plan-capture',
  settingsProject: 'config-section-settings-project',
  agentOperations: 'config-section-agent-operations',
  operationsMaintenance: 'config-section-operations-maintenance',
  operationsBackup: 'config-section-operations-backup',
} as const;

type ConfigPagePath = '/settings' | '/agent' | '/operations' | '/cortex';

interface ConfigSectionTarget {
  page: ConfigPagePath;
  sectionId: string;
  sectionLabel: string;
  searchParams?: Record<string, string>;
}

export interface ConfigFocusTarget extends ConfigSectionTarget {
  fieldPath: string;
  fieldLabel: string;
}

interface PrefixRule extends ConfigSectionTarget {
  prefix: string;
}

const SECTION_RULES: PrefixRule[] = [
  {
    prefix: 'appearance',
    page: '/settings',
    sectionId: CONFIG_SECTION_IDS.appearance,
    sectionLabel: 'Appearance',
  },
  {
    prefix: 'agent.provider',
    page: '/settings',
    sectionId: CONFIG_SECTION_IDS.settingsAgent,
    sectionLabel: 'Myco Agent',
  },
  {
    prefix: 'embedding',
    page: '/settings',
    sectionId: CONFIG_SECTION_IDS.settingsEmbedding,
    sectionLabel: 'Embedding',
  },
  {
    prefix: 'cortex.digest',
    page: '/cortex',
    sectionId: CONFIG_SECTION_IDS.cortexDigest,
    sectionLabel: 'Digest',
    searchParams: { [CONFIG_FOCUS_TAB_PARAM]: 'digest' },
  },
  {
    prefix: 'cortex.instructions',
    page: '/cortex',
    sectionId: CONFIG_SECTION_IDS.cortexInstructions,
    sectionLabel: 'Instructions',
  },
  {
    prefix: 'cortex.spores',
    page: '/cortex',
    sectionId: CONFIG_SECTION_IDS.cortexInstructions,
    sectionLabel: 'Instructions',
  },
  {
    prefix: 'cortex.canopy',
    page: '/cortex',
    sectionId: CONFIG_SECTION_IDS.cortexInstructions,
    sectionLabel: 'Canopy',
    searchParams: { [CONFIG_FOCUS_TAB_PARAM]: 'canopy' },
  },
  {
    prefix: 'cortex.enabled',
    page: '/cortex',
    sectionId: CONFIG_SECTION_IDS.cortexInstructions,
    sectionLabel: 'Instructions',
  },
  {
    prefix: 'notifications',
    page: '/settings',
    sectionId: CONFIG_SECTION_IDS.settingsNotifications,
    sectionLabel: 'Notifications',
  },
  {
    prefix: 'capture',
    page: '/settings',
    sectionId: CONFIG_SECTION_IDS.settingsPlanCapture,
    sectionLabel: 'Plan Capture',
  },
  // daemon.* fields live in three different groups on the unified Settings
  // page now — sessions, logging, update. The page emits `id="<group-id>"`
  // on each section element, so we point notification deep-links at the
  // anchor directly. Most-specific prefix wins (rule order matters; see
  // resolveConfigFocusTarget).
  {
    prefix: 'daemon.stale_session_threshold_ms',
    page: '/settings',
    sectionId: 'sessions',
    sectionLabel: 'Sessions',
  },
  {
    prefix: 'daemon.log_level',
    page: '/settings',
    sectionId: 'logging',
    sectionLabel: 'Logging',
  },
  {
    prefix: 'daemon.log_retention_days',
    page: '/settings',
    sectionId: 'logging',
    sectionLabel: 'Logging',
  },
  {
    prefix: 'daemon.update_channel',
    page: '/settings',
    sectionId: 'update',
    sectionLabel: 'Update',
  },
  // Scheduled / event tasks moved out of the Agent page into their own
  // group on the unified Settings page (Phase 5 fix-forward).
  {
    prefix: 'agent.scheduled_tasks_enabled',
    page: '/settings',
    sectionId: 'scheduled-tasks',
    sectionLabel: 'Scheduled tasks',
  },
  {
    prefix: 'agent.event_tasks_enabled',
    page: '/settings',
    sectionId: 'scheduled-tasks',
    sectionLabel: 'Scheduled tasks',
  },
  {
    prefix: 'agent.scheduled_tasks_active_window_days',
    page: '/settings',
    sectionId: 'scheduled-tasks',
    sectionLabel: 'Scheduled tasks',
  },
  {
    prefix: 'agent.summary_batch_interval',
    page: '/agent',
    sectionId: CONFIG_SECTION_IDS.agentOperations,
    sectionLabel: 'Agent Operations',
    searchParams: { tab: 'config' },
  },
  {
    prefix: 'skills',
    page: '/settings',
    sectionId: 'skills',
    sectionLabel: 'Skills',
  },
  // Maintenance and Backup moved from the Operations page into the unified
  // Settings page during Phase 5. Notification links opening "Open
  // Settings" land on the right group anchor on the new page.
  {
    prefix: 'maintenance',
    page: '/settings',
    sectionId: 'maintenance',
    sectionLabel: 'Maintenance',
  },
  {
    prefix: 'backup',
    page: '/settings',
    sectionId: 'backup',
    sectionLabel: 'Backup',
  },
];

const EXACT_FIELD_LABELS: Record<string, string> = {
  'appearance.theme': 'Color Theme',
  'appearance.mode': 'Mode',
  'appearance.font': 'Font',
  'appearance.density': 'Density',
  'agent.provider': 'Provider',
  'agent.provider.type': 'Provider',
  'agent.provider.model': 'Model',
  'agent.provider.base_url': 'Base URL',
  'agent.provider.context_length': 'Context Length',
  'embedding.provider': 'Provider',
  'embedding.model': 'Model',
  'embedding.base_url': 'Base URL',
  [CORTEX_PATHS.digest.tier]: 'Preferred Digest Tier',
  [CORTEX_PATHS.digest.injectOnSessionStart]: 'Session-Start Digest',
  [CORTEX_PATHS.instructions.injectOnSessionStart]: 'Session-Start Instructions',
  [CORTEX_PATHS.instructions.injectOnSubagentStart]: 'Subagent Context',
  [CORTEX_PATHS.spores.injectOnPromptSubmit]: 'Prompt-Submit Spore Injection',
  [CORTEX_PATHS.spores.maxPerPrompt]: 'Max Spores per Prompt',
  [CORTEX_PATHS.canopy.injectOnPreToolUse]: 'PreToolUse Canopy Injection',
  [CORTEX_PATHS.canopy.minFileBytes]: 'Min File Size (bytes)',
  'notifications.enabled': 'Notifications',
  'notifications.default_mode': 'Default Display',
  'notifications.system_notifications': 'Browser Notifications',
  'capture.ignore_plan_dirs_in_git': 'Ignore Custom Plan Dirs In Git',
  'capture.plan_dirs': 'Custom Directories',
  'daemon.log_level': 'Log Level',
  'daemon.log_retention_days': 'Log Retention (days)',
  [AGENT_PATHS.scheduledTasksEnabled]: 'Scheduled Tasks',
  [AGENT_PATHS.eventTasksEnabled]: 'Event-Driven Tasks',
  [AGENT_PATHS.summaryBatchInterval]: 'Title & Summary Batch Interval',
  'maintenance.auto_optimize': 'Auto-optimize',
  'maintenance.auto_optimize_interval_hours': 'Auto-optimize Interval',
  'backup.dir': 'Backup Directory',
};

const DYNAMIC_FIELD_LABEL_RULES: Array<{
  prefix: string;
  format: (path: string) => string | null;
}> = [
  {
    prefix: 'notifications.domains.',
    format: (path) => {
      const match = /^notifications\.domains\.([^.]+)\.(enabled|mode)$/.exec(path);
      if (!match) return null;
      const [, domain, leaf] = match;
      const domainLabel = humanizeToken(domain);
      return leaf === 'mode' ? `${domainLabel} Display` : `${domainLabel} Notifications`;
    },
  },
];

const SAVE_MESSAGE_LABEL_LIMIT = 3;

export function configFieldId(path: string): string {
  return `${FIELD_ID_PREFIX}${path.replace(/[^a-zA-Z0-9]+/g, '-')}`;
}

export function resolveConfigFocusTarget(path: string): ConfigFocusTarget | null {
  const section = findSectionRule(path);
  if (!section) return null;
  return {
    ...section,
    fieldPath: path,
    fieldLabel: resolveFieldLabel(path),
  };
}

export function buildConfigFocusLink(target: ConfigFocusTarget): string {
  const params = new URLSearchParams(target.searchParams);
  params.set(CONFIG_FOCUS_SECTION_PARAM, target.sectionId);
  params.set(CONFIG_FOCUS_FIELD_PARAM, target.fieldPath);
  return `${target.page}?${params.toString()}`;
}

export function buildScopedConfigSaveNotification(scope: 'project' | 'local', touchedPaths: string[]) {
  const uniquePaths = [...new Set(touchedPaths)];
  const scopeLabel = scope === 'local' ? 'Personal' : 'Project';
  const focusTarget = uniquePaths.map(resolveConfigFocusTarget).find((target) => target !== null) ?? null;
  const fieldLabels = uniquePaths.map(resolveFieldLabel);
  const primaryLabel = fieldLabels[0] ?? 'Setting';
  const labelList = fieldLabels.slice(0, SAVE_MESSAGE_LABEL_LIMIT).join(', ');
  const remainingCount = Math.max(0, fieldLabels.length - SAVE_MESSAGE_LABEL_LIMIT);
  const messageLabel = remainingCount > 0 ? `${labelList}, +${remainingCount} more` : labelList;

  return {
    title: uniquePaths.length === 1 ? `${primaryLabel} saved` : `${uniquePaths.length} settings saved`,
    message: focusTarget
      ? `${focusTarget.sectionLabel} · ${messageLabel} · ${scopeLabel}`
      : `${messageLabel} · ${scopeLabel}`,
    link: focusTarget ? buildConfigFocusLink(focusTarget) : null,
    metadata: {
      scope,
      touched_paths: uniquePaths,
      field_labels: fieldLabels,
      focus_target: focusTarget
        ? {
            page: focusTarget.page,
            section_id: focusTarget.sectionId,
            field_path: focusTarget.fieldPath,
            field_label: focusTarget.fieldLabel,
          }
        : null,
    },
  };
}

function findSectionRule(path: string): ConfigSectionTarget | null {
  for (const rule of SECTION_RULES) {
    if (path === rule.prefix || path.startsWith(`${rule.prefix}.`)) {
      const { page, sectionId, sectionLabel, searchParams } = rule;
      return { page, sectionId, sectionLabel, searchParams };
    }
  }
  return null;
}

function resolveFieldLabel(path: string): string {
  const exact = EXACT_FIELD_LABELS[path];
  if (exact) return exact;

  for (const rule of DYNAMIC_FIELD_LABEL_RULES) {
    if (path === rule.prefix || path.startsWith(rule.prefix)) {
      const label = rule.format(path);
      if (label) return label;
    }
  }

  return humanizeToken(path.split('.').pop() ?? 'setting');
}

function humanizeToken(value: string): string {
  return value
    .split(/[-_]/g)
    .filter(Boolean)
    .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
    .join(' ');
}
