
-- RV/Boat Lot inventory
CREATE TABLE public.rv_boat_lots (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  association_id UUID NOT NULL REFERENCES public.associations(id) ON DELETE CASCADE,
  lot_number TEXT NOT NULL,
  lot_type TEXT NOT NULL DEFAULT 'rv', -- 'rv' | 'boat' | 'either'
  size TEXT,
  monthly_rate NUMERIC(10,2),
  notes TEXT,
  status TEXT NOT NULL DEFAULT 'available', -- 'available' | 'occupied' | 'maintenance'
  created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  UNIQUE (association_id, lot_number)
);

-- Active rentals (assignments to owners)
CREATE TABLE public.rv_boat_lot_rentals (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  association_id UUID NOT NULL REFERENCES public.associations(id) ON DELETE CASCADE,
  lot_id UUID NOT NULL REFERENCES public.rv_boat_lots(id) ON DELETE CASCADE,
  owner_id UUID REFERENCES public.owners(id) ON DELETE SET NULL,
  unit_id UUID REFERENCES public.units(id) ON DELETE SET NULL,
  renter_name TEXT NOT NULL,
  renter_email TEXT,
  renter_phone TEXT,
  vehicle_description TEXT,
  start_date DATE NOT NULL DEFAULT CURRENT_DATE,
  end_date DATE,
  monthly_rate NUMERIC(10,2),
  status TEXT NOT NULL DEFAULT 'active', -- 'active' | 'ended'
  notes TEXT,
  created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

-- Waitlist
CREATE TABLE public.rv_boat_lot_waitlist (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  association_id UUID NOT NULL REFERENCES public.associations(id) ON DELETE CASCADE,
  position INTEGER NOT NULL,
  requester_name TEXT NOT NULL,
  requester_email TEXT,
  requester_phone TEXT,
  unit_address TEXT,
  owner_id UUID REFERENCES public.owners(id) ON DELETE SET NULL,
  unit_id UUID REFERENCES public.units(id) ON DELETE SET NULL,
  requested_lot_type TEXT DEFAULT 'either', -- 'rv' | 'boat' | 'either'
  vehicle_description TEXT,
  notes TEXT,
  status TEXT NOT NULL DEFAULT 'waiting', -- 'waiting' | 'fulfilled' | 'removed'
  source TEXT NOT NULL DEFAULT 'manual', -- 'manual' | 'public_form'
  fulfilled_at TIMESTAMPTZ,
  fulfilled_lot_number TEXT,
  fulfilled_by UUID REFERENCES auth.users(id) ON DELETE SET NULL,
  joined_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE INDEX rv_boat_lots_assoc_idx ON public.rv_boat_lots(association_id);
CREATE INDEX rv_boat_lot_rentals_assoc_idx ON public.rv_boat_lot_rentals(association_id);
CREATE INDEX rv_boat_lot_rentals_lot_idx ON public.rv_boat_lot_rentals(lot_id);
CREATE INDEX rv_boat_lot_waitlist_assoc_pos_idx ON public.rv_boat_lot_waitlist(association_id, position) WHERE status = 'waiting';

-- Updated_at triggers
CREATE TRIGGER trg_rv_boat_lots_updated BEFORE UPDATE ON public.rv_boat_lots
  FOR EACH ROW EXECUTE FUNCTION public.update_updated_at_column();
CREATE TRIGGER trg_rv_boat_lot_rentals_updated BEFORE UPDATE ON public.rv_boat_lot_rentals
  FOR EACH ROW EXECUTE FUNCTION public.update_updated_at_column();
CREATE TRIGGER trg_rv_boat_lot_waitlist_updated BEFORE UPDATE ON public.rv_boat_lot_waitlist
  FOR EACH ROW EXECUTE FUNCTION public.update_updated_at_column();

-- Auto-assign next position on insert (for waiting entries)
CREATE OR REPLACE FUNCTION public.assign_rv_boat_waitlist_position()
RETURNS TRIGGER LANGUAGE plpgsql SECURITY DEFINER SET search_path = public AS $$
BEGIN
  IF NEW.position IS NULL OR NEW.position = 0 THEN
    SELECT COALESCE(MAX(position), 0) + 1 INTO NEW.position
    FROM public.rv_boat_lot_waitlist
    WHERE association_id = NEW.association_id;
  END IF;
  RETURN NEW;
END;
$$;

CREATE TRIGGER trg_rv_boat_waitlist_position
  BEFORE INSERT ON public.rv_boat_lot_waitlist
  FOR EACH ROW EXECUTE FUNCTION public.assign_rv_boat_waitlist_position();

-- When a rental is created, mark lot occupied; when ended, mark available
CREATE OR REPLACE FUNCTION public.sync_rv_boat_lot_status()
RETURNS TRIGGER LANGUAGE plpgsql SECURITY DEFINER SET search_path = public AS $$
BEGIN
  IF TG_OP = 'INSERT' AND NEW.status = 'active' THEN
    UPDATE public.rv_boat_lots SET status = 'occupied', updated_at = now() WHERE id = NEW.lot_id;
  ELSIF TG_OP = 'UPDATE' AND OLD.status <> NEW.status THEN
    IF NEW.status = 'active' THEN
      UPDATE public.rv_boat_lots SET status = 'occupied', updated_at = now() WHERE id = NEW.lot_id;
    ELSIF NEW.status = 'ended' THEN
      UPDATE public.rv_boat_lots SET status = 'available', updated_at = now() WHERE id = NEW.lot_id;
    END IF;
  END IF;
  RETURN NEW;
END;
$$;

CREATE TRIGGER trg_sync_rv_boat_lot_status
  AFTER INSERT OR UPDATE ON public.rv_boat_lot_rentals
  FOR EACH ROW EXECUTE FUNCTION public.sync_rv_boat_lot_status();

-- Enable RLS
ALTER TABLE public.rv_boat_lots ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.rv_boat_lot_rentals ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.rv_boat_lot_waitlist ENABLE ROW LEVEL SECURITY;

-- Lots policies
CREATE POLICY "Staff and members can view lots" ON public.rv_boat_lots
  FOR SELECT USING (public.user_belongs_to_association(auth.uid(), association_id));
CREATE POLICY "Staff can manage lots" ON public.rv_boat_lots
  FOR ALL USING (public.has_role(auth.uid(), 'admin'::public.app_role) OR public.has_role(auth.uid(), 'manager'::public.app_role))
  WITH CHECK (public.has_role(auth.uid(), 'admin'::public.app_role) OR public.has_role(auth.uid(), 'manager'::public.app_role));

-- Rentals policies
CREATE POLICY "Staff and members can view rentals" ON public.rv_boat_lot_rentals
  FOR SELECT USING (public.user_belongs_to_association(auth.uid(), association_id));
CREATE POLICY "Staff can manage rentals" ON public.rv_boat_lot_rentals
  FOR ALL USING (public.has_role(auth.uid(), 'admin'::public.app_role) OR public.has_role(auth.uid(), 'manager'::public.app_role))
  WITH CHECK (public.has_role(auth.uid(), 'admin'::public.app_role) OR public.has_role(auth.uid(), 'manager'::public.app_role));

-- Waitlist policies
CREATE POLICY "Staff and members can view waitlist" ON public.rv_boat_lot_waitlist
  FOR SELECT USING (public.user_belongs_to_association(auth.uid(), association_id));
CREATE POLICY "Staff can manage waitlist" ON public.rv_boat_lot_waitlist
  FOR ALL USING (public.has_role(auth.uid(), 'admin'::public.app_role) OR public.has_role(auth.uid(), 'manager'::public.app_role))
  WITH CHECK (public.has_role(auth.uid(), 'admin'::public.app_role) OR public.has_role(auth.uid(), 'manager'::public.app_role));

-- Public can submit waitlist entries via published associations
CREATE POLICY "Public can submit waitlist entries" ON public.rv_boat_lot_waitlist
  FOR INSERT TO anon, authenticated
  WITH CHECK (
    source = 'public_form'
    AND status = 'waiting'
    AND EXISTS (
      SELECT 1 FROM public.association_public_pages app
      WHERE app.association_id = rv_boat_lot_waitlist.association_id
        AND app.is_published = true
    )
  );
