"use client";

import * as React from "react";
import { ShieldCheck, Save, Loader2 } from "lucide-react";
import { useForm } from "react-hook-form";
import { yupResolver } from "@hookform/resolvers/yup";
import * as yup from "yup";
import { toast } from "sonner";
import { useQueryClient } from "@tanstack/react-query";
import { Button } from "@/components/ui/button";
import { useUpdateDealBantMutation } from "@/api/rtk/deals-api";
import { invalidateLeadsBoardColumnsTouchingStages } from "@/features/leads/api/invalidate-leads-board-columns";
import { BantQualificationGrid } from "./bant-qualification-grid";
import { Deal } from "./types";
import { cn } from "@/lib/utils";

const bantSchema = yup.object().shape({
  bantBudgetId: yup.string(),
  bantAuthorityId: yup.string(),
  bantNeedId: yup.string(),
  bantTimelineId: yup.string(),
  bantScoreId: yup.string(),
});

interface DealBantSidebarProps {
  deal: Deal;
  className?: string;
}

/**
 * Persistent BANT panel on lead detail. Edits batch behind an explicit Save so reps can
 * tune multiple dimensions before one PATCH `/deals/:id/bant`.
 */
export function DealBantSidebar({ deal, className }: DealBantSidebarProps) {
  const queryClient = useQueryClient();
  const [updateDealBant, { isLoading: isSaving }] = useUpdateDealBantMutation();

  const {
    handleSubmit,
    setValue,
    watch,
    formState: { isDirty },
  } = useForm({
    resolver: yupResolver(bantSchema),
    // `values` keeps the form aligned when `deal` refetches or the user opens another lead.
    values: {
      bantBudgetId: deal.bantBudgetId || "",
      bantAuthorityId: deal.bantAuthorityId || "",
      bantNeedId: deal.bantNeedId || "",
      bantTimelineId: deal.bantTimelineId || "",
      bantScoreId: deal.bantScoreId || "",
    },
  });

  const handleUpdateBant = async (updates: Record<string, string | undefined>) => {
    try {
      await updateDealBant({ id: deal.id, body: updates }).unwrap();
      // Kanban column caches are keyed by stage; refresh this lead's column after PATCH.
      invalidateLeadsBoardColumnsTouchingStages(
        queryClient,
        [deal.stage].filter(Boolean) as string[],
      );
      toast.success("BANT updated");
    } catch {
      toast.error("Failed to update BANT");
    }
  };

  return (
    <aside
      className={cn(
        "flex h-full min-h-0 flex-col overflow-hidden rounded-2xl border border-gray-100 bg-white/60 backdrop-blur-sm shadow-sm",
        className,
      )}
    >
      <div className="flex shrink-0 flex-col gap-4 border-b border-gray-100 p-4 sm:p-5">
        <div className="min-w-0 text-left">
          <h3 className="flex items-center gap-2 text-base font-bold tracking-tight text-gray-900 font-['Lexend']">
            <ShieldCheck className="shrink-0 text-[#6C63FF]" size={18} />
            Lead Qualification
          </h3>
          <p className="mt-1 text-xs font-medium text-gray-500">
            BANT framework — always visible while you work this lead
          </p>
        </div>
        <Button
          variant="accentFormPrimary"
          size="sm"
          className="w-full sm:w-auto sm:self-end"
          onClick={handleSubmit(handleUpdateBant)}
          disabled={!isDirty || isSaving}
        >
          {isSaving ? <Loader2 className="size-4 animate-spin" /> : <Save size={16} />}
          {isSaving ? "Saving..." : "Save Qualification"}
        </Button>
      </div>

      <div className="min-h-0 flex-1 overflow-y-auto p-4 sm:p-5">
        <BantQualificationGrid
          columns={1}
          value={watch()}
          onChange={(f, v) =>
            // Grid reports dynamic field keys; narrow for react-hook-form's typed setValue.
            setValue(f as Parameters<typeof setValue>[0], v, { shouldDirty: true })
          }
        />
      </div>
    </aside>
  );
}
