import { create } from 'zustand';
import { nanoid } from 'nanoid';
import type {
  Room,
  Participant,
  ParticipantLocation,
  ParticipantStatus,
  Waypoint,
  RoomSettings,
  PrecisionLevel,
  Route,
  RouteSegment,
} from '@/types';

// Route state for navigation
interface ActiveRoute {
  id: string;
  from: {
    type: 'participant' | 'waypoint' | 'current';
    id?: string;
    name: string;
  };
  to: {
    type: 'participant' | 'waypoint';
    id: string;
    name: string;
  };
  segments: RouteSegment[];
  totalDistance: number;
  estimatedTime: number;
  summary: string;
  isLoading: boolean;
  error?: string;
}

// Color palette for participants
const COLORS = [
  '#10b981', // emerald
  '#6366f1', // indigo
  '#f59e0b', // amber
  '#ef4444', // red
  '#8b5cf6', // violet
  '#ec4899', // pink
  '#14b8a6', // teal
  '#f97316', // orange
  '#84cc16', // lime
  '#06b6d4', // cyan
];

interface RoomState {
  room: Room | null;
  participants: Participant[];
  currentParticipantId: string | null;
  isConnected: boolean;
  error: string | null;
  activeRoute: ActiveRoute | null;

  // Actions
  joinRoom: (slug: string, name: string, emoji: string) => void;
  leaveRoom: () => void;
  updateParticipant: (updates: Partial<Participant>) => void;
  updateLocation: (location: ParticipantLocation) => void;
  setStatus: (status: ParticipantStatus) => void;
  addWaypoint: (waypoint: Omit<Waypoint, 'id' | 'createdAt' | 'createdBy'>) => void;
  removeWaypoint: (waypointId: string) => void;

  // Route actions
  navigateTo: (
    target: { type: 'participant' | 'waypoint'; id: string },
    currentLocation: ParticipantLocation | undefined,
    allParticipants: Participant[],
    waypoints: Waypoint[]
  ) => Promise<void>;
  clearRoute: () => void;

  // Internal
  _syncFromDocument: (doc: unknown) => void;
}

export const useRoomStore = create<RoomState>((set, get) => ({
  room: null,
  participants: [],
  currentParticipantId: null,
  isConnected: false,
  error: null,
  activeRoute: null,

  joinRoom: (slug: string, name: string, emoji: string) => {
    const participantId = nanoid();
    const colorIndex = Math.floor(Math.random() * COLORS.length);

    const participant: Participant = {
      id: participantId,
      name,
      emoji,
      color: COLORS[colorIndex],
      joinedAt: new Date(),
      lastSeen: new Date(),
      status: 'online',
      privacySettings: {
        sharingEnabled: true,
        defaultPrecision: 'exact' as PrecisionLevel,
        showIndoorFloor: true,
        ghostMode: false,
      },
    };

    // Create or join room
    const room: Room = {
      id: nanoid(),
      slug,
      name: slug,
      createdAt: new Date(),
      createdBy: participantId,
      expiresAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000), // 7 days
      settings: {
        maxParticipants: 10,
        defaultPrecision: 'exact' as PrecisionLevel,
        allowGuestJoin: true,
        showC3NavIndoor: true,
      },
      participants: new Map([[participantId, participant]]),
      waypoints: [],
    };

    set({
      room,
      participants: [participant],
      currentParticipantId: participantId,
      isConnected: true,
      error: null,
    });

    // TODO: Connect to Automerge sync server
    console.log(`Joined room: ${slug} as ${name} (${emoji})`);
  },

  leaveRoom: () => {
    const { room, currentParticipantId } = get();
    if (room && currentParticipantId) {
      room.participants.delete(currentParticipantId);
    }

    set({
      room: null,
      participants: [],
      currentParticipantId: null,
      isConnected: false,
    });
  },

  updateParticipant: (updates: Partial<Participant>) => {
    const { room, currentParticipantId, participants } = get();
    if (!room || !currentParticipantId) return;

    const current = room.participants.get(currentParticipantId);
    if (!current) return;

    const updated = { ...current, ...updates, lastSeen: new Date() };
    room.participants.set(currentParticipantId, updated);

    set({
      participants: participants.map((p) =>
        p.id === currentParticipantId ? updated : p
      ),
    });
  },

  updateLocation: (location: ParticipantLocation) => {
    get().updateParticipant({ location });
  },

  setStatus: (status: ParticipantStatus) => {
    get().updateParticipant({ status });
  },

  addWaypoint: (waypoint) => {
    const { room, currentParticipantId } = get();
    if (!room || !currentParticipantId) return;

    const newWaypoint: Waypoint = {
      ...waypoint,
      id: nanoid(),
      createdAt: new Date(),
      createdBy: currentParticipantId,
    };

    room.waypoints.push(newWaypoint);
    set({ room: { ...room } });
  },

  removeWaypoint: (waypointId: string) => {
    const { room } = get();
    if (!room) return;

    room.waypoints = room.waypoints.filter((w) => w.id !== waypointId);
    set({ room: { ...room } });
  },

  navigateTo: async (
    target: { type: 'participant' | 'waypoint'; id: string },
    currentLocation: ParticipantLocation | undefined,
    allParticipants: Participant[],
    allWaypoints: Waypoint[]
  ) => {
    const { room } = get();

    // Check current user's location (passed from hook, not store)
    if (!currentLocation) {
      set({
        activeRoute: {
          id: nanoid(),
          from: { type: 'current', name: 'You' },
          to: { type: target.type, id: target.id, name: 'Target' },
          segments: [],
          totalDistance: 0,
          estimatedTime: 0,
          summary: '',
          isLoading: false,
          error: 'Enable location sharing to get directions',
        },
      });
      return;
    }

    // Get destination from passed participants/waypoints (not stale store data)
    let destLocation: { latitude: number; longitude: number; indoor?: { level: number; x: number; y: number } } | null = null;
    let destName = '';

    if (target.type === 'participant') {
      const participant = allParticipants.find((p) => p.id === target.id);
      if (participant?.location) {
        destLocation = {
          latitude: participant.location.latitude,
          longitude: participant.location.longitude,
          indoor: participant.location.indoor,
        };
        destName = participant.name;
      }
    } else if (target.type === 'waypoint') {
      const waypoint = allWaypoints.find((w) => w.id === target.id);
      if (waypoint) {
        destLocation = {
          latitude: waypoint.location.latitude,
          longitude: waypoint.location.longitude,
          indoor: waypoint.location.indoor,
        };
        destName = waypoint.name;
      }
    }

    if (!destLocation) {
      set({
        activeRoute: {
          id: nanoid(),
          from: { type: 'current', name: 'You' },
          to: { type: target.type, id: target.id, name: destName || 'Unknown' },
          segments: [],
          totalDistance: 0,
          estimatedTime: 0,
          summary: '',
          isLoading: false,
          error: 'Destination location not available',
        },
      });
      return;
    }

    // Set loading state
    set({
      activeRoute: {
        id: nanoid(),
        from: { type: 'current', name: 'You' },
        to: { type: target.type, id: target.id, name: destName },
        segments: [],
        totalDistance: 0,
        estimatedTime: 0,
        summary: '',
        isLoading: true,
      },
    });

    try {
      const response = await fetch('/api/routing', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          origin: {
            latitude: currentLocation.latitude,
            longitude: currentLocation.longitude,
            indoor: currentLocation.indoor,
          },
          destination: destLocation,
          mode: 'walking',
          eventId: room?.settings.eventId || '39c3',
        }),
      });

      const data = await response.json();

      if (data.success && data.route) {
        set({
          activeRoute: {
            id: nanoid(),
            from: { type: 'current', name: 'You' },
            to: { type: target.type, id: target.id, name: destName },
            segments: data.route.segments,
            totalDistance: data.route.totalDistance,
            estimatedTime: data.route.estimatedTime,
            summary: data.route.summary,
            isLoading: false,
          },
        });
      } else {
        set({
          activeRoute: {
            id: nanoid(),
            from: { type: 'current', name: 'You' },
            to: { type: target.type, id: target.id, name: destName },
            segments: [],
            totalDistance: 0,
            estimatedTime: 0,
            summary: '',
            isLoading: false,
            error: data.error || 'Could not calculate route',
          },
        });
      }
    } catch (error) {
      console.error('Navigation error:', error);
      set({
        activeRoute: {
          id: nanoid(),
          from: { type: 'current', name: 'You' },
          to: { type: target.type, id: target.id, name: destName },
          segments: [],
          totalDistance: 0,
          estimatedTime: 0,
          summary: '',
          isLoading: false,
          error: 'Failed to calculate route',
        },
      });
    }
  },

  clearRoute: () => {
    set({ activeRoute: null });
  },

  _syncFromDocument: (doc: unknown) => {
    // TODO: Implement Automerge document sync
    console.log('Sync from document:', doc);
  },
}));
