import { formatIrtInput, parseIrtInput } from '../utils/irtPrice'
import type {
  InvoiceAccountInput,
  InvoiceItemInput,
  InvoiceItemTemplate,
  InvoiceKeyPointInput,
  InvoiceTemplate,
  InvoiceTemplateItemInput,
} from '../types/invoice'

export type DraftLineItem = {
  key: string
  itemTemplateId?: string
  title: string
  duration: string
  worktime: string
  description: string
  price: string
  discountedPrice: string
}

export type DraftKeyPoint = { key: string; text: string }

export type DraftAccount = {
  key: string
  bankName: string
  accountHolderName: string
  cardNumber: string
  iban: string
}

export function newKey() {
  return `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`
}

export function emptyDraftItem(): DraftLineItem {
  return {
    key: newKey(),
    title: '',
    duration: '',
    worktime: '',
    description: '',
    price: '',
    discountedPrice: '',
  }
}

export function emptyDraftKeyPoint(): DraftKeyPoint {
  return { key: newKey(), text: '' }
}

export function emptyDraftAccount(): DraftAccount {
  return { key: newKey(), bankName: '', accountHolderName: '', cardNumber: '', iban: '' }
}

export function draftItemFromItemTemplate(template: InvoiceItemTemplate): DraftLineItem {
  return {
    key: newKey(),
    itemTemplateId: template.id,
    title: template.title,
    duration: template.duration ?? '',
    worktime: template.worktime ?? '',
    description: template.description ?? '',
    price: formatIrtInput(String(Math.round(template.price))),
    discountedPrice:
      template.discountedPrice === null || template.discountedPrice === undefined
        ? ''
        : formatIrtInput(String(Math.round(template.discountedPrice))),
  }
}

export function draftsFromInvoiceTemplate(template: InvoiceTemplate): {
  name: string
  topText: string
  items: DraftLineItem[]
  keyPoints: DraftKeyPoint[]
  accounts: DraftAccount[]
} {
  return {
    name: template.name,
    topText: template.topText ?? '',
    items:
      template.items.length > 0
        ? template.items.map((item) => ({
            key: newKey(),
            itemTemplateId: item.itemTemplateId ?? undefined,
            title: item.title,
            duration: item.duration ?? '',
            worktime: item.worktime ?? '',
            description: item.description ?? '',
            price: formatIrtInput(String(Math.round(item.price))),
            discountedPrice:
              item.discountedPrice === null || item.discountedPrice === undefined
                ? ''
                : formatIrtInput(String(Math.round(item.discountedPrice))),
          }))
        : [emptyDraftItem()],
    keyPoints:
      template.keyPoints.length > 0
        ? template.keyPoints.map((kp) => ({ key: newKey(), text: kp.text }))
        : [],
    accounts:
      template.accounts.length > 0
        ? template.accounts.map((acc) => ({
            key: newKey(),
            bankName: acc.bankName,
            accountHolderName: acc.accountHolderName ?? '',
            cardNumber: acc.cardNumber ?? '',
            iban: acc.iban ?? '',
          }))
        : [],
  }
}

export function draftsFromInvoice(invoice: {
  name: string | null
  topText: string | null
  notes?: string | null
  items?: Array<{
    templateId: string | null
    title: string
    duration: string | null
    worktime: string | null
    description: string | null
    price: number
    discountedPrice: number | null
  }>
  keyPoints?: Array<{ text: string }>
  accounts?: Array<{
    bankName: string
    accountHolderName: string | null
    cardNumber: string | null
    iban: string | null
  }>
}): {
  name: string
  topText: string
  notes: string
  items: DraftLineItem[]
  keyPoints: DraftKeyPoint[]
  accounts: DraftAccount[]
} {
  return {
    name: invoice.name ?? '',
    topText: invoice.topText ?? '',
    notes: invoice.notes ?? '',
    items:
      (invoice.items?.length ?? 0) > 0
        ? invoice.items!.map((item) => ({
            key: newKey(),
            itemTemplateId: item.templateId ?? undefined,
            title: item.title,
            duration: item.duration ?? '',
            worktime: item.worktime ?? '',
            description: item.description ?? '',
            price: formatIrtInput(String(Math.round(item.price))),
            discountedPrice:
              item.discountedPrice === null || item.discountedPrice === undefined
                ? ''
                : formatIrtInput(String(Math.round(item.discountedPrice))),
          }))
        : [emptyDraftItem()],
    keyPoints:
      (invoice.keyPoints?.length ?? 0) > 0
        ? invoice.keyPoints!.map((kp) => ({ key: newKey(), text: kp.text }))
        : [],
    accounts:
      (invoice.accounts?.length ?? 0) > 0
        ? invoice.accounts!.map((acc) => ({
            key: newKey(),
            bankName: acc.bankName,
            accountHolderName: acc.accountHolderName ?? '',
            cardNumber: acc.cardNumber ?? '',
            iban: acc.iban ?? '',
          }))
        : [],
  }
}

export function buildLineItemsPayload(items: DraftLineItem[]): InvoiceItemInput[] {
  return items.map((item) => {
    const title = item.title.trim()
    const price = parseIrtInput(item.price)
    if (!title) throw new Error('Each item needs a title.')
    if (price === null) throw new Error(`Price is required for “${title}”.`)
    const discountedPrice = item.discountedPrice.trim()
      ? parseIrtInput(item.discountedPrice)
      : null
    if (item.discountedPrice.trim() && discountedPrice === null) {
      throw new Error(`Discounted price is invalid for “${title}”.`)
    }
    if (discountedPrice !== null && discountedPrice > price) {
      throw new Error(`Discounted price cannot exceed price for “${title}”.`)
    }
    return {
      templateId: item.itemTemplateId,
      title,
      duration: item.duration.trim() || undefined,
      worktime: item.worktime.trim() || undefined,
      description: item.description.trim() || undefined,
      price,
      discountedPrice,
    }
  })
}

export function buildTemplateItemsPayload(items: DraftLineItem[]): InvoiceTemplateItemInput[] {
  return buildLineItemsPayload(items).map((item) => ({
    itemTemplateId: item.templateId,
    title: item.title,
    duration: item.duration,
    worktime: item.worktime,
    description: item.description,
    price: item.price,
    discountedPrice: item.discountedPrice,
  }))
}

export function buildKeyPointsPayload(points: DraftKeyPoint[]): InvoiceKeyPointInput[] {
  return points
    .map((p) => p.text.trim())
    .filter(Boolean)
    .map((text) => ({ text }))
}

export function buildAccountsPayload(accounts: DraftAccount[]): InvoiceAccountInput[] {
  return accounts
    .map((acc) => ({
      bankName: acc.bankName.trim(),
      accountHolderName: acc.accountHolderName.trim() || undefined,
      cardNumber: acc.cardNumber.trim() || undefined,
      iban: acc.iban.trim() || undefined,
    }))
    .filter((acc) => acc.bankName)
}
