"use client"

import * as React from "react"
import { Ban, Loader2 } from "lucide-react"
import { useQueryClient } from "@tanstack/react-query"
import { useAppDispatch, useAppSelector } from "@/store/hooks"
import {
  closeMoveToLostDialog,
  selectMoveToLostDialog,
} from "@/store/slices/move-to-lost-dialog-slice"
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog"
import { Button } from "@/components/ui/button"
import { Textarea } from "@/components/ui/textarea"
import { ReactSelect } from "@/components/ui/react-select"
import { useGetPipelinesQuery } from "@/api/rtk/pipelines-api"
import { useMoveDealMutation } from "@/api/rtk/deals-api"
import { useGetClosedLeadTagsQuery } from "@/api/rtk/deal-meta-api"
import { useMoveLeadMutation } from "@/features/leads/hooks/use-move-lead-mutation"
import { listLostLeadStages } from "@/lib/deal-stage-labels"
import type { Stage } from "@/components/deals/types"
import { toast } from "sonner"
import { markLocalDealBoardMove, clearLocalDealBoardMoveEcho } from "@/lib/deal-board-socket-coalesce"
import { invalidateLeadsBoardColumnsTouchingStages } from "@/features/leads/api/invalidate-leads-board-columns"
import { leadsKeys } from "@/features/leads/api/query-keys"
import {
  applyOptimisticLeadBoardMoveWithCounts,
  revertOptimisticLeadBoardMoveWithCounts,
} from "@/features/leads/api/optimistic-board-column-move"
import { baseApi } from "@/api/rtk/base-api"
import {
  countTrimmedWordsForLostReason,
  MIN_LOST_REASON_WORD_COUNT,
} from "@/lib/move-to-lost-reason"

function FieldLabel({ children }: { children: React.ReactNode }) {
  return (
    <label className="mb-1.5 block select-none font-['Lexend_Deca'] text-[10px] font-medium uppercase tracking-[0.09em] text-gray-400">
      {children}
    </label>
  )
}

export function MoveToLostDialog() {
  const dispatch = useAppDispatch()
  const queryClient = useQueryClient()
  const dlg = useAppSelector(selectMoveToLostDialog)
  const { data: pipelines } = useGetPipelinesQuery(undefined, {
    skip: !dlg.open || !dlg.pipelineId,
  })
  const [moveDealMutation, { isLoading: isMovingDeal }] = useMoveDealMutation()
  const { mutateAsync: moveLeadTs, isPending: isMovingLeadTs } =
    useMoveLeadMutation()

  const [selectedLostStageId, setSelectedLostStageId] = React.useState("")
  const [reason, setReason] = React.useState("")
  const [selectedClosedLeadTagId, setSelectedClosedLeadTagId] = React.useState("")
  const { data: closedLeadTagCatalog = [] } = useGetClosedLeadTagsQuery(undefined, {
    skip: !dlg.open,
  })

  const stages = React.useMemo(() => {
    if (!dlg.pipelineId || !pipelines?.length) return [] as Stage[]
    const p = pipelines.find((x) => x.id === dlg.pipelineId)
    return (p?.stages ?? []) as unknown as Stage[]
  }, [dlg.pipelineId, pipelines])

  const lostLeadStages = React.useMemo(
    () => listLostLeadStages(stages),
    [stages],
  )

  const reasonWordCount = React.useMemo(
    () => countTrimmedWordsForLostReason(reason),
    [reason],
  )

  React.useEffect(() => {
    if (!dlg.open) {
      setReason("")
      setSelectedLostStageId("")
      setSelectedClosedLeadTagId("")
      return
    }
    const defaultTag =
      closedLeadTagCatalog.find((t) => t.isDefaultForClosedLost) ??
      (closedLeadTagCatalog.length === 1 ? closedLeadTagCatalog[0] : undefined)
    if (defaultTag) setSelectedClosedLeadTagId(defaultTag.id)
    if (dlg.targetStageId && lostLeadStages.some((s) => s.id === dlg.targetStageId)) {
      setSelectedLostStageId(dlg.targetStageId)
      return
    }
    if (lostLeadStages.length === 1) {
      setSelectedLostStageId(lostLeadStages[0].id)
    }
  }, [dlg.open, dlg.targetStageId, lostLeadStages, closedLeadTagCatalog])

  const closedLeadTagsConfigured = closedLeadTagCatalog.length > 0

  const lostStageOptions = React.useMemo(
    () =>
      lostLeadStages.map((s) => ({
        value: s.id,
        label: (
          <>
            {s.name}
            {s.isSubStage && s.parentStageName
              ? ` (${s.parentStageName})`
              : null}
          </>
        ),
      })),
    [lostLeadStages],
  )

  const closedLeadTagOptions = React.useMemo(
    () =>
      closedLeadTagCatalog.map((t) => ({
        value: t.id,
        label: `${t.name}${t.isDefaultForClosedLost ? " (default)" : ""}`,
      })),
    [closedLeadTagCatalog],
  )

  const handleClose = () => {
    dispatch(closeMoveToLostDialog())
  }

  const handleConfirm = async () => {
    if (!dlg.dealId || !dlg.pipelineId || !dlg.moveContext) return
    const target = lostLeadStages.find((s) => s.id === selectedLostStageId)
    if (!target) {
      toast.error("Select a Closed Lost stage")
      return
    }
    const trimmed = reason.trim()
    const words = countTrimmedWordsForLostReason(reason)
    if (words < MIN_LOST_REASON_WORD_COUNT) {
      toast.error(`Reason must be at least ${MIN_LOST_REASON_WORD_COUNT} words`)
      return
    }

    const prob =
      typeof target.prob === "number" ? target.prob : dlg.targetProb ?? 0

    const fromStage = dlg.sourceStageId ?? ""
    let optimisticSnapshot: ReturnType<
      typeof applyOptimisticLeadBoardMoveWithCounts
    > = null

    try {
      if (dlg.moveContext.kind === "paged") {
        optimisticSnapshot = applyOptimisticLeadBoardMoveWithCounts(
          queryClient,
          {
            dealId: dlg.dealId,
            fromStage,
            toStage: target.id,
            listParams: dlg.moveContext.listParams,
          },
        )
        await moveLeadTs({
          id: dlg.dealId,
          stageId: target.id,
          prob,
          reason: trimmed,
          closedLeadTagId: selectedClosedLeadTagId || undefined,
        })
      } else if (dlg.moveContext.kind === "infinite") {
        await moveDealMutation({
          id: dlg.dealId,
          stageId: target.id,
          prob,
          reason: trimmed,
          closedLeadTagId: selectedClosedLeadTagId || undefined,
          ...dlg.moveContext.listArgs,
        }).unwrap()
      } else {
        await moveDealMutation({
          id: dlg.dealId,
          stageId: target.id,
          prob,
          reason: trimmed,
          closedLeadTagId: selectedClosedLeadTagId || undefined,
          pipelineId: dlg.pipelineId ?? undefined,
        }).unwrap()
      }

      const from = dlg.sourceStageId ?? undefined
      markLocalDealBoardMove(dlg.dealId, from, target.id)
      if (dlg.moveContext.kind === "paged") {
        void queryClient.invalidateQueries({
          queryKey: leadsKeys.boardCounts(dlg.moveContext.listParams),
        })
      } else {
        invalidateLeadsBoardColumnsTouchingStages(queryClient, [
          from,
          target.id,
        ].filter(Boolean) as string[])
      }

      dispatch(
        baseApi.util.invalidateTags([
          { type: "Deals", id: dlg.dealId },
          { type: "Deals", id: "LIST" },
        ]),
      )

      toast.success(`Lead moved to ${target.name}`)
      handleClose()
    } catch (err: unknown) {
      clearLocalDealBoardMoveEcho()
      if (
        optimisticSnapshot &&
        dlg.moveContext?.kind === "paged"
      ) {
        revertOptimisticLeadBoardMoveWithCounts(
          queryClient,
          optimisticSnapshot,
          dlg.moveContext.listParams,
        )
      }
      const msg =
        err && typeof err === "object" && "data" in err
          ? (() => {
              const d = (err as { data?: { message?: unknown } }).data?.message
              return typeof d === "string"
                ? d
                : Array.isArray(d) && typeof d[0] === "string"
                  ? d[0]
                  : ""
            })()
          : err instanceof Error
            ? err.message
            : ""
      toast.error(msg.trim() || "Failed to move lead to lost")
    }
  }

  const busy = isMovingDeal || isMovingLeadTs
  const titleName = dlg.customerName?.trim() || "this lead"

  return (
    <Dialog
      open={dlg.open}
      onOpenChange={(open) => {
        if (!open) handleClose()
      }}
    >
      <DialogContent className="sm:max-w-md">
        <DialogHeader>
          <DialogTitle>Move lead to Closed Lost</DialogTitle>
          <DialogDescription>
            {titleName}: choose the lost column and enter a reason. Minimum{" "}
            <span className="font-semibold text-gray-700">
              {MIN_LOST_REASON_WORD_COUNT}
            </span>{" "}
            words (after trimming leading and trailing spaces).
          </DialogDescription>
        </DialogHeader>
        <div className="grid gap-4 py-2">
          <div>
            <FieldLabel>Closed Lost stage</FieldLabel>
            <ReactSelect
              value={selectedLostStageId || ""}
              onValueChange={setSelectedLostStageId}
              options={lostStageOptions}
              placeholder="Select a stage"
              disabled={lostLeadStages.length === 0}
              triggerClassName="min-h-10 w-full rounded-xl border-gray-200"
            />
          </div>
          <div>
            <FieldLabel>Reason</FieldLabel>
            <Textarea
              value={reason}
              onChange={(e) => setReason(e.target.value)}
              placeholder="Why is this lead being marked lost?"
              className="min-h-[100px] rounded-xl border-gray-200"
              rows={4}
              aria-describedby="move-to-lost-reason-stats"
            />
            <div
              id="move-to-lost-reason-stats"
              className="mt-1.5 flex flex-col gap-0.5 text-[11px] text-gray-500 sm:flex-row sm:flex-wrap sm:items-baseline sm:justify-between sm:gap-x-4 sm:gap-y-0.5"
              aria-live="polite"
            >
              <span className="text-gray-600">
                <span className="font-semibold tabular-nums text-gray-800">
                  {reasonWordCount}
                </span>
                {" / "}
                <span className="font-semibold tabular-nums text-gray-800">
                  {MIN_LOST_REASON_WORD_COUNT}
                </span>{" "}
                words minimum
              </span>
              <span
                className={
                  reasonWordCount < MIN_LOST_REASON_WORD_COUNT
                    ? "font-medium text-amber-700"
                    : "font-medium text-emerald-700"
                }
              >
                {reasonWordCount < MIN_LOST_REASON_WORD_COUNT
                  ? `${MIN_LOST_REASON_WORD_COUNT - reasonWordCount} more word${MIN_LOST_REASON_WORD_COUNT - reasonWordCount === 1 ? "" : "s"} needed`
                  : "Requirement met"}
              </span>
            </div>
          </div>
          <div>
            <FieldLabel>Closed lead tag</FieldLabel>
            {closedLeadTagsConfigured ? (
              <ReactSelect
                value={selectedClosedLeadTagId || ""}
                onValueChange={setSelectedClosedLeadTagId}
                options={closedLeadTagOptions}
                placeholder="Select a tag"
                triggerClassName="min-h-10 w-full rounded-xl border-gray-200"
              />
            ) : (
              <p className="text-[12px] text-amber-700 bg-amber-50 border border-amber-100 rounded-xl px-3 py-2">
                No closed lead tags configured — ask an admin (Extra Content).
              </p>
            )}
          </div>
        </div>
        <DialogFooter className="mt-2 gap-3 sm:gap-3">
          <Button
            type="button"
            variant="outline"
            onClick={handleClose}
            disabled={busy}
          >
            Cancel
          </Button>
          <Button
            type="button"
            variant="destructive"
            onClick={() => void handleConfirm()}
            disabled={
              busy ||
              !selectedLostStageId ||
              reasonWordCount < MIN_LOST_REASON_WORD_COUNT ||
              !selectedClosedLeadTagId ||
              !closedLeadTagsConfigured
            }
          >
            {busy ? (
              <Loader2 className="mr-2 h-4 w-4 animate-spin" />
            ) : (
              <Ban className="mr-2 h-4 w-4" />
            )}
            Confirm move
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  )
}
