'use client';

import { useState } from 'react';
import type { ReactNode } from 'react';
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { useQuery, useQueryClient } from '@tanstack/react-query';
import { toast } from 'sonner';

import { Button } from '@/components/ui/button';
import {
  Dialog,
  DialogContent,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from '@/components/ui/dialog';
import { Label } from '@/components/ui/label';
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from '@/components/ui/select';
import { Textarea } from '@/components/ui/textarea';
import { FormErrorSummary } from '@/components/forms/form-error-summary';
import { useFormScrollToError } from '@/hooks/use-form-scroll-to-error';
import { PermissionGate } from '@/components/shared/permission-gate';
import { apiFetch } from '@/lib/api/client';
import { toastError } from '@/lib/api/toast-error';
import { useVocabulary } from '@/hooks/use-vocabulary';
import { updateBerthStatusSchema, type UpdateBerthStatusInput } from '@/lib/validators/berths';
import { BERTH_STATUSES, stageLabel } from '@/lib/constants';
import { cn } from '@/lib/utils';

const STATUS_LABELS: Record<string, string> = {
  available: 'Available',
  under_offer: 'Under Offer',
  sold: 'Sold',
};

interface InterestOption {
  id: string;
  clientName: string;
  pipelineStage: string;
}

/**
 * Click-to-change berth status from the berths LIST. Wraps the status chip
 * (passed as children) in a button that opens a compact change-status dialog
 * — status dropdown + required reason (with quick-pick chips) + an optional
 * interest link when moving to under_offer/sold. Same PATCH endpoint +
 * validator + audit as the berth detail page. Reps without `berths.edit` see
 * a plain, non-interactive chip via the PermissionGate fallback.
 */
export function BerthStatusQuickEdit({
  berthId,
  currentStatus,
  children,
  className,
}: {
  berthId: string;
  currentStatus: string;
  children: ReactNode;
  className?: string;
}) {
  const [open, setOpen] = useState(false);
  return (
    <PermissionGate resource="berths" action="edit" fallback={<>{children}</>}>
      <button
        type="button"
        onClick={(e) => {
          // The chip usually sits inside a clickable list card/row — stop the
          // click from also navigating to the berth detail page.
          e.preventDefault();
          e.stopPropagation();
          setOpen(true);
        }}
        title="Change status"
        aria-label="Change berth status"
        className={cn(
          'cursor-pointer rounded-full outline-none transition-opacity hover:opacity-80 focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1',
          className,
        )}
      >
        {children}
      </button>
      {open && (
        <BerthStatusQuickEditDialog
          berthId={berthId}
          currentStatus={currentStatus}
          open={open}
          onOpenChange={setOpen}
        />
      )}
    </PermissionGate>
  );
}

function BerthStatusQuickEditDialog({
  berthId,
  currentStatus,
  open,
  onOpenChange,
}: {
  berthId: string;
  currentStatus: string;
  open: boolean;
  onOpenChange: (open: boolean) => void;
}) {
  const queryClient = useQueryClient();
  const reasonChips = useVocabulary('berth_status_change_reasons');
  const {
    register,
    handleSubmit,
    setValue,
    watch,
    reset,
    formState: { errors, isSubmitting },
  } = useForm<UpdateBerthStatusInput>({
    resolver: zodResolver(updateBerthStatusSchema),
    defaultValues: { status: currentStatus as (typeof BERTH_STATUSES)[number], reason: '' },
  });
  const submitWithScroll = useFormScrollToError(handleSubmit, errors);

  const status = watch('status');
  const interestId = watch('interestId');
  const showInterestPicker = status === 'under_offer' || status === 'sold';

  // Active interests for the picker — only fetched once the picker is shown.
  const interestsQuery = useQuery<{ data: InterestOption[] }>({
    queryKey: ['interests', 'status-link-picker'],
    queryFn: () => apiFetch('/api/v1/interests?pageSize=200&sort=updatedAt&order=desc'),
    enabled: open && showInterestPicker,
    staleTime: 60_000,
  });
  const interestOptions = interestsQuery.data?.data ?? [];

  async function onSubmit(data: UpdateBerthStatusInput) {
    try {
      await apiFetch(`/api/v1/berths/${berthId}/status`, { method: 'PATCH', body: data });
      queryClient.invalidateQueries({ queryKey: ['berths'] });
      queryClient.invalidateQueries({ queryKey: ['berth', berthId] });
      queryClient.invalidateQueries({ queryKey: ['interests'] });
      toast.success('Status updated');
      reset();
      onOpenChange(false);
    } catch (err) {
      toastError(err);
    }
  }

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className="sm:max-w-md">
        <DialogHeader>
          <DialogTitle>Change status</DialogTitle>
        </DialogHeader>
        <form onSubmit={submitWithScroll(onSubmit)} className="space-y-4">
          <FormErrorSummary
            errors={errors}
            labels={{ status: 'Status', reason: 'Reason', interestId: 'Linked interest' }}
          />
          <div className="space-y-2">
            <Label>New status</Label>
            <Select
              value={status}
              onValueChange={(v) => {
                setValue('status', v as (typeof BERTH_STATUSES)[number]);
                // Clear any stale interest pick when returning to available.
                if (v === 'available') setValue('interestId', undefined);
              }}
            >
              <SelectTrigger>
                <SelectValue />
              </SelectTrigger>
              <SelectContent>
                {BERTH_STATUSES.map((s) => (
                  <SelectItem key={s} value={s}>
                    {STATUS_LABELS[s] ?? s}
                  </SelectItem>
                ))}
              </SelectContent>
            </Select>
          </div>
          <div className="space-y-2">
            <Label>Reason *</Label>
            {reasonChips.length > 0 && (
              <div className="flex flex-wrap gap-1.5">
                {reasonChips.map((chip) => (
                  <button
                    type="button"
                    key={chip}
                    onClick={() => setValue('reason', chip, { shouldDirty: true })}
                    className="rounded-full border border-muted-foreground/20 bg-muted px-2.5 py-0.5 text-xs hover:bg-accent"
                  >
                    {chip}
                  </button>
                ))}
              </div>
            )}
            <Textarea {...register('reason')} placeholder="Reason for status change…" rows={3} />
          </div>
          {showInterestPicker && (
            <div className="space-y-2">
              <Label>Linked interest (optional)</Label>
              <Select
                value={interestId ?? '__none__'}
                onValueChange={(v) => setValue('interestId', v === '__none__' ? undefined : v)}
              >
                <SelectTrigger>
                  <SelectValue placeholder="No interest" />
                </SelectTrigger>
                <SelectContent>
                  <SelectItem value="__none__">No interest</SelectItem>
                  {interestOptions.map((o) => (
                    <SelectItem key={o.id} value={o.id}>
                      {`${o.clientName || '(unnamed)'} · ${stageLabel(o.pipelineStage)}`}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
              <p className="text-xs text-muted-foreground">
                Links this change to the interest it relates to — it shows on that interest&apos;s
                timeline and the berth attaches to it automatically.
              </p>
            </div>
          )}
          <DialogFooter>
            <Button type="button" variant="outline" onClick={() => onOpenChange(false)}>
              Cancel
            </Button>
            <Button type="submit" disabled={isSubmitting}>
              {isSubmitting ? 'Saving…' : 'Update status'}
            </Button>
          </DialogFooter>
        </form>
      </DialogContent>
    </Dialog>
  );
}
