-- Fix RLS Policies for Employees Table (V5 - Architectural Fix)
-- This version moves user context to the 'users' table to break recursion.

-- 1. Extend public.users table (Idempotent)
DO $$
BEGIN
    IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='users' AND column_name='role_name') THEN
        ALTER TABLE public.users ADD COLUMN role_name TEXT;
    END IF;
    IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='users' AND column_name='company_id') THEN
        ALTER TABLE public.users ADD COLUMN company_id UUID;
    END IF;
END $$;

-- 2. Create Sync Function
CREATE OR REPLACE FUNCTION public.sync_user_security_context()
RETURNS TRIGGER AS $$
BEGIN
    -- Update the users table when an employee is linked to a user_id
    IF NEW.user_id IS NOT NULL THEN
        UPDATE public.users 
        SET 
            role_name = (SELECT name FROM public.roles WHERE id = NEW.role_id),
            company_id = NEW.company_id
        WHERE id = NEW.user_id;
    END IF;
    RETURN NEW;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;

-- 3. Create Sync Trigger
DROP TRIGGER IF EXISTS on_employee_security_change ON public.employees;
CREATE TRIGGER on_employee_security_change
AFTER INSERT OR UPDATE OF role_id, company_id, user_id ON public.employees
FOR EACH ROW
EXECUTE FUNCTION public.sync_user_security_context();

-- 4. Initial Sync (Seed existing users)
UPDATE public.users u
SET 
    role_name = r.name,
    company_id = e.company_id
FROM public.employees e
JOIN public.roles r ON e.role_id = r.id
WHERE e.user_id = u.id;

-- 5. Helper Function (Bypass RLS)
-- This one is now super safe because it only checks 'users' table
CREATE OR REPLACE FUNCTION public.is_authorized_to_manage(target_company_id UUID)
RETURNS BOOLEAN AS $$
BEGIN
    -- Allow if table is empty (initial setup)
    IF NOT EXISTS (SELECT 1 FROM public.employees) THEN
        RETURN TRUE;
    END IF;

    -- Check users table for cached role info
    -- Since we are querying 'users' from an 'employees' policy, there is NO RECURSION.
    RETURN EXISTS (
        SELECT 1 FROM public.users
        WHERE id = auth.uid() 
        AND (role_name = 'admin' OR (role_name = 'manager' AND company_id = target_company_id))
    );
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;

-- 6. Redefine Employees Policies
DROP POLICY IF EXISTS "Employees unified select" ON public.employees;
DROP POLICY IF EXISTS "Employees unified insert" ON public.employees;
DROP POLICY IF EXISTS "Employees unified update" ON public.employees;
DROP POLICY IF EXISTS "Employees unified delete" ON public.employees;
DROP POLICY IF EXISTS "View employees policy" ON public.employees;
DROP POLICY IF EXISTS "Manage employees policy" ON public.employees;
DROP POLICY IF EXISTS "Initial setup allowance" ON public.employees;

-- SELECT: Colleagues can see each other, Admins see all
CREATE POLICY "Employees select policy"
ON public.employees
FOR SELECT TO authenticated
USING (
    user_id = auth.uid() -- Can see self
    OR EXISTS (
        SELECT 1 FROM public.users u
        WHERE u.id = auth.uid()
        AND (u.role_name = 'admin' OR u.company_id = employees.company_id)
    )
);

-- INSERT/UPDATE/DELETE
CREATE POLICY "Employees management policy"
ON public.employees
FOR ALL TO authenticated
USING ( public.is_authorized_to_manage(company_id) )
WITH CHECK ( public.is_authorized_to_manage(company_id) );
