-- =====================================================
-- Event-Member Linkage
--
-- Problem: event_registrations links to members by email
-- only. If a member changes their email, event history is
-- lost. transfer_member matches by email — fragile.
--
-- Fix: Add member_id FK to event_registrations, backfill
-- from email matches, update transfer_member.
-- =====================================================

-- Add member_id FK column
ALTER TABLE public.event_registrations
  ADD COLUMN IF NOT EXISTS member_id uuid
  REFERENCES public.members(id) ON DELETE SET NULL;

CREATE INDEX IF NOT EXISTS ix_event_registrations_member
  ON public.event_registrations(member_id)
  WHERE member_id IS NOT NULL;

-- Backfill: match existing registrations to members by email within the same account
UPDATE public.event_registrations er
SET member_id = m.id
FROM public.events e, public.members m
WHERE e.id = er.event_id
  AND m.account_id = e.account_id
  AND lower(m.email) = lower(er.email)
  AND m.email IS NOT NULL AND m.email != ''
  AND m.status IN ('active', 'inactive', 'pending')
  AND er.member_id IS NULL
  AND er.email IS NOT NULL AND er.email != '';

-- Update transfer_member to count active events via member_id instead of email
CREATE OR REPLACE FUNCTION public.transfer_member(
  p_member_id uuid,
  p_target_account_id uuid,
  p_reason text DEFAULT NULL,
  p_keep_sepa boolean DEFAULT true
)
RETURNS uuid
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = ''
AS $$
DECLARE
  v_source_account_id uuid;
  v_source_name varchar;
  v_target_name varchar;
  v_active_courses bigint;
  v_active_events bigint;
  v_cleared_data jsonb;
  v_transfer_id uuid;
  v_member record;
BEGIN
  -- Get current member state
  SELECT * INTO v_member FROM public.members WHERE id = p_member_id;
  IF v_member IS NULL THEN
    RAISE EXCEPTION 'Member not found';
  END IF;

  v_source_account_id := v_member.account_id;

  -- Verify target account exists
  IF NOT EXISTS (SELECT 1 FROM public.accounts WHERE id = p_target_account_id) THEN
    RAISE EXCEPTION 'Target account not found';
  END IF;

  -- Ensure caller has access to source account
  IF NOT public.has_role_on_account_or_ancestor(v_source_account_id) THEN
    RAISE EXCEPTION 'Access denied to source account';
  END IF;

  -- Same account? No-op
  IF v_source_account_id = p_target_account_id THEN
    RAISE EXCEPTION 'Cannot transfer member to the same account';
  END IF;

  -- Ensure both accounts share a common ancestor
  IF NOT EXISTS (
    SELECT 1
    FROM public.get_account_ancestors(v_source_account_id) sa
    JOIN public.get_account_ancestors(p_target_account_id) ta ON sa = ta
  ) THEN
    RAISE EXCEPTION 'Source and target accounts do not share a common ancestor (Verband)';
  END IF;

  -- Get org names for the transfer note
  SELECT name INTO v_source_name FROM public.accounts WHERE id = v_source_account_id;
  SELECT name INTO v_target_name FROM public.accounts WHERE id = p_target_account_id;

  -- Count active relationships (informational, for the log)
  SELECT count(*) INTO v_active_courses
  FROM public.course_participants cp
  JOIN public.courses c ON c.id = cp.course_id
  WHERE cp.member_id = p_member_id AND cp.status = 'enrolled';

  -- Use member_id for event lookups instead of fragile email matching
  SELECT count(*) INTO v_active_events
  FROM public.event_registrations er
  JOIN public.events e ON e.id = er.event_id
  WHERE er.member_id = p_member_id
    AND er.status IN ('confirmed', 'pending')
    AND e.event_date >= current_date;

  -- Perform the transfer
  UPDATE public.members
  SET
    account_id = p_target_account_id,
    -- Clear org-specific admin data
    dues_category_id = NULL,
    member_number = NULL,
    -- Clear primary_mandate_id FK (mandate needs re-confirmation in new org)
    primary_mandate_id = NULL,
    -- Legacy inline SEPA fields (deprecated, kept for backward compat)
    sepa_mandate_id = CASE WHEN p_keep_sepa THEN sepa_mandate_id ELSE NULL END,
    sepa_mandate_date = CASE WHEN p_keep_sepa THEN sepa_mandate_date ELSE NULL END,
    sepa_mandate_status = 'pending',
    -- Append transfer note
    notes = COALESCE(notes, '') ||
      E'\n[Transfer ' || to_char(now(), 'YYYY-MM-DD') || '] ' ||
      v_source_name || ' → ' || v_target_name ||
      COALESCE(' | Grund: ' || p_reason, ''),
    is_transferred = true
  WHERE id = p_member_id;

  -- Reset SEPA mandate(s) in the mandates table
  UPDATE public.sepa_mandates
  SET status = 'pending'
  WHERE member_id = p_member_id
    AND status = 'active';

  -- Build cleared data snapshot for the transfer log
  v_cleared_data := jsonb_build_object(
    'member_number', v_member.member_number,
    'dues_category_id', v_member.dues_category_id,
    'active_courses', v_active_courses,
    'active_events', v_active_events
  );

  -- Create transfer log entry
  INSERT INTO public.member_transfers (
    member_id, source_account_id, target_account_id, transferred_by, reason, cleared_data
  ) VALUES (
    p_member_id,
    v_source_account_id,
    p_target_account_id,
    COALESCE(nullif(current_setting('app.current_user_id', true), '')::uuid, auth.uid()),
    p_reason,
    v_cleared_data
  )
  RETURNING id INTO v_transfer_id;

  RETURN v_transfer_id;
END;
$$;
