-- t-paliad-070: Rename departments → partner_units across the schema, drop
-- the legacy users.dezernat free-text column, and add the
-- partner_unit_events audit table.
--
-- Order of operations matters because constraint names are owned by their
-- owning table; we rename the table first, then the columns/constraints/
-- policies that postgres did not auto-rename.
--
-- Idempotent renames (DO $$ EXCEPTION WHEN undefined_object $$) are used
-- for constraint/index/policy steps so re-runs after a partial apply on
-- freshly-provisioned DBs (e.g. test DBs that may have run earlier
-- migrations under different names) do not abort the chain.

-- ---------------------------------------------------------------------------
-- 1. Best-effort second seed of department_members from the legacy
--    users.dezernat free-text field. Mirror of migration 019 — re-run before
--    DROP COLUMN to capture any drift since 019 ran. Idempotent via
--    ON CONFLICT DO NOTHING.
-- ---------------------------------------------------------------------------
INSERT INTO paliad.departments (id, name, lead_user_id, office, created_at, updated_at)
SELECT gen_random_uuid(),
       btrim(u.dezernat),
       NULL,
       MIN(u.office),
       now(),
       now()
  FROM paliad.users u
 WHERE u.dezernat IS NOT NULL
   AND btrim(u.dezernat) <> ''
   AND NOT EXISTS (
     SELECT 1 FROM paliad.departments d2 WHERE d2.name = btrim(u.dezernat)
   )
 GROUP BY btrim(u.dezernat)
ON CONFLICT DO NOTHING;

INSERT INTO paliad.department_members (department_id, user_id, created_at)
SELECT d.id, u.id, now()
  FROM paliad.users u
  JOIN paliad.departments d
    ON d.name = btrim(u.dezernat)
 WHERE u.dezernat IS NOT NULL
   AND btrim(u.dezernat) <> ''
ON CONFLICT DO NOTHING;

-- ---------------------------------------------------------------------------
-- 2. Drop the legacy free-text column. The structured side
--    (department_members) is the source of truth from here on.
-- ---------------------------------------------------------------------------
ALTER TABLE paliad.users DROP COLUMN IF EXISTS dezernat;

-- ---------------------------------------------------------------------------
-- 3. Rename tables.
-- ---------------------------------------------------------------------------
ALTER TABLE paliad.departments        RENAME TO partner_units;
ALTER TABLE paliad.department_members RENAME TO partner_unit_members;

-- ---------------------------------------------------------------------------
-- 4. Rename junction column.
-- ---------------------------------------------------------------------------
ALTER TABLE paliad.partner_unit_members RENAME COLUMN department_id TO partner_unit_id;

-- ---------------------------------------------------------------------------
-- 5. Rename constraints. Postgres auto-renames the underlying index for
--    pkey/uniq constraints; standalone indexes are renamed in step 6.
-- ---------------------------------------------------------------------------
DO $$ BEGIN ALTER TABLE paliad.partner_units        RENAME CONSTRAINT departments_pkey                       TO partner_units_pkey;                             EXCEPTION WHEN undefined_object OR undefined_table OR duplicate_object THEN NULL; END $$;
DO $$ BEGIN ALTER TABLE paliad.partner_units        RENAME CONSTRAINT departments_lead_user_id_fkey          TO partner_units_lead_user_id_fkey;                EXCEPTION WHEN undefined_object OR undefined_table OR duplicate_object THEN NULL; END $$;
DO $$ BEGIN ALTER TABLE paliad.partner_units        RENAME CONSTRAINT departments_office_check               TO partner_units_office_check;                     EXCEPTION WHEN undefined_object OR undefined_table OR duplicate_object THEN NULL; END $$;
DO $$ BEGIN ALTER TABLE paliad.partner_unit_members RENAME CONSTRAINT department_members_pkey                TO partner_unit_members_pkey;                      EXCEPTION WHEN undefined_object OR undefined_table OR duplicate_object THEN NULL; END $$;
DO $$ BEGIN ALTER TABLE paliad.partner_unit_members RENAME CONSTRAINT department_members_department_id_fkey  TO partner_unit_members_partner_unit_id_fkey;      EXCEPTION WHEN undefined_object OR undefined_table OR duplicate_object THEN NULL; END $$;
DO $$ BEGIN ALTER TABLE paliad.partner_unit_members RENAME CONSTRAINT department_members_user_id_fkey        TO partner_unit_members_user_id_fkey;              EXCEPTION WHEN undefined_object OR undefined_table OR duplicate_object THEN NULL; END $$;

-- ---------------------------------------------------------------------------
-- 6. Rename non-pkey indexes.
-- ---------------------------------------------------------------------------
DO $$ BEGIN ALTER INDEX paliad.departments_office_idx        RENAME TO partner_units_office_idx;        EXCEPTION WHEN undefined_object OR undefined_table OR duplicate_object THEN NULL; END $$;
DO $$ BEGIN ALTER INDEX paliad.departments_lead_idx          RENAME TO partner_units_lead_idx;          EXCEPTION WHEN undefined_object OR undefined_table OR duplicate_object THEN NULL; END $$;
DO $$ BEGIN ALTER INDEX paliad.department_members_user_idx   RENAME TO partner_unit_members_user_idx;   EXCEPTION WHEN undefined_object OR undefined_table OR duplicate_object THEN NULL; END $$;

-- ---------------------------------------------------------------------------
-- 7. Rename RLS policies.
-- ---------------------------------------------------------------------------
DO $$ BEGIN ALTER POLICY departments_select        ON paliad.partner_units        RENAME TO partner_units_select;        EXCEPTION WHEN undefined_object OR undefined_table OR duplicate_object THEN NULL; END $$;
DO $$ BEGIN ALTER POLICY departments_write         ON paliad.partner_units        RENAME TO partner_units_write;         EXCEPTION WHEN undefined_object OR undefined_table OR duplicate_object THEN NULL; END $$;
DO $$ BEGIN ALTER POLICY department_members_select ON paliad.partner_unit_members RENAME TO partner_unit_members_select; EXCEPTION WHEN undefined_object OR undefined_table OR duplicate_object THEN NULL; END $$;
DO $$ BEGIN ALTER POLICY department_members_write  ON paliad.partner_unit_members RENAME TO partner_unit_members_write;  EXCEPTION WHEN undefined_object OR undefined_table OR duplicate_object THEN NULL; END $$;

-- ---------------------------------------------------------------------------
-- 8. Audit table for partner-unit events. Mutations on partner_units +
--    partner_unit_members emit one row each, written in the same tx by
--    PartnerUnitService. The viewer in audit_service.go unions this source
--    in alongside project_events / caldav_sync_log / reminder_log.
--
--    partner_unit_id is nullable + ON DELETE SET NULL so the historical
--    'deleted' event survives the cascade that removes the unit row.
-- ---------------------------------------------------------------------------
CREATE TABLE paliad.partner_unit_events (
    id              uuid          PRIMARY KEY DEFAULT gen_random_uuid(),
    partner_unit_id uuid          NULL REFERENCES paliad.partner_units(id) ON DELETE SET NULL,
    actor_id        uuid          NOT NULL REFERENCES auth.users(id),
    event_type      text          NOT NULL CHECK (event_type IN (
        'created', 'updated', 'deleted', 'member_added', 'member_removed'
    )),
    -- Snapshot of the unit's name at event time so deleted units still show
    -- a human-readable label in the audit timeline (partner_unit_id is NULL
    -- on deleted, so we can't JOIN through to partner_units.name).
    unit_name       text          NOT NULL,
    payload         jsonb         NOT NULL DEFAULT '{}'::jsonb,
    created_at      timestamptz   NOT NULL DEFAULT now()
);

CREATE INDEX partner_unit_events_unit_idx  ON paliad.partner_unit_events(partner_unit_id, created_at DESC);
CREATE INDEX partner_unit_events_actor_idx ON paliad.partner_unit_events(actor_id, created_at DESC);
CREATE INDEX partner_unit_events_time_idx  ON paliad.partner_unit_events(created_at DESC);

-- RLS: read access matches /api/partner-units (any authenticated user);
-- writes only by global_admin (defence-in-depth — the service already
-- gates with requireAdmin).
ALTER TABLE paliad.partner_unit_events ENABLE ROW LEVEL SECURITY;

CREATE POLICY partner_unit_events_select ON paliad.partner_unit_events
    FOR SELECT USING (auth.uid() IS NOT NULL);

CREATE POLICY partner_unit_events_write ON paliad.partner_unit_events
    FOR INSERT WITH CHECK (
      EXISTS (
        SELECT 1 FROM paliad.users u
         WHERE u.id = auth.uid()
           AND u.global_role = 'global_admin'
      )
    );
