"use client"

import { useState } from "react"

import { chequePagesApi } from "@/lib/api/general-ledger"
import { errorMessage } from "@/lib/error-map"
import { formatAmount, formatReportDate } from "@/lib/format"
import { validateIssueChequeForm } from "@/lib/validations/general-ledger"
import { cn } from "@/lib/utils"
import { ChequePage, ChequePageIssueStatus, ChequePageStatusAction, PayeeType } from "@/types/general-ledger"

import { Badge } from "@/components/ui/badge"
import { Button } from "@/components/ui/button"
import { Checkbox } from "@/components/ui/checkbox"
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<ChequePageIssueStatus, string> = {
  [ChequePageIssueStatus.Unused]: "bg-muted text-muted-foreground",
  [ChequePageIssueStatus.Issued]: "bg-primary/10 text-primary",
  [ChequePageIssueStatus.Cleared]: "bg-success/10 text-success",
  [ChequePageIssueStatus.Bounced]: "bg-destructive/10 text-destructive",
  [ChequePageIssueStatus.Cancelled]: "bg-destructive/10 text-destructive",
  [ChequePageIssueStatus.Void]: "bg-muted text-muted-foreground",
}

type PendingAction = "Issue" | ChequePageStatusAction | null

interface ChequePageDialogProps {
  page: ChequePage | null
  open: boolean
  onOpenChange: (open: boolean) => void
  /** Called with the server's response after a successful issue/status-update, so the caller's list stays in sync. */
  onUpdated: (updated: ChequePage) => void
}

/** View a single cheque page's details, and (from `Unused`/`Issued`) issue it or move it through
 * Clear/Bounce/Cancel/Void — a modal rather than a separate page, so acting on several leaves from
 * a book's page list doesn't lose scroll position/context each time (docs/21 §7). */
export function ChequePageDialog({ page, open, onOpenChange, onUpdated }: ChequePageDialogProps) {
  const [pendingAction, setPendingAction] = useState<PendingAction>(null)
  const [submitting, setSubmitting] = useState(false)
  const [errors, setErrors] = useState<Record<string, string>>({})

  const [payeeType, setPayeeType] = useState<PayeeType>(PayeeType.Supplier)
  const [payeeName, setPayeeName] = useState("")
  const [payeeId, setPayeeId] = useState("")
  const [issueDate, setIssueDate] = useState("")
  const [amount, setAmount] = useState("")
  const [currencyCode, setCurrencyCode] = useState("LKR")
  const [voucherId, setVoucherId] = useState("")
  const [referenceNo, setReferenceNo] = useState("")
  const [purpose, setPurpose] = useState("")
  const [isCrossCheque, setIsCrossCheque] = useState(false)
  const [isAccountPayee, setIsAccountPayee] = useState(false)
  const [isPostDated, setIsPostDated] = useState(false)
  const [notes, setNotes] = useState("")
  const [printedBy, setPrintedBy] = useState("")

  const [clearedDate, setClearedDate] = useState("")
  const [cancelReason, setCancelReason] = useState("")
  const [performedBy, setPerformedBy] = useState("")

  function resetActionState() {
    setPendingAction(null)
    setErrors({})
    setPayeeType(PayeeType.Supplier)
    setPayeeName("")
    setPayeeId("")
    setIssueDate("")
    setAmount("")
    setCurrencyCode("LKR")
    setVoucherId("")
    setReferenceNo("")
    setPurpose("")
    setIsCrossCheque(false)
    setIsAccountPayee(false)
    setIsPostDated(false)
    setNotes("")
    setPrintedBy("")
    setClearedDate("")
    setCancelReason("")
    setPerformedBy("")
  }

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

  async function submitIssue() {
    if (!page) return
    const nextErrors = validateIssueChequeForm({ payeeName, issueDate, amount })
    setErrors(nextErrors)
    if (Object.keys(nextErrors).length > 0) return
    setSubmitting(true)
    try {
      const updated = await chequePagesApi.issue(page.chequeNo, {
        payeeType,
        payeeId: payeeId ? Number(payeeId) : undefined,
        payeeName,
        issueDate,
        amount: Number(amount),
        currencyCode: currencyCode || undefined,
        voucherId: voucherId ? Number(voucherId) : undefined,
        referenceNo: referenceNo || undefined,
        purpose: purpose || undefined,
        isCrossCheque,
        isAccountPayee,
        isPostDated,
        notes: notes || undefined,
        printedBy: printedBy || undefined,
      })
      toast.success("Cheque issued", `${updated.chequeNo} → ${updated.payeeName}`)
      onUpdated(updated)
      resetActionState()
    } catch (err) {
      toast.error("Could not issue cheque", errorMessage(err))
    } finally {
      setSubmitting(false)
    }
  }

  async function submitStatusAction(action: ChequePageStatusAction) {
    if (!page) return
    if (action === ChequePageStatusAction.Clear && !clearedDate) {
      setErrors({ clearedDate: "Cleared date is required" })
      return
    }
    if (action === ChequePageStatusAction.Cancel && !cancelReason.trim()) {
      setErrors({ cancelReason: "Cancel reason is required" })
      return
    }
    setSubmitting(true)
    try {
      const updated = await chequePagesApi.updateStatus(page.chequeNo, {
        action,
        clearedDate: action === ChequePageStatusAction.Clear ? clearedDate : undefined,
        cancelReason: action === ChequePageStatusAction.Cancel ? cancelReason : undefined,
        performedBy: performedBy || undefined,
      })
      toast.success(`Cheque ${action.toLowerCase()}d`, updated.chequeNo)
      onUpdated(updated)
      resetActionState()
    } catch (err) {
      toast.error(`Could not ${action.toLowerCase()} cheque`, errorMessage(err))
    } finally {
      setSubmitting(false)
    }
  }

  if (!page) return null

  const availableActions: ChequePageStatusAction[] =
    page.issueStatus === ChequePageIssueStatus.Unused
      ? [ChequePageStatusAction.Cancel, ChequePageStatusAction.Void]
      : page.issueStatus === ChequePageIssueStatus.Issued
        ? [ChequePageStatusAction.Clear, ChequePageStatusAction.Bounce, ChequePageStatusAction.Cancel]
        : []

  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 {page.chequeNo}
            <Badge variant="outline" className={cn("h-6 justify-center border-transparent text-sm", STATUS_BADGE[page.issueStatus])}>
              {page.issueStatus}
            </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">Payee</dt>
              <dd>{page.payeeName ?? "—"}</dd>
              <dt className="text-muted-foreground">Payee type</dt>
              <dd>{page.payeeType ?? "—"}</dd>
              <dt className="text-muted-foreground">Issue date</dt>
              <dd>{formatReportDate(page.issueDate)}</dd>
              <dt className="text-muted-foreground">Amount</dt>
              <dd>{page.amount !== null ? formatAmount(page.amount) : "—"}</dd>
              <dt className="text-muted-foreground">Reference no.</dt>
              <dd>{page.referenceNo ?? "—"}</dd>
              <dt className="text-muted-foreground">Purpose</dt>
              <dd>{page.purpose ?? "—"}</dd>
              <dt className="text-muted-foreground">Notes</dt>
              <dd>{page.notes ?? "—"}</dd>
              {page.issueStatus === ChequePageIssueStatus.Cleared && (
                <>
                  <dt className="text-muted-foreground">Cleared date</dt>
                  <dd>{formatReportDate(page.clearedDate)}</dd>
                </>
              )}
              {page.issueStatus === ChequePageIssueStatus.Cancelled && (
                <>
                  <dt className="text-muted-foreground">Cancel reason</dt>
                  <dd>{page.cancelReason ?? "—"}</dd>
                </>
              )}
            </dl>

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

        {pendingAction === "Issue" && (
          <FieldGroup>
            <Field data-invalid={!!errors.payeeName}>
              <FieldLabel htmlFor="cp-payee-name">Payee name</FieldLabel>
              <Input id="cp-payee-name" value={payeeName} onChange={(e) => setPayeeName(e.target.value)} aria-invalid={!!errors.payeeName} />
              <FieldError errors={[errors.payeeName ? { message: errors.payeeName } : undefined]} />
            </Field>

            <Field>
              <FieldLabel htmlFor="cp-payee-type">Payee type</FieldLabel>
              <Select<PayeeType> value={payeeType} onValueChange={(v) => setPayeeType(v ?? PayeeType.Supplier)}>
                <SelectTrigger id="cp-payee-type" className="w-full text-base">
                  <SelectValue />
                </SelectTrigger>
                <SelectContent>
                  {Object.values(PayeeType).map((t) => (
                    <SelectItem key={t} value={t} label={t} className="text-base">
                      {t}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </Field>

            <Field>
              <FieldLabel htmlFor="cp-payee-id">Payee ID (optional)</FieldLabel>
              <Input id="cp-payee-id" type="number" value={payeeId} onChange={(e) => setPayeeId(e.target.value)} />
            </Field>

            <div className="grid grid-cols-2 gap-3">
              <Field data-invalid={!!errors.issueDate}>
                <FieldLabel htmlFor="cp-issue-date">Issue date</FieldLabel>
                <Input
                  id="cp-issue-date"
                  type="date"
                  value={issueDate}
                  onChange={(e) => setIssueDate(e.target.value)}
                  aria-invalid={!!errors.issueDate}
                />
                <FieldError errors={[errors.issueDate ? { message: errors.issueDate } : undefined]} />
              </Field>
              <Field data-invalid={!!errors.amount}>
                <FieldLabel htmlFor="cp-amount">Amount</FieldLabel>
                <Input id="cp-amount" type="number" value={amount} onChange={(e) => setAmount(e.target.value)} aria-invalid={!!errors.amount} />
                <FieldError errors={[errors.amount ? { message: errors.amount } : undefined]} />
              </Field>
            </div>

            <div className="grid grid-cols-2 gap-3">
              <Field>
                <FieldLabel htmlFor="cp-currency">Currency</FieldLabel>
                <Input id="cp-currency" value={currencyCode} onChange={(e) => setCurrencyCode(e.target.value)} maxLength={3} />
              </Field>
              <Field>
                <FieldLabel htmlFor="cp-voucher">Voucher ID (optional)</FieldLabel>
                <Input id="cp-voucher" type="number" value={voucherId} onChange={(e) => setVoucherId(e.target.value)} />
              </Field>
            </div>

            <Field>
              <FieldLabel htmlFor="cp-ref">Reference no. (optional)</FieldLabel>
              <Input id="cp-ref" value={referenceNo} onChange={(e) => setReferenceNo(e.target.value)} />
            </Field>

            <Field>
              <FieldLabel htmlFor="cp-purpose">Purpose (optional)</FieldLabel>
              <Input id="cp-purpose" value={purpose} onChange={(e) => setPurpose(e.target.value)} />
            </Field>

            <div className="flex flex-wrap gap-4">
              <label className="flex items-center gap-2 text-sm">
                <Checkbox checked={isCrossCheque} onCheckedChange={(v) => setIsCrossCheque(v === true)} />
                Cross cheque
              </label>
              <label className="flex items-center gap-2 text-sm">
                <Checkbox checked={isAccountPayee} onCheckedChange={(v) => setIsAccountPayee(v === true)} />
                Account payee
              </label>
              <label className="flex items-center gap-2 text-sm">
                <Checkbox checked={isPostDated} onCheckedChange={(v) => setIsPostDated(v === true)} />
                Post-dated
              </label>
            </div>

            <Field>
              <FieldLabel htmlFor="cp-notes">Notes (optional)</FieldLabel>
              <Input id="cp-notes" value={notes} onChange={(e) => setNotes(e.target.value)} />
            </Field>

            <Field>
              <FieldLabel htmlFor="cp-printed-by">Printed by (optional)</FieldLabel>
              <Input id="cp-printed-by" value={printedBy} onChange={(e) => setPrintedBy(e.target.value)} />
            </Field>
          </FieldGroup>
        )}

        {pendingAction === ChequePageStatusAction.Clear && (
          <FieldGroup>
            <Field data-invalid={!!errors.clearedDate}>
              <FieldLabel htmlFor="cp-cleared-date">Cleared date</FieldLabel>
              <Input
                id="cp-cleared-date"
                type="date"
                value={clearedDate}
                onChange={(e) => setClearedDate(e.target.value)}
                aria-invalid={!!errors.clearedDate}
              />
              <FieldError errors={[errors.clearedDate ? { message: errors.clearedDate } : undefined]} />
            </Field>
            <Field>
              <FieldLabel htmlFor="cp-performed-by">Performed by (optional)</FieldLabel>
              <Input id="cp-performed-by" value={performedBy} onChange={(e) => setPerformedBy(e.target.value)} />
            </Field>
          </FieldGroup>
        )}

        {pendingAction === ChequePageStatusAction.Cancel && (
          <FieldGroup>
            <Field data-invalid={!!errors.cancelReason}>
              <FieldLabel htmlFor="cp-cancel-reason">Cancel reason</FieldLabel>
              <Input
                id="cp-cancel-reason"
                value={cancelReason}
                onChange={(e) => setCancelReason(e.target.value)}
                aria-invalid={!!errors.cancelReason}
              />
              <FieldError errors={[errors.cancelReason ? { message: errors.cancelReason } : undefined]} />
            </Field>
            <Field>
              <FieldLabel htmlFor="cp-performed-by">Performed by (optional)</FieldLabel>
              <Input id="cp-performed-by" value={performedBy} onChange={(e) => setPerformedBy(e.target.value)} />
            </Field>
          </FieldGroup>
        )}

        {(pendingAction === ChequePageStatusAction.Bounce || pendingAction === ChequePageStatusAction.Void) && (
          <FieldGroup>
            <Field>
              <FieldLabel htmlFor="cp-performed-by">Performed by (optional)</FieldLabel>
              <Input id="cp-performed-by" value={performedBy} onChange={(e) => setPerformedBy(e.target.value)} />
            </Field>
          </FieldGroup>
        )}

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