'use client';

import { useMemo, useState } from 'react';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import {
  Bell,
  CalendarDays,
  Mail,
  MessageCircle,
  MoreVertical,
  Phone,
  Pencil,
  Plus,
  Trash2,
  Users,
  Video,
} from 'lucide-react';
import { format, formatDistanceToNowStrict } from 'date-fns';
import { toast } from 'sonner';

import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from '@/components/ui/dialog';
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from '@/components/ui/select';
import { Skeleton } from '@/components/ui/skeleton';
import { Textarea } from '@/components/ui/textarea';
import { apiFetch } from '@/lib/api/client';
import { toastError } from '@/lib/api/toast-error';
import { cn } from '@/lib/utils';

interface InterestContactLogTabProps {
  interestId: string;
}

type Channel = 'email' | 'phone' | 'whatsapp' | 'in_person' | 'video' | 'other';
type Direction = 'outbound' | 'inbound';

interface ContactLogEntry {
  id: string;
  occurredAt: string;
  channel: Channel;
  direction: Direction;
  summary: string;
  followUpAt: string | null;
  reminderId: string | null;
  createdBy: string;
  createdAt: string;
  updatedAt: string;
}

const CHANNEL_META: Record<Channel, { label: string; icon: typeof Phone; tone: string }> = {
  email: { label: 'Email', icon: Mail, tone: 'bg-sky-100 text-sky-700' },
  phone: { label: 'Phone', icon: Phone, tone: 'bg-emerald-100 text-emerald-700' },
  whatsapp: { label: 'WhatsApp', icon: MessageCircle, tone: 'bg-emerald-100 text-emerald-700' },
  in_person: { label: 'In person', icon: Users, tone: 'bg-amber-100 text-amber-800' },
  video: { label: 'Video', icon: Video, tone: 'bg-violet-100 text-violet-700' },
  other: { label: 'Other', icon: CalendarDays, tone: 'bg-slate-100 text-slate-700' },
};

/**
 * Per-interaction contact log. Sales reps log every email / call /
 * WhatsApp / meeting touch with the client here so the team has a
 * structured history of "what was the last conversation about" — not
 * just the bare "last contact 8d ago" timestamp on the interest.
 *
 * Each entry can optionally schedule a follow-up that auto-creates a
 * reminder pointing back at the interest. Editing the entry's
 * follow-up date keeps the linked reminder in sync; deleting the
 * entry removes the reminder.
 */
export function InterestContactLogTab({ interestId }: InterestContactLogTabProps) {
  const [composeOpen, setComposeOpen] = useState(false);
  const [editTarget, setEditTarget] = useState<ContactLogEntry | null>(null);

  const { data: res, isLoading } = useQuery<{ data: ContactLogEntry[] }>({
    queryKey: ['interests', interestId, 'contact-log'],
    queryFn: () =>
      apiFetch<{ data: ContactLogEntry[] }>(`/api/v1/interests/${interestId}/contact-log`),
  });

  const entries = res?.data ?? [];

  return (
    <div className="space-y-4">
      <div className="flex items-center justify-between">
        <div>
          <h3 className="text-sm font-semibold text-foreground">Contact log</h3>
          <p className="text-xs text-muted-foreground">
            Record each conversation. The most recent log entry sets the &ldquo;Last contact&rdquo;
            chip on the interest header.
          </p>
        </div>
        <Button size="sm" onClick={() => setComposeOpen(true)} className="gap-1.5">
          <Plus className="size-4" />
          Log contact
        </Button>
      </div>

      {isLoading ? (
        <div className="space-y-2">
          <Skeleton className="h-20 rounded-lg" />
          <Skeleton className="h-20 rounded-lg" />
        </div>
      ) : entries.length === 0 ? (
        <EmptyState onAdd={() => setComposeOpen(true)} />
      ) : (
        <ol className="space-y-2">
          {entries.map((e) => (
            <ContactLogRow key={e.id} entry={e} interestId={interestId} onEdit={setEditTarget} />
          ))}
        </ol>
      )}

      <ComposeDialog interestId={interestId} open={composeOpen} onOpenChange={setComposeOpen} />
      {editTarget && (
        <ComposeDialog
          interestId={interestId}
          existing={editTarget}
          open={!!editTarget}
          onOpenChange={(o) => !o && setEditTarget(null)}
        />
      )}
    </div>
  );
}

// ─── Row ─────────────────────────────────────────────────────────────────────

function ContactLogRow({
  entry,
  interestId,
  onEdit,
}: {
  entry: ContactLogEntry;
  interestId: string;
  onEdit: (e: ContactLogEntry) => void;
}) {
  const queryClient = useQueryClient();
  const channelMeta = CHANNEL_META[entry.channel];
  const Icon = channelMeta.icon;

  const deleteMutation = useMutation({
    mutationFn: () => apiFetch(`/api/v1/contact-log/${entry.id}`, { method: 'DELETE' }),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['interests', interestId, 'contact-log'] });
      queryClient.invalidateQueries({ queryKey: ['interests', interestId] });
      toast.success('Contact log entry deleted.');
    },
    onError: (err) => toastError(err),
  });

  return (
    <li className="rounded-lg border bg-background p-3">
      <div className="flex items-start gap-3">
        <span
          aria-hidden
          className={cn(
            'mt-0.5 flex size-8 shrink-0 items-center justify-center rounded-full',
            channelMeta.tone,
          )}
        >
          <Icon className="size-3.5" />
        </span>
        <div className="min-w-0 flex-1 space-y-1.5">
          <div className="flex items-center gap-2 flex-wrap">
            <span className="text-sm font-medium text-foreground">{channelMeta.label}</span>
            <Badge variant="outline" className="text-[10px] capitalize">
              {entry.direction}
            </Badge>
            <span className="text-xs text-muted-foreground">
              {format(new Date(entry.occurredAt), 'MMM d, yyyy · HH:mm')}
            </span>
            <span className="text-xs text-muted-foreground">
              ({formatDistanceToNowStrict(new Date(entry.occurredAt))} ago)
            </span>
          </div>
          <p className="text-sm text-foreground whitespace-pre-wrap">{entry.summary}</p>
          {entry.followUpAt && (
            <p className="inline-flex items-center gap-1.5 rounded-md border border-amber-200 bg-amber-50 px-2 py-0.5 text-xs text-amber-900">
              <Bell className="size-3" />
              Follow up {format(new Date(entry.followUpAt), 'MMM d, yyyy')} (reminder created)
            </p>
          )}
        </div>
        <DropdownMenu>
          <DropdownMenuTrigger asChild>
            <Button variant="ghost" size="icon" className="h-7 w-7" aria-label="Row actions">
              <MoreVertical className="h-4 w-4" />
            </Button>
          </DropdownMenuTrigger>
          <DropdownMenuContent align="end">
            <DropdownMenuItem onClick={() => onEdit(entry)}>
              <Pencil className="mr-2 size-3.5" />
              Edit
            </DropdownMenuItem>
            <DropdownMenuItem
              className="text-destructive"
              disabled={deleteMutation.isPending}
              onClick={() => {
                if (window.confirm('Delete this contact log entry?')) {
                  deleteMutation.mutate();
                }
              }}
            >
              <Trash2 className="mr-2 size-3.5" />
              Delete
            </DropdownMenuItem>
          </DropdownMenuContent>
        </DropdownMenu>
      </div>
    </li>
  );
}

// ─── Empty state ─────────────────────────────────────────────────────────────

function EmptyState({ onAdd }: { onAdd: () => void }) {
  return (
    <div className="rounded-xl border border-dashed bg-muted/20 p-8 text-center">
      <div className="mx-auto flex size-12 items-center justify-center rounded-full bg-background text-muted-foreground">
        <Phone className="size-5" />
      </div>
      <h3 className="mt-3 text-sm font-medium text-foreground">No contact logged yet</h3>
      <p className="mt-1 text-xs text-muted-foreground">
        Record every call, email, and meeting so the team has full context the next time someone
        picks up the deal.
      </p>
      <Button size="sm" onClick={onAdd} className="mt-4 gap-1.5">
        <Plus className="size-3.5" />
        Log first contact
      </Button>
    </div>
  );
}

// ─── Compose / edit dialog ───────────────────────────────────────────────────

function ComposeDialog({
  interestId,
  existing,
  open,
  onOpenChange,
}: {
  interestId: string;
  existing?: ContactLogEntry;
  open: boolean;
  onOpenChange: (open: boolean) => void;
}) {
  const queryClient = useQueryClient();
  const isEdit = !!existing;

  const defaultOccurredAt = useMemo(() => {
    if (existing) return localIsoString(existing.occurredAt);
    return localIsoString(new Date().toISOString());
  }, [existing]);

  const [occurredAt, setOccurredAt] = useState<string>(defaultOccurredAt);
  const [channel, setChannel] = useState<Channel>(existing?.channel ?? 'phone');
  const [direction, setDirection] = useState<Direction>(existing?.direction ?? 'outbound');
  const [summary, setSummary] = useState<string>(existing?.summary ?? '');
  const [followUpAt, setFollowUpAt] = useState<string>(
    existing?.followUpAt ? localIsoString(existing.followUpAt) : '',
  );

  // Re-sync local state when the existing entry changes (e.g. opening
  // the edit dialog for a different row).
  useMemo(() => {
    if (open) {
      setOccurredAt(
        existing ? localIsoString(existing.occurredAt) : localIsoString(new Date().toISOString()),
      );
      setChannel(existing?.channel ?? 'phone');
      setDirection(existing?.direction ?? 'outbound');
      setSummary(existing?.summary ?? '');
      setFollowUpAt(existing?.followUpAt ? localIsoString(existing.followUpAt) : '');
    }
  }, [open, existing]);

  const mutation = useMutation({
    mutationFn: async () => {
      const body = {
        occurredAt: new Date(occurredAt).toISOString(),
        channel,
        direction,
        summary,
        followUpAt: followUpAt ? new Date(followUpAt).toISOString() : null,
      };
      if (isEdit) {
        return apiFetch(`/api/v1/contact-log/${existing!.id}`, {
          method: 'PATCH',
          body,
        });
      }
      return apiFetch(`/api/v1/interests/${interestId}/contact-log`, {
        method: 'POST',
        body,
      });
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['interests', interestId, 'contact-log'] });
      // Bump the parent interest cache so the "Last contact" header chip
      // updates without a refresh.
      queryClient.invalidateQueries({ queryKey: ['interests', interestId] });
      toast.success(isEdit ? 'Contact log entry updated.' : 'Contact logged.');
      onOpenChange(false);
    },
    onError: (err) => toastError(err),
  });

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className="sm:max-w-md">
        <DialogHeader>
          <DialogTitle>{isEdit ? 'Edit contact log entry' : 'Log a contact'}</DialogTitle>
          <DialogDescription>
            Record the channel, the direction, and what was discussed. Optionally schedule a
            follow-up — a reminder will be created automatically.
          </DialogDescription>
        </DialogHeader>

        <div className="space-y-3 py-1">
          <div className="grid grid-cols-2 gap-2">
            <div className="space-y-1">
              <Label htmlFor="cl-channel">Channel</Label>
              <Select value={channel} onValueChange={(v) => setChannel(v as Channel)}>
                <SelectTrigger id="cl-channel">
                  <SelectValue />
                </SelectTrigger>
                <SelectContent>
                  {(Object.keys(CHANNEL_META) as Channel[]).map((c) => (
                    <SelectItem key={c} value={c}>
                      {CHANNEL_META[c].label}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </div>
            <div className="space-y-1">
              <Label htmlFor="cl-direction">Direction</Label>
              <Select value={direction} onValueChange={(v) => setDirection(v as Direction)}>
                <SelectTrigger id="cl-direction">
                  <SelectValue />
                </SelectTrigger>
                <SelectContent>
                  <SelectItem value="outbound">Outbound (you reached out)</SelectItem>
                  <SelectItem value="inbound">Inbound (they reached out)</SelectItem>
                </SelectContent>
              </Select>
            </div>
          </div>

          <div className="space-y-1">
            <Label htmlFor="cl-occurred">When did the conversation happen?</Label>
            <Input
              id="cl-occurred"
              type="datetime-local"
              value={occurredAt}
              onChange={(e) => setOccurredAt(e.target.value)}
            />
          </div>

          <div className="space-y-1">
            <Label htmlFor="cl-summary">Summary</Label>
            <Textarea
              id="cl-summary"
              placeholder="e.g. Confirmed yacht size, asked about tax structure, said they'll respond after their accountant reviews."
              rows={4}
              value={summary}
              onChange={(e) => setSummary(e.target.value)}
            />
          </div>

          <div className="space-y-1">
            <Label htmlFor="cl-followup">Follow up by (optional — creates a reminder)</Label>
            <Input
              id="cl-followup"
              type="datetime-local"
              value={followUpAt}
              onChange={(e) => setFollowUpAt(e.target.value)}
            />
          </div>
        </div>

        <DialogFooter>
          <Button
            variant="outline"
            onClick={() => onOpenChange(false)}
            disabled={mutation.isPending}
          >
            Cancel
          </Button>
          <Button
            onClick={() => mutation.mutate()}
            disabled={mutation.isPending || summary.trim().length === 0}
          >
            {mutation.isPending ? 'Saving…' : isEdit ? 'Save changes' : 'Log contact'}
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}

/**
 * Convert an ISO string into the `YYYY-MM-DDTHH:mm` format that
 * `<input type="datetime-local">` expects, in the user's local
 * timezone. (Browsers don't accept the trailing `Z` in this input
 * type and reject anything with a timezone offset.)
 */
function localIsoString(iso: string): string {
  const d = new Date(iso);
  const pad = (n: number) => String(n).padStart(2, '0');
  return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}T${pad(d.getHours())}:${pad(d.getMinutes())}`;
}
