-- Phase F: paliad.user_caldav_config — per-user CalDAV credentials and sync state.
--
-- Each user can configure ONE external CalDAV calendar (one row per user).
-- Credentials are stored encrypted at rest using AES-GCM with a 12-byte
-- random nonce prepended to the ciphertext. The encryption key comes from
-- the CALDAV_ENCRYPTION_KEY env var (32-byte AES-256, base64-encoded).
--
-- Audit §1.3 fix: this is the migration that closes the KanzlAI plaintext
-- credential issue. Application code refuses to read/write encrypted blobs
-- when CALDAV_ENCRYPTION_KEY is unset.
--
-- Sync model: a per-user goroutine, spawned at server startup for every row
-- with enabled = true, pushes/pulls every 60 seconds. Conflict resolution is
-- last-write-wins on the modified timestamp; conflicts on Akte-attached
-- termine append a row to paliad.akten_events.

CREATE TABLE paliad.user_caldav_config (
    user_id              uuid PRIMARY KEY REFERENCES auth.users(id) ON DELETE CASCADE,
    url                  text NOT NULL,
    username             text NOT NULL,
    password_encrypted   bytea NOT NULL,
    calendar_path        text NOT NULL DEFAULT '',
    enabled              boolean NOT NULL DEFAULT true,
    last_sync_at         timestamptz,
    last_sync_error      text,
    created_at           timestamptz NOT NULL DEFAULT now(),
    updated_at           timestamptz NOT NULL DEFAULT now()
);

-- Recent sync errors per user (last 5 retained). Separate table so the
-- main row stays small and we can show an audit trail in the UI.
CREATE TABLE paliad.caldav_sync_log (
    id           uuid PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id      uuid NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
    occurred_at  timestamptz NOT NULL DEFAULT now(),
    direction    text NOT NULL CHECK (direction IN ('push', 'pull', 'both')),
    items_pushed int  NOT NULL DEFAULT 0,
    items_pulled int  NOT NULL DEFAULT 0,
    error        text,
    duration_ms  int
);
CREATE INDEX caldav_sync_log_user_time_idx
    ON paliad.caldav_sync_log (user_id, occurred_at DESC);

-- RLS: a user can only see and manage their own row. Encrypted password
-- never leaves the database except through the service layer (and even
-- there, the API never returns it).
ALTER TABLE paliad.user_caldav_config ENABLE ROW LEVEL SECURITY;
CREATE POLICY user_caldav_self_select ON paliad.user_caldav_config
    FOR SELECT TO authenticated
    USING (user_id = auth.uid());
CREATE POLICY user_caldav_self_insert ON paliad.user_caldav_config
    FOR INSERT TO authenticated
    WITH CHECK (user_id = auth.uid());
CREATE POLICY user_caldav_self_update ON paliad.user_caldav_config
    FOR UPDATE TO authenticated
    USING (user_id = auth.uid())
    WITH CHECK (user_id = auth.uid());
CREATE POLICY user_caldav_self_delete ON paliad.user_caldav_config
    FOR DELETE TO authenticated
    USING (user_id = auth.uid());

ALTER TABLE paliad.caldav_sync_log ENABLE ROW LEVEL SECURITY;
CREATE POLICY caldav_sync_log_self_select ON paliad.caldav_sync_log
    FOR SELECT TO authenticated
    USING (user_id = auth.uid());
