/**
 * API bridge for custom XBRL concept mappings.
 */

import { invoke } from '@tauri-apps/api/core';
import { listen, type UnlistenFn } from '@tauri-apps/api/event';
import type {
  CustomXbrlConceptMapping,
  FormulaValidationResult,
  MappingsConfig,
  MappingsUpdatedEvent,
} from '../types/mappings';
import type { AvailableXbrlConcept } from '../types/financial';

type Invoker = <T>(
  command: string,
  args?: Record<string, unknown>,
) => Promise<T>;
type Listener = <T>(
  event: string,
  handler: (event: { payload: T }) => void,
) => Promise<UnlistenFn>;

export interface MappingsBridge {
  listMappings(): Promise<CustomXbrlConceptMapping[]>;
  getMapping(id: string): Promise<CustomXbrlConceptMapping>;
  addMapping(mapping: CustomXbrlConceptMapping): Promise<string>;
  updateMapping(id: string, mapping: CustomXbrlConceptMapping): Promise<void>;
  deleteMapping(id: string): Promise<void>;
  toggleMapping(id: string): Promise<boolean>;
  importMappings(json: string): Promise<MappingsConfig>;
  exportMappings(): Promise<string>;
  validateFormula(expression: string): Promise<FormulaValidationResult>;
  getTickerConcepts(ticker: string): Promise<AvailableXbrlConcept[]>;
  listenForUpdates(
    handler: (payload: MappingsUpdatedEvent) => void,
  ): Promise<UnlistenFn>;
}

export const createMappingsBridge = (
  invoker: Invoker = invoke,
  listener: Listener = listen,
): MappingsBridge => ({
  listMappings() {
    return invoker<CustomXbrlConceptMapping[]>('list_custom_mappings');
  },

  getMapping(id) {
    return invoker<CustomXbrlConceptMapping>('get_custom_mapping', { id });
  },

  addMapping(mapping) {
    return invoker<string>('add_custom_mapping', { mapping });
  },

  updateMapping(id, mapping) {
    return invoker<void>('update_custom_mapping', { id, mapping });
  },

  deleteMapping(id) {
    return invoker<void>('delete_custom_mapping', { id });
  },

  toggleMapping(id) {
    return invoker<boolean>('toggle_custom_mapping', { id });
  },

  importMappings(json) {
    return invoker<MappingsConfig>('import_mappings', { json });
  },

  exportMappings() {
    return invoker<string>('export_mappings');
  },

  validateFormula(expression) {
    return invoker<FormulaValidationResult>('validate_formula', { expression });
  },

  getTickerConcepts(ticker) {
    return invoker<AvailableXbrlConcept[]>('get_ticker_concepts', { ticker });
  },

  listenForUpdates(handler) {
    return listener<MappingsUpdatedEvent>('mappings_updated', (event) =>
      handler(event.payload),
    );
  },
});

export const mappingsBridge = createMappingsBridge();
