import {
  createContext,
  PropsWithChildren,
  useCallback,
  useContext,
  useMemo,
  useReducer,
} from 'react';

import type { PaymentMethod } from '@/constants/accounts';
import type { OcrResult } from '@/lib/ocr';

export type Mode = 'expense' | 'report';

/**
 * 1回の業務フロー（撮影→確認→編集→送信）で扱う一時データ。
 * ホーム画面でリセットされ、送信完了でクリアされる。
 */
export type Draft = {
  mode: Mode;
  imageUri?: string;
  capturedAt?: string;
  ocr?: OcrResult;

  debitAccountCode?: string;
  creditAccountCode?: string;
  payment?: PaymentMethod;
  amount?: number;
  memo?: string;
};

type Action =
  | { type: 'reset'; mode: Mode }
  | { type: 'setImage'; imageUri: string; capturedAt: string }
  | { type: 'setOcr'; ocr: OcrResult }
  | { type: 'patch'; patch: Partial<Draft> };

function reducer(state: Draft, action: Action): Draft {
  switch (action.type) {
    case 'reset':
      return { mode: action.mode };
    case 'setImage':
      return { ...state, imageUri: action.imageUri, capturedAt: action.capturedAt };
    case 'setOcr':
      return { ...state, ocr: action.ocr };
    case 'patch':
      return { ...state, ...action.patch };
    default:
      return state;
  }
}

type DraftContextValue = {
  draft: Draft;
  resetDraft: (mode: Mode) => void;
  setImage: (imageUri: string, capturedAt: string) => void;
  setOcr: (ocr: OcrResult) => void;
  patchDraft: (patch: Partial<Draft>) => void;
};

const DraftContext = createContext<DraftContextValue | null>(null);

export function DraftProvider({ children }: PropsWithChildren) {
  const [draft, dispatch] = useReducer(reducer, { mode: 'expense' } satisfies Draft);

  const resetDraft = useCallback((mode: Mode) => {
    dispatch({ type: 'reset', mode });
  }, []);

  const setImage = useCallback((imageUri: string, capturedAt: string) => {
    dispatch({ type: 'setImage', imageUri, capturedAt });
  }, []);

  const setOcr = useCallback((ocr: OcrResult) => {
    dispatch({ type: 'setOcr', ocr });
  }, []);

  const patchDraft = useCallback((patch: Partial<Draft>) => {
    dispatch({ type: 'patch', patch });
  }, []);

  const value = useMemo<DraftContextValue>(
    () => ({ draft, resetDraft, setImage, setOcr, patchDraft }),
    [draft, resetDraft, setImage, setOcr, patchDraft]
  );

  return <DraftContext.Provider value={value}>{children}</DraftContext.Provider>;
}

export function useDraft(): DraftContextValue {
  const ctx = useContext(DraftContext);
  if (!ctx) {
    throw new Error('useDraft must be used within a DraftProvider');
  }
  return ctx;
}
