import { invoke } from '@tauri-apps/api/core';
import { listen, type UnlistenFn } from '@tauri-apps/api/event';
import type {
  ArchiveResearchNoteRequest,
  ArchiveResearchWorkspaceRequest,
  CaptureResearchNoteRequest,
  CreateFinancialModelRequest,
  CreateResearchWorkspaceRequest,
  EvaluateFinancialModelRequest,
  EvaluateFinancialModelResult,
  ExportFinancialModelXlsxRequest,
  ExportFinancialModelXlsxResult,
  ExportResearchBundleRequest,
  FinancialModel,
  GetFinancialModelRequest,
  GetNoteAuditTrailRequest,
  GetResearchFileTextPreviewRequest,
  GetNotesByTickerRequest,
  GetWorkspaceProjectionRequest,
  GhostNote,
  ListFinancialModelsRequest,
  ListModelCellAnnotationsRequest,
  ListModelDataBindingsRequest,
  ListNoteLinksRequest,
  ListResearchFilesRequest,
  ListResearchNotesRequest,
  ListWorkspaceGhostNotesRequest,
  NoteAuditTrail,
  NoteCaptureResult,
  NoteLink,
  PipelineJob,
  PreviewLinkRequest,
  PreviewLinkResult,
  PromoteNoteToThesisRequest,
  ResearchBundleExport,
  ResearchFile,
  ResearchFileTextPreview,
  ResearchGhostUpdateEvent,
  ResearchJobUpdateEvent,
  ResearchNote,
  ResearchNoteUpdateEvent,
  ResearchWorkspace,
  ResearchWorkspaceUpdateEvent,
  RetryResearchJobsRequest,
  ResolveGhostInterventionRequest,
  ReviewGhostNoteRequest,
  SaveFinancialModelRequest,
  SaveModelDataBindingRequest,
  SearchResearchNotesRequest,
  LinkNoteToModelCellRequest,
  UpdateResearchNoteRequest,
  UpdateModelCellAnnotationRequest,
  UpdateResearchWorkspaceRequest,
  UnlinkNoteFromModelCellRequest,
  UploadResearchFilesRequest,
  WorkspaceProjection,
  ModelCellAnnotation,
  ModelDataBinding,
  RefreshModelDataBindingsRequest,
} from '../types/research';

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 ResearchBridge {
  createResearchWorkspace(
    request: CreateResearchWorkspaceRequest,
  ): Promise<ResearchWorkspace>;
  listResearchWorkspaces(): Promise<ResearchWorkspace[]>;
  getResearchWorkspace(workspaceId: string): Promise<ResearchWorkspace>;
  captureResearchNote(request: CaptureResearchNoteRequest): Promise<NoteCaptureResult>;
  previewNoteLink(request: PreviewLinkRequest): Promise<PreviewLinkResult>;
  updateResearchNote(request: UpdateResearchNoteRequest): Promise<ResearchNote>;
  archiveResearchNote(request: ArchiveResearchNoteRequest): Promise<ResearchNote>;
  listResearchNotes(request: ListResearchNotesRequest): Promise<ResearchNote[]>;
  getNotesByTicker(request: GetNotesByTickerRequest): Promise<ResearchNote[]>;
  getWorkspaceProjection(
    request: GetWorkspaceProjectionRequest,
  ): Promise<WorkspaceProjection>;
  listFinancialModels(request: ListFinancialModelsRequest): Promise<FinancialModel[]>;
  getFinancialModel(request: GetFinancialModelRequest): Promise<FinancialModel>;
  createFinancialModel(request: CreateFinancialModelRequest): Promise<FinancialModel>;
  saveFinancialModel(request: SaveFinancialModelRequest): Promise<FinancialModel>;
  evaluateFinancialModel(
    request: EvaluateFinancialModelRequest,
  ): Promise<EvaluateFinancialModelResult>;
  listModelDataBindings(
    request: ListModelDataBindingsRequest,
  ): Promise<ModelDataBinding[]>;
  saveModelDataBinding(request: SaveModelDataBindingRequest): Promise<ModelDataBinding>;
  refreshModelDataBindings(
    request: RefreshModelDataBindingsRequest,
  ): Promise<ModelDataBinding[]>;
  linkNoteToModelCell(request: LinkNoteToModelCellRequest): Promise<ModelCellAnnotation>;
  unlinkNoteFromModelCell(
    request: UnlinkNoteFromModelCellRequest,
  ): Promise<ModelCellAnnotation>;
  updateModelCellAnnotation(
    request: UpdateModelCellAnnotationRequest,
  ): Promise<ModelCellAnnotation>;
  listModelCellAnnotations(
    request: ListModelCellAnnotationsRequest,
  ): Promise<ModelCellAnnotation[]>;
  exportFinancialModelXlsx(
    request: ExportFinancialModelXlsxRequest,
  ): Promise<ExportFinancialModelXlsxResult>;
  listNoteLinks(request: ListNoteLinksRequest): Promise<NoteLink[]>;
  listWorkspaceGhostNotes(
    request: ListWorkspaceGhostNotesRequest,
  ): Promise<GhostNote[]>;
  reviewGhostNote(request: ReviewGhostNoteRequest): Promise<GhostNote>;
  resolveGhostIntervention(request: ResolveGhostInterventionRequest): Promise<GhostNote>;
  promoteNoteToThesis(
    request: PromoteNoteToThesisRequest,
  ): Promise<ResearchNote>;
  listResearchJobs(request: import('../types/research').ListResearchJobsRequest): Promise<PipelineJob[]>;
  retryResearchJobs(request: RetryResearchJobsRequest): Promise<PipelineJob[]>;
  getNoteAuditTrail(request: GetNoteAuditTrailRequest): Promise<NoteAuditTrail>;
  listResearchFiles(request: ListResearchFilesRequest): Promise<ResearchFile[]>;
  uploadResearchFiles(request: UploadResearchFilesRequest): Promise<ResearchFile[]>;
  getResearchFileTextPreview(
    request: GetResearchFileTextPreviewRequest,
  ): Promise<ResearchFileTextPreview>;
  exportResearchBundle(
    request: ExportResearchBundleRequest,
  ): Promise<ResearchBundleExport>;
  searchResearchNotes(
    request: SearchResearchNotesRequest,
  ): Promise<ResearchNote[]>;
  updateResearchWorkspace(
    request: UpdateResearchWorkspaceRequest,
  ): Promise<ResearchWorkspace>;
  archiveResearchWorkspace(
    request: ArchiveResearchWorkspaceRequest,
  ): Promise<ResearchWorkspace>;
  listenForWorkspaceUpdates(
    handler: (payload: ResearchWorkspaceUpdateEvent) => void,
  ): Promise<UnlistenFn>;
  listenForNoteUpdates(
    handler: (payload: ResearchNoteUpdateEvent) => void,
  ): Promise<UnlistenFn>;
  listenForGhostUpdates(
    handler: (payload: ResearchGhostUpdateEvent) => void,
  ): Promise<UnlistenFn>;
  listenForJobUpdates(
    handler: (payload: ResearchJobUpdateEvent) => void,
  ): Promise<UnlistenFn>;
}

export const createResearchBridge = (
  invoker: Invoker = invoke,
  listener: Listener = listen,
): ResearchBridge => ({
  createResearchWorkspace(request) {
    return invoker<ResearchWorkspace>('create_research_workspace', { request });
  },

  listResearchWorkspaces() {
    return invoker<ResearchWorkspace[]>('list_research_workspaces');
  },

  getResearchWorkspace(workspaceId) {
    return invoker<ResearchWorkspace>('get_research_workspace', { workspaceId });
  },

  captureResearchNote(request) {
    return invoker<NoteCaptureResult>('capture_research_note', { request });
  },

  previewNoteLink(request) {
    return invoker<PreviewLinkResult>('preview_note_link', { request });
  },

  updateResearchNote(request) {
    return invoker<ResearchNote>('update_research_note', { request });
  },

  archiveResearchNote(request) {
    return invoker<ResearchNote>('archive_research_note', { request });
  },

  listResearchNotes(request) {
    return invoker<ResearchNote[]>('list_research_notes', { request });
  },

  getNotesByTicker(request) {
    return invoker<ResearchNote[]>('get_notes_by_ticker', { request });
  },

  getWorkspaceProjection(request) {
    return invoker<WorkspaceProjection>('get_workspace_projection', { request });
  },

  listFinancialModels(request) {
    return invoker<FinancialModel[]>('list_financial_models', { request });
  },

  getFinancialModel(request) {
    return invoker<FinancialModel>('get_financial_model', { request });
  },

  createFinancialModel(request) {
    return invoker<FinancialModel>('create_financial_model', { request });
  },

  saveFinancialModel(request) {
    return invoker<FinancialModel>('save_financial_model', { request });
  },

  evaluateFinancialModel(request) {
    return invoker<EvaluateFinancialModelResult>('evaluate_financial_model', { request });
  },

  listModelDataBindings(request) {
    return invoker<ModelDataBinding[]>('list_model_data_bindings', { request });
  },

  saveModelDataBinding(request) {
    return invoker<ModelDataBinding>('save_model_data_binding', { request });
  },

  refreshModelDataBindings(request) {
    return invoker<ModelDataBinding[]>('refresh_model_data_bindings', { request });
  },

  linkNoteToModelCell(request) {
    return invoker<ModelCellAnnotation>('link_note_to_model_cell', { request });
  },

  unlinkNoteFromModelCell(request) {
    return invoker<ModelCellAnnotation>('unlink_note_from_model_cell', { request });
  },

  updateModelCellAnnotation(request) {
    return invoker<ModelCellAnnotation>('update_model_cell_annotation', { request });
  },

  listModelCellAnnotations(request) {
    return invoker<ModelCellAnnotation[]>('list_model_cell_annotations', { request });
  },

  exportFinancialModelXlsx(request) {
    return invoker<ExportFinancialModelXlsxResult>('export_financial_model_xlsx', { request });
  },

  listNoteLinks(request) {
    return invoker<NoteLink[]>('list_note_links', { request });
  },

  listWorkspaceGhostNotes(request) {
    return invoker<GhostNote[]>('list_workspace_ghost_notes', { request });
  },

  reviewGhostNote(request) {
    return invoker<GhostNote>('review_ghost_note', { request });
  },

  resolveGhostIntervention(request) {
    return invoker<GhostNote>('resolve_ghost_intervention', { request });
  },

  promoteNoteToThesis(request) {
    return invoker<ResearchNote>('promote_note_to_thesis', { request });
  },

  listResearchJobs(request) {
    return invoker<PipelineJob[]>('list_research_jobs', { request });
  },

  retryResearchJobs(request) {
    return invoker<PipelineJob[]>('retry_research_jobs', { request });
  },

  getNoteAuditTrail(request) {
    return invoker<NoteAuditTrail>('get_note_audit_trail', { request });
  },

  listResearchFiles(request) {
    return invoker<ResearchFile[]>('list_research_files', { request });
  },

  uploadResearchFiles(request) {
    return invoker<ResearchFile[]>('upload_research_files', { request });
  },

  getResearchFileTextPreview(request) {
    return invoker<ResearchFileTextPreview>('get_research_file_text_preview', { request });
  },

  exportResearchBundle(request) {
    return invoker<ResearchBundleExport>('export_research_bundle', { request });
  },

  searchResearchNotes(request) {
    return invoker<ResearchNote[]>('search_research_notes', { request });
  },

  updateResearchWorkspace(request) {
    return invoker<ResearchWorkspace>('update_research_workspace', { request });
  },

  archiveResearchWorkspace(request) {
    return invoker<ResearchWorkspace>('archive_research_workspace', { request });
  },

  listenForWorkspaceUpdates(handler) {
    return listener<ResearchWorkspace>('research_workspace_updated', (event) =>
      handler({
        workspaceId: event.payload.id,
        workspace: event.payload,
      }),
    );
  },

  listenForNoteUpdates(handler) {
    return listener<ResearchNote>('research_note_updated', (event) =>
      handler({
        workspaceId: event.payload.workspaceId,
        note: event.payload,
      }),
    );
  },

  listenForGhostUpdates(handler) {
    return listener<GhostNote>('research_ghost_updated', (event) =>
      handler({
        workspaceId: event.payload.workspaceId,
        ghost: event.payload,
      }),
    );
  },

  listenForJobUpdates(handler) {
    return listener<PipelineJob>('research_job_updated', (event) =>
      handler({
        workspaceId: event.payload.workspaceId,
        job: event.payload,
      }),
    );
  },
});

export const researchBridge = createResearchBridge();
