import { useCallback, useMemo, useState } from 'react';
import { researchBridge } from '../lib/researchBridge';
import type {
  CaptureResearchNoteRequest,
  NoteEmbedInput,
  NoteCaptureResult,
  NoteType,
  SourceKind,
} from '../types/research';

export interface ResearchComposerState {
  rawText: string;
  bodyHtml: string;
  embeds: NoteEmbedInput[];
  fileIds: string[];
  ticker: string;
  workspaceId: string;
  sourceUrl: string;
  sourceTitle: string;
  sourceKind: SourceKind;
  userNoteTypeOverride?: NoteType;
  includeCurrentContext: boolean;
  captureMode: 'standard' | 'link';
  linkUrlDraft: string;
}

interface UseResearchComposerArgs {
  defaultWorkspaceId?: string | null;
  defaultTicker?: string;
}

export const createInitialResearchComposerState = (
  defaultWorkspaceId?: string | null,
  defaultTicker?: string,
): ResearchComposerState => ({
  rawText: '',
  bodyHtml: '',
  embeds: [],
  fileIds: [],
  ticker: defaultTicker ?? '',
  workspaceId: defaultWorkspaceId ?? '',
  sourceUrl: '',
  sourceTitle: '',
  sourceKind: 'manual',
  userNoteTypeOverride: undefined,
  includeCurrentContext: true,
  captureMode: 'standard',
  linkUrlDraft: '',
});

export const useResearchComposer = ({
  defaultWorkspaceId,
  defaultTicker,
}: UseResearchComposerArgs = {}) => {
  const [draft, setDraft] = useState<ResearchComposerState>(
    createInitialResearchComposerState(defaultWorkspaceId, defaultTicker),
  );
  const [isSubmitting, setIsSubmitting] = useState(false);
  const [error, setError] = useState<string | null>(null);

  const hasContent = useMemo(() => Boolean(draft.rawText.trim()), [draft.rawText]);
  const hasWorkspace = useMemo(() => Boolean(draft.workspaceId.trim()), [draft.workspaceId]);

  const updateDraft = useCallback((patch: Partial<ResearchComposerState>) => {
    setDraft((current) => ({ ...current, ...patch }));
  }, []);

  const setErrorMessage = useCallback((message: string | null) => {
    setError(message);
  }, []);

  const resetDraft = useCallback((workspaceId = draft.workspaceId, ticker = draft.ticker) => {
    setDraft(createInitialResearchComposerState(workspaceId, ticker));
    setError(null);
  }, [draft.ticker, draft.workspaceId]);

  const validateDraft = useCallback(
    (workspaceId?: string | null) => {
      if (!draft.rawText.trim()) {
        throw new Error('Note text is required.');
      }

      if (!workspaceId && !draft.workspaceId.trim()) {
        throw new Error('Select or create a research workspace before saving this note.');
      }
    },
    [draft.rawText, draft.workspaceId],
  );

  const buildCaptureRequest = useCallback(
    (
      workspaceId: string,
      overrides: Partial<CaptureResearchNoteRequest> = {},
    ): CaptureResearchNoteRequest => ({
      workspaceId,
      rawText: draft.rawText.trim(),
      bodyHtml: draft.bodyHtml || undefined,
      embeds: draft.embeds,
      fileIds: draft.fileIds,
      ticker: draft.ticker || undefined,
      userNoteTypeOverride: draft.userNoteTypeOverride,
      sourceRef: draft.sourceUrl || draft.sourceTitle
        ? {
            kind: draft.sourceKind,
            title: draft.sourceTitle || undefined,
            url: draft.sourceUrl || undefined,
          }
        : undefined,
      ...overrides,
    }),
    [
      draft.rawText,
      draft.bodyHtml,
      draft.embeds,
      draft.sourceKind,
      draft.sourceTitle,
      draft.sourceUrl,
      draft.ticker,
      draft.userNoteTypeOverride,
    ],
  );

  const submitWithWorkspace = useCallback(async (
    workspaceId: string,
    overrides: Partial<CaptureResearchNoteRequest> = {},
  ): Promise<NoteCaptureResult> => {
    validateDraft(workspaceId);
    setIsSubmitting(true);
    setError(null);
    try {
      const result = await researchBridge.captureResearchNote(
        buildCaptureRequest(workspaceId, overrides),
      );
      resetDraft(workspaceId, draft.ticker);
      return result;
    } catch (submitError) {
      const nextError =
        submitError instanceof Error ? submitError.message : String(submitError);
      setError(nextError);
      throw submitError;
    } finally {
      setIsSubmitting(false);
    }
  }, [buildCaptureRequest, draft.ticker, resetDraft, validateDraft]);

  const submit = useCallback(async (
    overrides: Partial<CaptureResearchNoteRequest> = {},
  ): Promise<NoteCaptureResult> => {
    return submitWithWorkspace(draft.workspaceId, overrides);
  }, [draft.workspaceId, submitWithWorkspace]);

  const insertFormatting = useCallback((
    kind: 'bullet' | 'heading' | 'quote' | 'callout',
  ) => {
    const prefix =
      kind === 'bullet'
        ? '- '
        : kind === 'heading'
          ? '## '
          : kind === 'quote'
            ? '> '
            : '> Thesis angle: ';
    setDraft((current) => ({
      ...current,
      rawText: current.rawText ? `${current.rawText}\n${prefix}` : prefix,
    }));
  }, []);

  return {
    draft,
    setDraft: updateDraft,
    resetDraft,
    validateDraft,
    buildCaptureRequest,
    submitWithWorkspace,
    submit,
    insertFormatting,
    hasContent,
    hasWorkspace,
    isValid: hasContent,
    isSubmitting,
    error,
    setErrorMessage,
  };
};
