-- ==========================================
-- Chat Switchboard — 018 Workflows
-- ==========================================
-- Workflow definitions, stages, version snapshots, assignments.
-- Consolidated v0.28.0: merges 023 + 025 (assignments) + 027 (webhooks).
-- Also adds deferred FK: channels.workflow_id → workflows.id.
-- ==========================================

-- =========================================
-- WORKFLOW DEFINITIONS
-- =========================================

CREATE TABLE IF NOT EXISTS workflows (
    id           UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    team_id      UUID REFERENCES teams(id) ON DELETE CASCADE,
    name         TEXT NOT NULL,
    slug         TEXT NOT NULL,
    description  TEXT NOT NULL DEFAULT '',
    branding     JSONB NOT NULL DEFAULT '{}',
    entry_mode   TEXT NOT NULL DEFAULT 'public_link'
                     CHECK (entry_mode IN ('public_link', 'team_only')),
    is_active    BOOLEAN NOT NULL DEFAULT false,
    version      INTEGER NOT NULL DEFAULT 1,
    on_complete  JSONB,
    retention    JSONB NOT NULL DEFAULT '{"mode": "archive"}',

    -- Webhooks (v0.27.3)
    webhook_url    TEXT,
    webhook_secret TEXT,

    created_by   UUID NOT NULL REFERENCES users(id),
    created_at   TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at   TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE UNIQUE INDEX IF NOT EXISTS idx_workflows_team_slug
    ON workflows(team_id, slug) WHERE team_id IS NOT NULL;
CREATE UNIQUE INDEX IF NOT EXISTS idx_workflows_global_slug
    ON workflows(slug) WHERE team_id IS NULL;
CREATE INDEX IF NOT EXISTS idx_workflows_active
    ON workflows(is_active) WHERE is_active = true;

DROP TRIGGER IF EXISTS workflows_updated_at ON workflows;
CREATE TRIGGER workflows_updated_at
    BEFORE UPDATE ON workflows
    FOR EACH ROW EXECUTE FUNCTION update_updated_at();

COMMENT ON TABLE workflows IS 'Team-owned or global workflow definitions with staged processes.';
COMMENT ON COLUMN workflows.slug IS 'URL-safe identifier, unique within scope (team or global).';
COMMENT ON COLUMN workflows.branding IS '{"accent_color": "#hex", "logo_url": "...", "tagline": "..."}';
COMMENT ON COLUMN workflows.on_complete IS 'Chaining hook — triggers another workflow on completion.';
COMMENT ON COLUMN workflows.retention IS '{"mode": "archive"|"delete", "delete_after_days": N}';


-- =========================================
-- WORKFLOW STAGES
-- =========================================

CREATE TABLE IF NOT EXISTS workflow_stages (
    id                 UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    workflow_id        UUID NOT NULL REFERENCES workflows(id) ON DELETE CASCADE,
    ordinal            INTEGER NOT NULL,
    name               TEXT NOT NULL,
    persona_id         UUID REFERENCES personas(id) ON DELETE SET NULL,
    assignment_team_id UUID REFERENCES teams(id) ON DELETE SET NULL,
    form_template      JSONB NOT NULL DEFAULT '{}',
    stage_mode         TEXT NOT NULL DEFAULT 'chat_only'
                           CHECK (stage_mode IN ('chat_only', 'form_only', 'form_chat', 'review')),
    history_mode       TEXT NOT NULL DEFAULT 'full'
                           CHECK (history_mode IN ('full', 'summary', 'fresh')),
    auto_transition    BOOLEAN NOT NULL DEFAULT false,
    transition_rules   JSONB NOT NULL DEFAULT '{}',
    surface_pkg_id     TEXT REFERENCES packages(id) ON DELETE SET NULL,
    sla_seconds        INTEGER,
    created_at         TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE INDEX IF NOT EXISTS idx_workflow_stages_workflow
    ON workflow_stages(workflow_id, ordinal);

COMMENT ON TABLE workflow_stages IS 'Ordered stages within a workflow. Each stage has a driving persona and optional human assignment.';
COMMENT ON COLUMN workflow_stages.history_mode IS 'full=complete history, summary=utility-role summary, fresh=clean slate';
COMMENT ON COLUMN workflow_stages.form_template IS 'JSON schema of fields the persona should collect from the visitor.';
COMMENT ON COLUMN workflow_stages.surface_pkg_id IS 'Optional package that provides a custom stage surface. NULL = built-in surface based on stage_mode.';
COMMENT ON COLUMN workflow_stages.sla_seconds IS 'SLA budget in seconds for this stage. NULL = no SLA.';


-- =========================================
-- WORKFLOW VERSIONS (immutable snapshots)
-- =========================================

CREATE TABLE IF NOT EXISTS workflow_versions (
    id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    workflow_id     UUID NOT NULL REFERENCES workflows(id) ON DELETE CASCADE,
    version_number  INTEGER NOT NULL,
    snapshot        JSONB NOT NULL,
    created_at      TIMESTAMPTZ NOT NULL DEFAULT NOW(),

    UNIQUE (workflow_id, version_number)
);

CREATE INDEX IF NOT EXISTS idx_workflow_versions_workflow
    ON workflow_versions(workflow_id, version_number DESC);

COMMENT ON TABLE workflow_versions IS 'Immutable snapshots of workflow definitions. Active instances run against a pinned version.';
COMMENT ON COLUMN workflow_versions.snapshot IS 'Full JSON: definition + stages + persona tool grants at publish time.';


-- =========================================
-- WORKFLOW ASSIGNMENTS
-- =========================================

CREATE TABLE IF NOT EXISTS workflow_assignments (
    id           UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    channel_id   UUID NOT NULL REFERENCES channels(id) ON DELETE CASCADE,
    stage        INTEGER NOT NULL,
    team_id      UUID NOT NULL REFERENCES teams(id) ON DELETE CASCADE,
    assigned_to  UUID REFERENCES users(id) ON DELETE SET NULL,
    status       TEXT NOT NULL DEFAULT 'unassigned'
                     CHECK (status IN ('unassigned', 'claimed', 'completed')),
    review_comments JSONB NOT NULL DEFAULT '[]',
    created_at   TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    claimed_at   TIMESTAMPTZ,
    completed_at TIMESTAMPTZ
);

CREATE INDEX IF NOT EXISTS idx_workflow_assignments_channel
    ON workflow_assignments(channel_id, stage);
CREATE INDEX IF NOT EXISTS idx_workflow_assignments_team_status
    ON workflow_assignments(team_id, status) WHERE status = 'unassigned';
CREATE INDEX IF NOT EXISTS idx_workflow_assignments_user
    ON workflow_assignments(assigned_to) WHERE assigned_to IS NOT NULL;

COMMENT ON TABLE workflow_assignments IS 'Queue entries for human review stages in workflows.';
COMMENT ON COLUMN workflow_assignments.status IS 'unassigned=waiting, claimed=being worked, completed=done';


-- =========================================
-- DEFERRED FK: channels.workflow_id → workflows
-- =========================================

DO $$ BEGIN
    IF NOT EXISTS (
        SELECT 1 FROM pg_constraint WHERE conname = 'fk_channels_workflow'
    ) THEN
        ALTER TABLE channels ADD CONSTRAINT fk_channels_workflow
            FOREIGN KEY (workflow_id) REFERENCES workflows(id) ON DELETE SET NULL;
    END IF;
END $$;
