"use client"

import { useEffect, useState } from "react"

import { bankAccountsApi, receivedChequesApi } from "@/lib/api/general-ledger"
import { errorMessage } from "@/lib/error-map"
import { formatAmount, formatReportDate } from "@/lib/format"
import { cn } from "@/lib/utils"
import {
  CashAndBankAccountDto,
  CashBankAccountType,
  ReceivedCheque,
  ReceivedChequeStatus,
  ReceivedChequeStatusAction,
} from "@/types/general-ledger"

import { Badge } from "@/components/ui/badge"
import { Button } from "@/components/ui/button"
import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog"
import { Field, FieldError, FieldGroup, FieldLabel } from "@/components/ui/field"
import { Input } from "@/components/ui/input"
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
import { toast } from "@/components/ui/toast"

const STATUS_BADGE: Record<ReceivedChequeStatus, string> = {
  [ReceivedChequeStatus.Received]: "bg-muted text-muted-foreground",
  [ReceivedChequeStatus.Deposited]: "bg-primary/10 text-primary",
  [ReceivedChequeStatus.Cleared]: "bg-success/10 text-success",
  [ReceivedChequeStatus.Returned]: "bg-destructive/10 text-destructive",
  [ReceivedChequeStatus.Cancelled]: "bg-destructive/10 text-destructive",
}

interface ReceivedChequeDialogProps {
  cheque: ReceivedCheque | null
  open: boolean
  onOpenChange: (open: boolean) => void
  onUpdated: (updated: ReceivedCheque) => void
}

/** View a received cheque's details and (from `Received`/`Deposited`) move it through
 * Deposit/Clear/Return/Cancel — a modal, same posture as `ChequePageDialog`. */
export function ReceivedChequeDialog({ cheque, open, onOpenChange, onUpdated }: ReceivedChequeDialogProps) {
  const [pendingAction, setPendingAction] = useState<ReceivedChequeStatusAction | null>(null)
  const [submitting, setSubmitting] = useState(false)
  const [errors, setErrors] = useState<Record<string, string>>({})

  const [bankAccounts, setBankAccounts] = useState<CashAndBankAccountDto[] | null>(null)
  const [depositBankAccountId, setDepositBankAccountId] = useState("")
  const [depositDate, setDepositDate] = useState("")
  const [performedBy, setPerformedBy] = useState("")
  const [notes, setNotes] = useState("")

  useEffect(() => {
    if (pendingAction !== ReceivedChequeStatusAction.Deposit || bankAccounts !== null) return
    bankAccountsApi.list(CashBankAccountType.Bank).then(setBankAccounts).catch(() => setBankAccounts([]))
    // Only fetched once, lazily, the first time Deposit is chosen.
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [pendingAction])

  function resetActionState() {
    setPendingAction(null)
    setErrors({})
    setDepositBankAccountId("")
    setDepositDate("")
    setPerformedBy("")
    setNotes("")
  }

  function handleOpenChange(next: boolean) {
    if (!next) resetActionState()
    onOpenChange(next)
  }

  async function submitStatusAction(action: ReceivedChequeStatusAction) {
    if (!cheque) return
    if (action === ReceivedChequeStatusAction.Deposit) {
      const nextErrors: Record<string, string> = {}
      if (!depositBankAccountId) nextErrors.depositBankAccountId = "Select a deposit bank account"
      if (!depositDate) nextErrors.depositDate = "Deposit date is required"
      setErrors(nextErrors)
      if (Object.keys(nextErrors).length > 0) return
    }
    setSubmitting(true)
    try {
      const updated = await receivedChequesApi.updateStatus(cheque.receivedChequeId, {
        action,
        depositBankAccountId: action === ReceivedChequeStatusAction.Deposit ? Number(depositBankAccountId) : undefined,
        depositDate: action === ReceivedChequeStatusAction.Deposit ? depositDate : undefined,
        notes: notes || undefined,
        performedBy: performedBy || undefined,
      })
      toast.success(`Cheque ${action.toLowerCase()}ed`, updated.chequeNo)
      onUpdated(updated)
      resetActionState()
    } catch (err) {
      toast.error(`Could not ${action.toLowerCase()} cheque`, errorMessage(err))
    } finally {
      setSubmitting(false)
    }
  }

  if (!cheque) return null

  const availableActions: ReceivedChequeStatusAction[] =
    cheque.status === ReceivedChequeStatus.Received
      ? [ReceivedChequeStatusAction.Deposit, ReceivedChequeStatusAction.Cancel]
      : cheque.status === ReceivedChequeStatus.Deposited
        ? [ReceivedChequeStatusAction.Clear, ReceivedChequeStatusAction.Return]
        : []

  return (
    <Dialog open={open} onOpenChange={handleOpenChange}>
      <DialogContent className="max-h-[85vh] overflow-y-auto sm:max-w-lg">
        <DialogHeader>
          <DialogTitle className="flex items-center gap-2 text-lg">
            Cheque {cheque.chequeNo}
            <Badge variant="outline" className={cn("h-6 justify-center border-transparent text-sm", STATUS_BADGE[cheque.status])}>
              {cheque.status}
            </Badge>
          </DialogTitle>
        </DialogHeader>

        {!pendingAction && (
          <div className="flex flex-col gap-4">
            <dl className="grid grid-cols-2 gap-x-4 gap-y-2 text-sm">
              <dt className="text-muted-foreground">Received from</dt>
              <dd>{cheque.receivedFromName}</dd>
              <dt className="text-muted-foreground">Type</dt>
              <dd>{cheque.receivedFromType}</dd>
              <dt className="text-muted-foreground">Cheque date</dt>
              <dd>{formatReportDate(cheque.chequeDate)}</dd>
              <dt className="text-muted-foreground">Amount</dt>
              <dd>{formatAmount(cheque.amount)}</dd>
              <dt className="text-muted-foreground">Received date</dt>
              <dd>{formatReportDate(cheque.receivedDate)}</dd>
              <dt className="text-muted-foreground">Drawer bank</dt>
              <dd>{cheque.drawerBankName ?? "—"}</dd>
              <dt className="text-muted-foreground">Drawer branch</dt>
              <dd>{cheque.drawerBankBranch ?? "—"}</dd>
              <dt className="text-muted-foreground">Account holder</dt>
              <dd>{cheque.accountHolderName ?? "—"}</dd>
              <dt className="text-muted-foreground">Reference</dt>
              <dd>{cheque.referenceType ?? "—"}</dd>
              <dt className="text-muted-foreground">Notes</dt>
              <dd>{cheque.notes ?? "—"}</dd>
              {cheque.status === ReceivedChequeStatus.Deposited && (
                <>
                  <dt className="text-muted-foreground">Deposited to</dt>
                  <dd>#{cheque.depositBankAccountId}</dd>
                  <dt className="text-muted-foreground">Deposit date</dt>
                  <dd>{formatReportDate(cheque.depositDate)}</dd>
                </>
              )}
            </dl>

            {availableActions.length > 0 && (
              <div className="flex flex-wrap gap-2 border-t pt-4">
                {availableActions.map((action) => (
                  <Button key={action} size="sm" variant="outline" onClick={() => setPendingAction(action)}>
                    {action}
                  </Button>
                ))}
              </div>
            )}
          </div>
        )}

        {pendingAction === ReceivedChequeStatusAction.Deposit && (
          <FieldGroup>
            <Field data-invalid={!!errors.depositBankAccountId}>
              <FieldLabel htmlFor="rc-deposit-bank">Deposit bank account</FieldLabel>
              <Select<string> value={depositBankAccountId} onValueChange={(v) => setDepositBankAccountId(v ?? "")}>
                <SelectTrigger id="rc-deposit-bank" className="w-full text-base" aria-invalid={!!errors.depositBankAccountId}>
                  <SelectValue placeholder={bankAccounts === null ? "Loading…" : "Select a bank account"} />
                </SelectTrigger>
                <SelectContent>
                  {(bankAccounts ?? []).map((a) => (
                    <SelectItem key={a.accountId} value={String(a.accountId)} label={a.accountName} className="text-base">
                      {a.accountName}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
              <FieldError errors={[errors.depositBankAccountId ? { message: errors.depositBankAccountId } : undefined]} />
            </Field>
            <Field data-invalid={!!errors.depositDate}>
              <FieldLabel htmlFor="rc-deposit-date">Deposit date</FieldLabel>
              <Input
                id="rc-deposit-date"
                type="date"
                value={depositDate}
                onChange={(e) => setDepositDate(e.target.value)}
                aria-invalid={!!errors.depositDate}
              />
              <FieldError errors={[errors.depositDate ? { message: errors.depositDate } : undefined]} />
            </Field>
            <Field>
              <FieldLabel htmlFor="rc-performed-by">Performed by (optional)</FieldLabel>
              <Input id="rc-performed-by" value={performedBy} onChange={(e) => setPerformedBy(e.target.value)} />
            </Field>
            <Field>
              <FieldLabel htmlFor="rc-notes">Notes (optional)</FieldLabel>
              <Input id="rc-notes" value={notes} onChange={(e) => setNotes(e.target.value)} />
            </Field>
          </FieldGroup>
        )}

        {(pendingAction === ReceivedChequeStatusAction.Clear ||
          pendingAction === ReceivedChequeStatusAction.Return ||
          pendingAction === ReceivedChequeStatusAction.Cancel) && (
          <FieldGroup>
            <Field>
              <FieldLabel htmlFor="rc-performed-by">Performed by (optional)</FieldLabel>
              <Input id="rc-performed-by" value={performedBy} onChange={(e) => setPerformedBy(e.target.value)} />
            </Field>
            <Field>
              <FieldLabel htmlFor="rc-notes">Notes (optional)</FieldLabel>
              <Input id="rc-notes" value={notes} onChange={(e) => setNotes(e.target.value)} />
            </Field>
          </FieldGroup>
        )}

        {pendingAction && (
          <DialogFooter>
            <Button variant="outline" onClick={() => resetActionState()} disabled={submitting}>
              Back
            </Button>
            <Button onClick={() => submitStatusAction(pendingAction)} disabled={submitting}>
              {submitting ? "Submitting…" : pendingAction}
            </Button>
          </DialogFooter>
        )}
      </DialogContent>
    </Dialog>
  )
}
