
-- Elections table
CREATE TABLE public.elections (
  id UUID NOT NULL DEFAULT gen_random_uuid() PRIMARY KEY,
  association_id UUID NOT NULL REFERENCES public.associations(id) ON DELETE CASCADE,
  title TEXT NOT NULL,
  description TEXT,
  election_type TEXT NOT NULL DEFAULT 'board_election',
  status TEXT NOT NULL DEFAULT 'draft',
  voting_start TIMESTAMPTZ,
  voting_end TIMESTAMPTZ,
  results_locked BOOLEAN NOT NULL DEFAULT true,
  quorum_required INTEGER NOT NULL DEFAULT 0,
  proxies_count INTEGER NOT NULL DEFAULT 0,
  in_person_count INTEGER NOT NULL DEFAULT 0,
  created_by UUID REFERENCES auth.users(id),
  created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

-- Election positions (e.g. President, Treasurer)
CREATE TABLE public.election_positions (
  id UUID NOT NULL DEFAULT gen_random_uuid() PRIMARY KEY,
  election_id UUID NOT NULL REFERENCES public.elections(id) ON DELETE CASCADE,
  title TEXT NOT NULL,
  seats_available INTEGER NOT NULL DEFAULT 1,
  sort_order INTEGER NOT NULL DEFAULT 0,
  created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

-- Election candidates
CREATE TABLE public.election_candidates (
  id UUID NOT NULL DEFAULT gen_random_uuid() PRIMARY KEY,
  position_id UUID NOT NULL REFERENCES public.election_positions(id) ON DELETE CASCADE,
  candidate_name TEXT NOT NULL,
  bio TEXT,
  sort_order INTEGER NOT NULL DEFAULT 0,
  created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

-- Eligible voters (one vote per unit)
CREATE TABLE public.election_eligible_voters (
  id UUID NOT NULL DEFAULT gen_random_uuid() PRIMARY KEY,
  election_id UUID NOT NULL REFERENCES public.elections(id) ON DELETE CASCADE,
  owner_id UUID NOT NULL REFERENCES public.owners(id) ON DELETE CASCADE,
  unit_id UUID REFERENCES public.units(id) ON DELETE SET NULL,
  has_consent BOOLEAN NOT NULL DEFAULT false,
  consent_date TIMESTAMPTZ,
  vote_token UUID UNIQUE DEFAULT gen_random_uuid(),
  has_voted BOOLEAN NOT NULL DEFAULT false,
  voted_at TIMESTAMPTZ,
  created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  UNIQUE(election_id, unit_id)
);

-- Anonymous ballots (no link to voter identity - linked only to token)
CREATE TABLE public.election_ballots (
  id UUID NOT NULL DEFAULT gen_random_uuid() PRIMARY KEY,
  election_id UUID NOT NULL REFERENCES public.elections(id) ON DELETE CASCADE,
  position_id UUID NOT NULL REFERENCES public.election_positions(id) ON DELETE CASCADE,
  candidate_id UUID REFERENCES public.election_candidates(id) ON DELETE SET NULL,
  vote_token UUID NOT NULL,
  created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

-- Audit log (tracks who voted but NOT how)
CREATE TABLE public.election_audit_log (
  id UUID NOT NULL DEFAULT gen_random_uuid() PRIMARY KEY,
  election_id UUID NOT NULL REFERENCES public.elections(id) ON DELETE CASCADE,
  voter_description TEXT NOT NULL,
  action TEXT NOT NULL DEFAULT 'voted',
  ip_address TEXT,
  created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

-- Enable RLS
ALTER TABLE public.elections ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.election_positions ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.election_candidates ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.election_eligible_voters ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.election_ballots ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.election_audit_log ENABLE ROW LEVEL SECURITY;

-- Elections: staff full access, owners can read their own association's elections
CREATE POLICY "Staff can manage elections" ON public.elections
  FOR ALL TO authenticated
  USING (public.has_role(auth.uid(), 'admin') OR public.has_role(auth.uid(), 'manager') OR public.has_role(auth.uid(), 'employee'));

CREATE POLICY "Owners can view their association elections" ON public.elections
  FOR SELECT TO authenticated
  USING (association_id IN (SELECT public.get_user_association_ids()));

-- Positions: staff full access, authenticated read
CREATE POLICY "Staff can manage positions" ON public.election_positions
  FOR ALL TO authenticated
  USING (public.has_role(auth.uid(), 'admin') OR public.has_role(auth.uid(), 'manager') OR public.has_role(auth.uid(), 'employee'));

CREATE POLICY "Authenticated can view positions" ON public.election_positions
  FOR SELECT TO authenticated
  USING (election_id IN (SELECT id FROM public.elections WHERE association_id IN (SELECT public.get_user_association_ids())));

-- Candidates: staff full access, authenticated read
CREATE POLICY "Staff can manage candidates" ON public.election_candidates
  FOR ALL TO authenticated
  USING (public.has_role(auth.uid(), 'admin') OR public.has_role(auth.uid(), 'manager') OR public.has_role(auth.uid(), 'employee'));

CREATE POLICY "Authenticated can view candidates" ON public.election_candidates
  FOR SELECT TO authenticated
  USING (position_id IN (SELECT id FROM public.election_positions WHERE election_id IN (SELECT id FROM public.elections WHERE association_id IN (SELECT public.get_user_association_ids()))));

-- Eligible voters: staff full access, voters can see their own record
CREATE POLICY "Staff can manage eligible voters" ON public.election_eligible_voters
  FOR ALL TO authenticated
  USING (public.has_role(auth.uid(), 'admin') OR public.has_role(auth.uid(), 'manager') OR public.has_role(auth.uid(), 'employee'));

CREATE POLICY "Owners can view their own voter record" ON public.election_eligible_voters
  FOR SELECT TO authenticated
  USING (owner_id IN (SELECT id FROM public.owners WHERE user_id = auth.uid()));

-- Ballots: staff can read (for tallying), voters can insert/update their own
CREATE POLICY "Staff can view ballots" ON public.election_ballots
  FOR SELECT TO authenticated
  USING (public.has_role(auth.uid(), 'admin') OR public.has_role(auth.uid(), 'manager'));

CREATE POLICY "Voters can insert ballots" ON public.election_ballots
  FOR INSERT TO authenticated
  WITH CHECK (vote_token IN (SELECT vote_token FROM public.election_eligible_voters WHERE owner_id IN (SELECT id FROM public.owners WHERE user_id = auth.uid())));

CREATE POLICY "Voters can update their ballots" ON public.election_ballots
  FOR UPDATE TO authenticated
  USING (vote_token IN (SELECT vote_token FROM public.election_eligible_voters WHERE owner_id IN (SELECT id FROM public.owners WHERE user_id = auth.uid())));

CREATE POLICY "Voters can delete their ballots" ON public.election_ballots
  FOR DELETE TO authenticated
  USING (vote_token IN (SELECT vote_token FROM public.election_eligible_voters WHERE owner_id IN (SELECT id FROM public.owners WHERE user_id = auth.uid())));

-- Audit log: staff can read, system inserts
CREATE POLICY "Staff can view audit log" ON public.election_audit_log
  FOR SELECT TO authenticated
  USING (public.has_role(auth.uid(), 'admin') OR public.has_role(auth.uid(), 'manager'));

CREATE POLICY "Authenticated can insert audit log" ON public.election_audit_log
  FOR INSERT TO authenticated
  WITH CHECK (true);

-- Indexes
CREATE INDEX idx_elections_association ON public.elections(association_id);
CREATE INDEX idx_elections_status ON public.elections(status);
CREATE INDEX idx_election_positions_election ON public.election_positions(election_id);
CREATE INDEX idx_election_candidates_position ON public.election_candidates(position_id);
CREATE INDEX idx_election_eligible_voters_election ON public.election_eligible_voters(election_id);
CREATE INDEX idx_election_eligible_voters_token ON public.election_eligible_voters(vote_token);
CREATE INDEX idx_election_ballots_election ON public.election_ballots(election_id);
CREATE INDEX idx_election_ballots_token ON public.election_ballots(vote_token);
