'use client';

import { useState, useMemo } from 'react';
import { useQuery } from '@tanstack/react-query';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Textarea } from '@/components/ui/textarea';
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from '@/components/ui/select';
import { Sheet, SheetContent, SheetHeader, SheetTitle, SheetFooter } from '@/components/ui/sheet';
import { ClientPicker } from '@/components/shared/client-picker';
import { InterestPicker } from '@/components/shared/interest-picker';
import { BerthPicker } from '@/components/shared/berth-picker';
import { apiFetch } from '@/lib/api/client';
import { usePermissions } from '@/hooks/use-permissions';

interface UserOption {
  id: string;
  displayName: string;
}

interface ReminderFormProps {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  reminder?: {
    id: string;
    title: string;
    note: string | null;
    dueAt: string;
    priority: string;
    assignedTo: string | null;
    clientId: string | null;
    interestId: string | null;
    berthId: string | null;
  } | null;
  // Pre-fill entity link when creating from entity detail pages
  defaultClientId?: string;
  defaultInterestId?: string;
  defaultBerthId?: string;
  onSuccess: () => void;
}

export function ReminderForm(props: ReminderFormProps) {
  // Key-based remount: the body is keyed on `open + reminder.id` so its
  // useState initializers re-run on each open with the correct seed.
  // Replaces the prior useEffect-driven open→reset that the Compiler
  // flagged as set-state-in-effect.
  return (
    <ReminderFormBody
      key={props.open ? `open:${props.reminder?.id ?? 'new'}` : 'closed'}
      {...props}
    />
  );
}

function ReminderFormBody({
  open,
  onOpenChange,
  reminder,
  defaultClientId,
  defaultInterestId,
  defaultBerthId,
  onSuccess,
}: ReminderFormProps) {
  const isEdit = !!reminder;
  // Tomorrow 9am default for new-reminder dueAt.
  const defaultDueAt = useMemo(() => {
    const t = new Date();
    t.setDate(t.getDate() + 1);
    t.setHours(9, 0, 0, 0);
    return t.toISOString().slice(0, 16);
  }, []);
  const [title, setTitle] = useState(reminder?.title ?? '');
  const [note, setNote] = useState(reminder?.note ?? '');
  const [dueAt, setDueAt] = useState(reminder ? reminder.dueAt.slice(0, 16) : defaultDueAt);
  const [priority, setPriority] = useState(reminder?.priority ?? 'medium');
  const [assignedTo, setAssignedTo] = useState(reminder?.assignedTo ?? '');
  const [clientId, setClientId] = useState(reminder?.clientId ?? defaultClientId ?? '');
  const [interestId, setInterestId] = useState(reminder?.interestId ?? defaultInterestId ?? '');
  const [berthId, setBerthId] = useState(reminder?.berthId ?? defaultBerthId ?? '');
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const { can } = usePermissions();
  const canAssignOthers = can('reminders', 'assign_others');
  // useQuery replaces the prior useEffect(fetch+setState) pattern.
  const usersQuery = useQuery<{ data: UserOption[] }>({
    queryKey: ['admin', 'users', 'options'],
    queryFn: () => apiFetch('/api/v1/admin/users/options'),
    enabled: open && canAssignOthers,
  });
  const users = usersQuery.data?.data ?? [];

  async function handleSubmit(e: React.FormEvent) {
    e.preventDefault();
    setError(null);
    setLoading(true);

    try {
      const body = {
        title,
        note: note || undefined,
        dueAt: new Date(dueAt).toISOString(),
        priority,
        assignedTo: assignedTo || undefined,
        clientId: clientId || undefined,
        interestId: interestId || undefined,
        berthId: berthId || undefined,
      };

      if (isEdit) {
        await apiFetch(`/api/v1/reminders/${reminder.id}`, {
          method: 'PATCH',
          body,
        });
      } else {
        await apiFetch('/api/v1/reminders', {
          method: 'POST',
          body,
        });
      }
      onSuccess();
      onOpenChange(false);
    } catch (err: unknown) {
      const message = err instanceof Error ? err.message : 'Something went wrong';
      setError(message);
    } finally {
      setLoading(false);
    }
  }

  return (
    <Sheet open={open} onOpenChange={onOpenChange}>
      <SheetContent className="overflow-y-auto">
        <SheetHeader>
          <SheetTitle>{isEdit ? 'Edit Reminder' : 'New Reminder'}</SheetTitle>
        </SheetHeader>

        <form onSubmit={handleSubmit} className="mt-6 space-y-4">
          <div className="space-y-2">
            <Label htmlFor="reminder-title">Title</Label>
            <Input
              id="reminder-title"
              value={title}
              onChange={(e) => setTitle(e.target.value)}
              placeholder="Follow up with client..."
              required
            />
          </div>

          <div className="space-y-2">
            <Label htmlFor="reminder-note">Note</Label>
            <Textarea
              id="reminder-note"
              value={note}
              onChange={(e) => setNote(e.target.value)}
              placeholder="Additional details..."
              rows={3}
            />
          </div>

          {/* 2fr/1fr split — the datetime-local control needs more room
              for "MM/DD/YYYY HH:MM AM" than a 4-item priority Select. */}
          <div className="grid grid-cols-[2fr_1fr] gap-4">
            <div className="space-y-2">
              <Label htmlFor="reminder-due">Due Date & Time</Label>
              <Input
                id="reminder-due"
                type="datetime-local"
                value={dueAt}
                onChange={(e) => setDueAt(e.target.value)}
                required
              />
            </div>

            <div className="space-y-2">
              <Label htmlFor="reminder-priority">Priority</Label>
              <Select value={priority} onValueChange={setPriority}>
                <SelectTrigger id="reminder-priority">
                  <SelectValue />
                </SelectTrigger>
                <SelectContent>
                  <SelectItem value="low">Low</SelectItem>
                  <SelectItem value="medium">Medium</SelectItem>
                  <SelectItem value="high">High</SelectItem>
                  <SelectItem value="urgent">Urgent</SelectItem>
                </SelectContent>
              </Select>
            </div>
          </div>

          {canAssignOthers && (
            <div className="space-y-2">
              <Label htmlFor="reminder-assign">Assign to user</Label>
              <Select
                value={assignedTo === '' ? '__self__' : assignedTo}
                onValueChange={(v) => setAssignedTo(v === '__self__' ? '' : v)}
              >
                <SelectTrigger id="reminder-assign">
                  <SelectValue placeholder="Myself" />
                </SelectTrigger>
                <SelectContent>
                  {/* Radix Select forbids empty-string values, so use a
                      sentinel here and map back to '' in the handler. */}
                  <SelectItem value="__self__">Myself</SelectItem>
                  {users.map((u) => (
                    <SelectItem key={u.id} value={u.id}>
                      {u.displayName}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </div>
          )}

          <div className="space-y-2">
            <Label className="text-xs text-muted-foreground">Link to entity (optional)</Label>
            <p className="text-[11px] text-muted-foreground">
              Pick a client first to scope the interest and berth dropdowns to that client&apos;s
              deals.
            </p>
            <div className="grid grid-cols-1 gap-2">
              <ClientPicker
                value={clientId || null}
                onChange={(id) => {
                  setClientId(id ?? '');
                  // Clearing the client also clears scoped selections so a
                  // stale interest/berth from a different client doesn't
                  // silently submit alongside the new client.
                  if (!id) {
                    setInterestId('');
                    setBerthId('');
                  }
                }}
              />
              <InterestPicker
                value={interestId || null}
                onChange={(id) => setInterestId(id ?? '')}
                clientId={clientId || null}
              />
              <BerthPicker
                value={berthId || null}
                onChange={(id) => setBerthId(id ?? '')}
                clientId={clientId || null}
              />
            </div>
          </div>

          {error && <p className="text-sm text-destructive">{error}</p>}

          <SheetFooter>
            <Button
              type="button"
              variant="outline"
              onClick={() => onOpenChange(false)}
              disabled={loading}
            >
              Cancel
            </Button>
            <Button type="submit" disabled={loading || !title.trim() || !dueAt}>
              {loading ? 'Saving...' : isEdit ? 'Save Changes' : 'Create Reminder'}
            </Button>
          </SheetFooter>
        </form>
      </SheetContent>
    </Sheet>
  );
}
