import * as api from "@client/api";
import type { Job } from "@shared/types.js";
import { StickyNote } from "lucide-react";
import type React from "react";
import { useCallback, useEffect, useRef, useState } from "react";
import { toast } from "sonner";
import { Textarea } from "@/components/ui/textarea";
import { cn } from "@/lib/utils";

interface JobNotesProps {
  job: Job;
  onJobUpdated: () => void | Promise<void>;
  className?: string;
}

const DEBOUNCE_MS = 800;

export const JobNotes: React.FC<JobNotesProps> = ({
  job,
  onJobUpdated,
  className,
}) => {
  const [value, setValue] = useState(job.notes ?? "");
  const [isSaving, setIsSaving] = useState(false);
  const pendingRef = useRef<string | null>(null);
  const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
  const jobIdRef = useRef(job.id);

  useEffect(() => {
    if (jobIdRef.current !== job.id) {
      jobIdRef.current = job.id;
      if (timerRef.current) clearTimeout(timerRef.current);
      pendingRef.current = null;
    }
    setValue(job.notes ?? "");
  }, [job.id, job.notes]);

  const persist = useCallback(
    async (text: string) => {
      try {
        setIsSaving(true);
        await api.updateJob(job.id, { notes: text || null });
        await onJobUpdated();
      } catch (error) {
        const msg =
          error instanceof Error ? error.message : "Failed to save notes";
        toast.error(msg);
      } finally {
        setIsSaving(false);
        if (pendingRef.current !== null) {
          const next = pendingRef.current;
          pendingRef.current = null;
          void persist(next);
        }
      }
    },
    [job.id, onJobUpdated],
  );

  const scheduleFlush = useCallback(
    (text: string) => {
      if (timerRef.current) clearTimeout(timerRef.current);
      timerRef.current = setTimeout(() => {
        if (isSaving) {
          pendingRef.current = text;
        } else {
          void persist(text);
        }
      }, DEBOUNCE_MS);
    },
    [isSaving, persist],
  );

  const handleChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
    const next = e.target.value;
    setValue(next);
    scheduleFlush(next);
  };

  const handleBlur = () => {
    if (timerRef.current) clearTimeout(timerRef.current);
    const trimmed = value;
    if (trimmed !== (job.notes ?? "")) {
      if (isSaving) {
        pendingRef.current = trimmed;
      } else {
        void persist(trimmed);
      }
    }
  };

  return (
    <div className={cn("space-y-1.5", className)}>
      <div className="flex items-center gap-1.5">
        <StickyNote className="h-3.5 w-3.5 text-muted-foreground/70" />
        <span className="text-[11px] font-medium text-muted-foreground/70 uppercase tracking-wide">
          Notes
        </span>
        {isSaving && (
          <span className="text-[10px] text-muted-foreground/50 ml-auto">
            Saving…
          </span>
        )}
      </div>
      <Textarea
        value={value}
        onChange={handleChange}
        onBlur={handleBlur}
        placeholder="Add notes about this listing…"
        className="min-h-[72px] resize-y text-xs leading-relaxed bg-muted/5 border-border/40 placeholder:text-muted-foreground/40 focus-visible:ring-1"
      />
    </div>
  );
};
