import { billingCycleForSchedule, scheduleValue } from './billingSchedule';

interface Category {
  id: string | number;
  name?: string | null;
}

interface Template {
  name?: string | null;
  categoryKeywords?: string[];
}

// The source bill a draft is seeded from. The specific fields the draft reads
// are declared; the index signature carries every other field through the spread.
export interface SourceBill {
  id?: string | number | null;
  name?: string | null;
  category_id?: string | number | null;
  due_day?: number | null;
  expected_amount?: number | null;
  cycle_type?: string | null;
  billing_cycle?: string | null;
  cycle_day?: string | number | null;
  autopay_enabled?: unknown;
  autodraft_status?: string | null;
  auto_mark_paid?: unknown;
  has_2fa?: unknown;
  snowball_include?: unknown;
  snowball_exempt?: unknown;
  [key: string]: unknown;
}

interface MakeBillDraftOptions {
  copy?: boolean;
  template?: Template | null;
  categories?: Category[];
}

function categoryForTemplate(template: Template | null | undefined, categories: Category[] = []): string | number | null {
  const keywords = template?.categoryKeywords || [];
  const match = categories.find(category => {
    const name = String(category.name || '').toLowerCase();
    return keywords.some(keyword => name.includes(keyword));
  });
  return match?.id ?? null;
}

function categoryIdOrFallback(
  categoryId: string | number | null | undefined,
  template: Template | null,
  categories: Category[] = [],
): string | number | null {
  if (categoryId && categories.some(category => String(category.id) === String(categoryId))) {
    return categoryId;
  }
  return template ? categoryForTemplate(template, categories) : null;
}

export function makeBillDraft(source: SourceBill | null | undefined, { copy = false, template = null, categories = [] }: MakeBillDraftOptions = {}): SourceBill {
  const data: SourceBill = source || {};
  return {
    ...data,
    id: undefined,
    source_bill_id: copy && data.id != null ? data.id : undefined,
    active: 1,
    name: copy
      ? `${data.name || 'Bill'} (Copy)`
      : (data.name || template?.name || ''),
    category_id: categoryIdOrFallback(data.category_id, template, categories),
    due_day: data.due_day || 1,
    expected_amount: data.expected_amount ?? 0,
    billing_cycle: billingCycleForSchedule(scheduleValue(data)),
    cycle_type: scheduleValue(data),
    cycle_day: String(data.cycle_day || '1'),
    autopay_enabled: !!data.autopay_enabled,
    autodraft_status: data.autodraft_status || (data.autopay_enabled ? 'assumed_paid' : 'none'),
    auto_mark_paid: !!data.auto_mark_paid,
    has_2fa: !!data.has_2fa,
    snowball_include: !!data.snowball_include,
    snowball_exempt: !!data.snowball_exempt,
  };
}

/** The pre-filled draft object produced by makeBillDraft (fed to BillModal's `initialBill`). */
export type BillDraft = ReturnType<typeof makeBillDraft>;
