import { useState, FormEvent, useCallback } from 'react';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { toast } from 'sonner';
import api, { getErrorMessage } from '@/lib/api';
import type { Calendar, CalendarMemberInfo, CalendarPermission, Connection } from '@/types';
import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
  DialogFooter,
  DialogClose,
} from '@/components/ui/dialog';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Button } from '@/components/ui/button';
import { Switch } from '@/components/ui/switch';
import { Select } from '@/components/ui/select';
import { useConnections } from '@/hooks/useConnections';
import { useSharedCalendars } from '@/hooks/useSharedCalendars';
import CalendarMemberSearch from './CalendarMemberSearch';
import CalendarMemberList from './CalendarMemberList';

interface CalendarFormProps {
  calendar: Calendar | null;
  onClose: () => void;
}

const colorSwatches = [
  '#3b82f6', '#ef4444', '#f97316', '#eab308',
  '#22c55e', '#8b5cf6', '#ec4899', '#06b6d4',
];

export default function CalendarForm({ calendar, onClose }: CalendarFormProps) {
  const queryClient = useQueryClient();
  const [name, setName] = useState(calendar?.name || '');
  const [color, setColor] = useState(calendar?.color || '#3b82f6');
  const [isShared, setIsShared] = useState(calendar?.is_shared ?? false);

  const [pendingInvite, setPendingInvite] = useState<{ conn: Connection; permission: CalendarPermission } | null>(null);

  const { connections } = useConnections();
  const { invite, isInviting, updateMember, removeMember } = useSharedCalendars();

  const membersQuery = useQuery({
    queryKey: ['calendar-members', calendar?.id],
    queryFn: async () => {
      const { data } = await api.get<CalendarMemberInfo[]>(
        `/shared-calendars/${calendar!.id}/members`
      );
      return data;
    },
    enabled: !!calendar?.is_shared,
  });
  const members = membersQuery.data ?? [];

  const mutation = useMutation({
    mutationFn: async () => {
      if (calendar) {
        const { data } = await api.put(`/calendars/${calendar.id}`, { name, color });
        return data;
      } else {
        const { data } = await api.post('/calendars', { name, color });
        return data;
      }
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['calendars'] });
      queryClient.invalidateQueries({ queryKey: ['calendar-events'] });
      toast.success(calendar ? 'Calendar updated' : 'Calendar created');
      onClose();
    },
    onError: (error) => {
      toast.error(getErrorMessage(error, 'Failed to save calendar'));
    },
  });

  const deleteMutation = useMutation({
    mutationFn: async () => {
      await api.delete(`/calendars/${calendar?.id}`);
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['calendars'] });
      queryClient.invalidateQueries({ queryKey: ['calendar-events'] });
      toast.success('Calendar deleted');
      onClose();
    },
    onError: (error) => {
      toast.error(getErrorMessage(error, 'Failed to delete calendar'));
    },
  });

  const handleSubmit = (e: FormEvent) => {
    e.preventDefault();
    if (!name.trim()) return;
    mutation.mutate();
  };

  const handleSelectConnection = useCallback((conn: Connection) => {
    setPendingInvite({ conn, permission: 'read_only' });
  }, []);

  const handleSendInvite = async () => {
    if (!calendar || !pendingInvite) return;
    await invite({
      calendarId: calendar.id,
      connectionId: pendingInvite.conn.id,
      permission: pendingInvite.permission,
      canAddOthers: false,
    });
    setPendingInvite(null);
  };

  const handleUpdatePermission = async (memberId: number, permission: CalendarPermission) => {
    if (!calendar) return;
    await updateMember({ calendarId: calendar.id, memberId, permission });
  };

  const handleUpdateCanAddOthers = async (memberId: number, canAddOthers: boolean) => {
    if (!calendar) return;
    await updateMember({ calendarId: calendar.id, memberId, canAddOthers });
  };

  const handleRemoveMember = async (memberId: number) => {
    if (!calendar) return;
    await removeMember({ calendarId: calendar.id, memberId });
  };

  const canDelete = calendar && !calendar.is_default && !calendar.is_system;
  const showSharing = calendar && !calendar.is_system;

  return (
    <Dialog open={true} onOpenChange={onClose}>
      <DialogContent className={isShared && showSharing ? 'sm:max-w-lg' : undefined}>
        <DialogClose onClick={onClose} />
        <DialogHeader>
          <DialogTitle>{calendar ? 'Edit Calendar' : 'New Calendar'}</DialogTitle>
        </DialogHeader>
        <form onSubmit={handleSubmit} className="space-y-4">
          <div className="space-y-2">
            <Label htmlFor="cal-name" required>Name</Label>
            <Input
              id="cal-name"
              value={name}
              onChange={(e) => setName(e.target.value)}
              placeholder="Calendar name"
              required
              disabled={calendar?.is_system}
            />
          </div>

          <div className="space-y-2">
            <Label>Color</Label>
            <div className="flex gap-2">
              {colorSwatches.map((c) => (
                <button
                  key={c}
                  type="button"
                  onClick={() => setColor(c)}
                  className="h-8 w-8 rounded-full border-2 transition-all duration-150 hover:scale-110"
                  style={{
                    backgroundColor: c,
                    borderColor: color === c ? 'hsl(0 0% 98%)' : 'transparent',
                    boxShadow: color === c ? `0 0 0 2px ${c}40` : 'none',
                  }}
                />
              ))}
            </div>
          </div>

          {showSharing && (
            <>
              <div className="flex items-center justify-between py-3 border-t border-border">
                <Label className="mb-0">Share this calendar</Label>
                <Switch
                  checked={isShared}
                  onCheckedChange={setIsShared}
                />
              </div>

              {isShared && (
                <div className="space-y-3">
                  <div className="flex items-center justify-between">
                    <Label className="mb-0">Members</Label>
                    <span className="text-[11px] text-muted-foreground">
                      You (Owner)
                    </span>
                  </div>

                  {pendingInvite ? (
                    <div className="rounded-md border border-border bg-card-elevated p-3 space-y-2 animate-fade-in">
                      <div className="flex items-center justify-between">
                        <span className="text-sm text-foreground">
                          {pendingInvite.conn.connected_preferred_name || pendingInvite.conn.connected_umbral_name}
                        </span>
                        <button
                          type="button"
                          onClick={() => setPendingInvite(null)}
                          className="text-xs text-muted-foreground hover:text-foreground"
                        >
                          Cancel
                        </button>
                      </div>
                      <div className="flex items-center gap-2">
                        <Select
                          value={pendingInvite.permission}
                          onChange={(e) => setPendingInvite((prev) => prev ? { ...prev, permission: e.target.value as CalendarPermission } : null)}
                          className="text-xs flex-1"
                        >
                          <option value="read_only">Read Only</option>
                          <option value="create_modify">Create / Modify</option>
                          <option value="full_access">Full Access</option>
                        </Select>
                        <Button
                          type="button"
                          size="sm"
                          onClick={handleSendInvite}
                          disabled={isInviting}
                        >
                          {isInviting ? 'Sending...' : 'Send Invite'}
                        </Button>
                      </div>
                    </div>
                  ) : (
                    <CalendarMemberSearch
                      connections={connections}
                      existingMembers={members}
                      onSelect={handleSelectConnection}
                      isLoading={isInviting}
                    />
                  )}

                  <CalendarMemberList
                    members={members}
                    isLoading={membersQuery.isLoading}
                    isOwner={true}
                    onUpdatePermission={handleUpdatePermission}
                    onUpdateCanAddOthers={handleUpdateCanAddOthers}
                    onRemove={handleRemoveMember}
                  />
                </div>
              )}
            </>
          )}

          <DialogFooter>
            {canDelete && (
              <Button
                type="button"
                variant="destructive"
                onClick={() => deleteMutation.mutate()}
                disabled={deleteMutation.isPending}
                className="mr-auto"
              >
                Delete
              </Button>
            )}
            <Button type="button" variant="outline" onClick={onClose}>
              Cancel
            </Button>
            <Button type="submit" disabled={mutation.isPending}>
              {mutation.isPending ? 'Saving...' : calendar ? 'Update' : 'Create'}
            </Button>
          </DialogFooter>
        </form>
      </DialogContent>
    </Dialog>
  );
}
