import { useState } from 'react'
import { useTranslation } from 'react-i18next'
import { MasterDetail } from '@/components/templates'
import {
  Badge,
  Checkbox,
  ConfirmDialog,
  EmptyState,
  Field,
  Input,
  SegmentedControl,
  Select,
  StatusPill,
  useToast,
  type Column,
} from '@/components/ui'
import { useListPagination } from '@/lib/useListPagination'
import { currencySymbol, formatMoney, minorUnitFactor } from '@/lib/money'
import { getCurrency } from '@/lib/locale'
import {
  useCharges,
  useCreateCharge,
  useCrudPanel,
  useDeleteCharge,
  useTaxGroups,
  useUpdateCharge,
  type Charge,
  type ChargeInput,
  type ChargeKind,
} from '../hooks'
import { serverMessage } from '@/lib/api'

interface Draft {
  name: string
  code: string
  kind: ChargeKind
  amount: string // rupees
  rate: string // percent
  taxable: boolean
  tax_group_id: string
  active: boolean
  sort: string
}
const empty: Draft = { name: '', code: '', kind: 'fixed', amount: '0', rate: '0', taxable: false, tax_group_id: '', active: true, sort: '99' }

/**
 * Charges (T2) — typed order-level extras a cashier can add to a bill (delivery,
 * packing, handling). Each is a fixed rupee amount or a percent of the order
 * subtotal, optionally taxed. Edit in place.
 */
export function ChargesPage() {
  const { t } = useTranslation()
  const toast = useToast()
  const pager = useListPagination()
  const { data, meta, isLoading } = useCharges(pager.params)
  // active=1 — see the Tax groups screen's own toast.
  const { data: groups } = useTaxGroups({ active: 1, per_page: 100 })
  const create = useCreateCharge()
  const update = useUpdateCharge()
  const del = useDeleteCharge()
  const panel = useCrudPanel<Charge, Draft>(empty, (c) => ({
    name: c.name,
    code: c.code,
    kind: c.kind,
    amount: c.amount ? String(c.amount.amount / minorUnitFactor(c.amount.currency)) : '0',
    rate: c.rate != null ? String(c.rate) : '0',
    taxable: c.taxable,
    tax_group_id: c.tax_group_id ? String(c.tax_group_id) : '',
    active: c.active,
    sort: String(c.sort),
  }))
  const [confirmDelete, setConfirmDelete] = useState(false)

  // Re-sorting is within the page only — the server already orders the whole
  // list by sort_order, so this just keeps rows tidy if two share an order.
  const rows = [...(data ?? [])].sort((a, b) => a.sort - b.sort)
  const groupName = (id: number | null) => (id == null ? null : groups?.find((g) => g.id === id)?.name ?? null)

  const save = () => {
    const d = panel.draft
    if (!d.name.trim() || !d.code.trim()) {
      toast.danger(t('Name and code required'), t('A charge needs a name and a stable code.'))
      return
    }
    if (d.kind === 'fixed' && (Number(d.amount) || 0) <= 0) {
      toast.danger(t('Amount required'), t('A fixed charge needs an amount above zero.'))
      return
    }
    if (d.kind === 'percent') {
      const r = Number(d.rate) || 0
      if (r <= 0) {
        toast.danger(t('Rate required'), t('A percent charge needs a rate above zero.'))
        return
      }
      if (r > 100) {
        toast.danger(t('Rate too high'), t('A percentage charge cannot be more than 100%.'))
        return
      }
    }
    const input: ChargeInput = {
      name: d.name.trim(),
      code: d.code.trim().toUpperCase(),
      kind: d.kind,
      amount: d.kind === 'fixed' ? { amount: Math.round((Number(d.amount) || 0) * minorUnitFactor(getCurrency())), currency: getCurrency() } : null,
      rate: d.kind === 'percent' ? Number(d.rate) || 0 : null,
      taxable: d.taxable,
      tax_group_id: d.taxable && d.tax_group_id ? Number(d.tax_group_id) : null,
      active: d.active,
      sort: Number(d.sort) || 0,
    }
    const onError = (e: unknown) => toast.danger(t('Could not save'), serverMessage(e, t('Please try again.')))
    if (panel.isNew)
      create.mutate(input, {
        onSuccess: () => {
          toast.success(t('Charge created'), t('{{name}} was created', { name: input.name }))
          panel.close()
        },
        onError,
      })
    else
      update.mutate(
        { id: panel.editing!.id, input },
        {
          onSuccess: () => {
            toast.success(t('Charge saved'), t('{{name}} was saved', { name: input.name }))
            panel.close()
          },
          onError,
        },
      )
  }

  const remove = () => {
    if (!panel.editing) return
    del.mutate({ id: panel.editing.id }, {
      onSuccess: () => {
        toast.success(t('Charge deleted'), t('{{name}} was removed', { name: panel.editing?.name }))
        setConfirmDelete(false)
        panel.close()
      },
      onError: (e) => {
        setConfirmDelete(false)
        toast.danger(t('Could not delete'), serverMessage(e, t('Please try again.')))
      },
    })
  }

  const columns: Column<Charge>[] = [
    { key: 'name', header: t('Charge'), cell: (c) => (
      <div className="flex items-center gap-2">
        <b className="text-content">{c.name}</b>
        <span className="mono text-xs text-content-3">{c.code}</span>
      </div>
    ) },
    {
      key: 'amount',
      header: t('Value'),
      num: true,
      cell: (c) =>
        c.kind === 'fixed' && c.amount ? (
          <span className="mono">{formatMoney(c.amount)}</span>
        ) : (
          <span className="mono">{c.rate}%</span>
        ),
    },
    {
      key: 'taxable',
      header: t('Tax'),
      cell: (c) => (c.taxable ? <StatusPill tone="info">{groupName(c.tax_group_id) ?? t('Taxed')}</StatusPill> : <span className="text-content-3">{t('No tax')}</span>),
    },
    { key: 'active', header: t('Status'), cell: (c) => (c.active ? <Badge tone="accent">{t('Active')}</Badge> : <Badge tone="neutral">{t('Hidden')}</Badge>) },
  ]

  const groupOptions = (groups ?? []).map((g) => ({ value: String(g.id), label: g.name }))

  return (
    <>
      <MasterDetail<Charge>
        writePermission='Manage Settings'
        title={t('Charges')}
        microcopy={t('Typed extras a cashier can add to a bill — delivery, packing, handling — as a fixed amount or a percent.')}
        addLabel={t('Add charge')}
        onAdd={() => panel.openNew()}
        loading={isLoading}
        pagination={pager.propsFrom(meta)}
        columns={columns}
        rows={rows}
        rowKey={(c) => String(c.id)}
        onRowClick={panel.openEdit}
        isRowActive={(c) => c.id === panel.editing?.id}
        emptyState={<EmptyState icon="tag" title={t('No charges yet')} description={t('Add a delivery or packing charge cashiers can apply at checkout.')} />}
        detailOpen={panel.open}
        onCloseDetail={panel.close}
        detailTitle={panel.isNew ? t('New charge') : panel.editing?.name}
        detailSubtitle={panel.editing ? t('charge · #{{id}}', { id: panel.editing.id }) : t('charge')}
        dirty={panel.dirty}
        saving={create.isPending || update.isPending}
        onSave={save}
        onDiscard={panel.close}
        onDelete={panel.editing ? () => setConfirmDelete(true) : undefined}
        detail={
          <div className="grid gap-4">
            <Input label={t('Name')} required value={panel.draft.name} onChange={(e) => panel.patch({ name: e.target.value })} placeholder={t('e.g. Home Delivery')} />
            <Input label={t('Code')} required value={panel.draft.code} onChange={(e) => panel.patch({ code: e.target.value })} placeholder={t('e.g. DELIVERY')} help={t('Uppercased on save.')} />
            <Field label={t('Type')}>
              <SegmentedControl<ChargeKind>
                value={panel.draft.kind}
                onChange={(x) => panel.patch({ kind: x })}
                options={[
                  { value: 'fixed', label: t('Fixed {{symbol}}', { symbol: currencySymbol(getCurrency()) }) },
                  { value: 'percent', label: t('Percent %') },
                ]}
              />
            </Field>
            {panel.draft.kind === 'fixed' ? (
              <Input label={t('Amount')} type="number" min={0.01} step="0.01" prefix={currencySymbol(getCurrency())} value={panel.draft.amount} onChange={(e) => panel.patch({ amount: e.target.value })} help={t('Flat amount added to the bill.')} />
            ) : (
              <Input label={t('Rate (%)')} type="number" min={0.01} max={100} step="0.01" value={panel.draft.rate} onChange={(e) => panel.patch({ rate: e.target.value })} help={t('Percent of the order subtotal.')} />
            )}
            <Checkbox label={t('Taxable')} checked={panel.draft.taxable} onChange={(e) => panel.patch({ taxable: e.target.checked })} description={t('Apply sales tax to the charge itself.')} />
            {panel.draft.taxable && (
              <Select label={t('Tax group')} value={panel.draft.tax_group_id} onChange={(e) => panel.patch({ tax_group_id: e.target.value })} options={groupOptions} placeholder={t('— Select a group —')} />
            )}
            <Input label={t('Sort order')} type="number" min={0} value={panel.draft.sort} onChange={(e) => panel.patch({ sort: e.target.value })} help={t('Lower numbers appear first.')} />
            <Checkbox label={t('Active')} checked={panel.draft.active} onChange={(e) => panel.patch({ active: e.target.checked })} description={t("Hidden charges stay on old bills but can't be applied.")} />
          </div>
        }
      />
      <ConfirmDialog
        open={confirmDelete}
        onClose={() => setConfirmDelete(false)}
        onConfirm={remove}
        destructive
        icon="trash"
        title={t('Delete “{{name}}”?', { name: panel.editing?.name })}
        consequence={t("The charge disappears from the checkout. Bills that already carry it are unchanged. If it's in regular use, deactivate instead.")}
        confirmLabel={t('Delete charge')}
        loading={del.isPending}
      />
    </>
  )
}

export default ChargesPage
