CREATE TABLE enterprise_site_connections (
    id                    BIGSERIAL PRIMARY KEY,
    tenant_id             BIGINT NOT NULL REFERENCES tenants(id),
    workspace_id          BIGINT NOT NULL REFERENCES workspaces(id),
    created_by_user_id    BIGINT NOT NULL REFERENCES users(id),
    name                  VARCHAR(160) NOT NULL,
    site_url              TEXT NOT NULL,
    cms_type              VARCHAR(32) NOT NULL,
    auth_type             VARCHAR(32) NOT NULL DEFAULT 'native_api',
    appid                 VARCHAR(160) NOT NULL,
    credential_ciphertext TEXT NOT NULL,
    default_acode         VARCHAR(32),
    default_mcode         VARCHAR(32),
    default_scode         VARCHAR(64),
    status                VARCHAR(20) NOT NULL DEFAULT 'draft',
    plugin_version        VARCHAR(40),
    site_name             VARCHAR(160),
    last_ping_at          TIMESTAMPTZ,
    last_sync_at          TIMESTAMPTZ,
    last_publish_at       TIMESTAMPTZ,
    last_error            TEXT,
    created_at            TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at            TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    deleted_at            TIMESTAMPTZ,
    CONSTRAINT ck_enterprise_site_connections_cms_type
        CHECK (cms_type IN ('pbootcms', 'wordpress', 'dedecms', 'phpcms')),
    CONSTRAINT ck_enterprise_site_connections_status
        CHECK (status IN ('draft', 'connected', 'error', 'disabled'))
);

CREATE UNIQUE INDEX uk_enterprise_site_connections_active_site
    ON enterprise_site_connections (tenant_id, workspace_id, lower(site_url), cms_type)
    WHERE deleted_at IS NULL;

CREATE INDEX idx_enterprise_site_connections_tenant_workspace
    ON enterprise_site_connections (tenant_id, workspace_id, status, created_at DESC)
    WHERE deleted_at IS NULL;

CREATE TABLE enterprise_site_categories (
    id               BIGSERIAL PRIMARY KEY,
    tenant_id        BIGINT NOT NULL REFERENCES tenants(id),
    workspace_id     BIGINT NOT NULL REFERENCES workspaces(id),
    connection_id    BIGINT NOT NULL REFERENCES enterprise_site_connections(id) ON DELETE CASCADE,
    remote_id        VARCHAR(128) NOT NULL,
    parent_remote_id VARCHAR(128),
    name             VARCHAR(160) NOT NULL,
    slug             VARCHAR(160),
    raw_payload_json JSONB,
    synced_at        TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    created_at       TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at       TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    CONSTRAINT uk_enterprise_site_categories_remote
        UNIQUE (connection_id, remote_id)
);

CREATE INDEX idx_enterprise_site_categories_connection
    ON enterprise_site_categories (connection_id, remote_id);

ALTER TABLE publish_records
    ALTER COLUMN platform_account_id DROP NOT NULL;

ALTER TABLE publish_records
    ADD COLUMN target_type VARCHAR(32) NOT NULL DEFAULT 'platform_account',
    ADD COLUMN target_connection_id BIGINT REFERENCES enterprise_site_connections(id);

ALTER TABLE publish_records
    ADD CONSTRAINT ck_publish_records_target_type
        CHECK (target_type IN ('platform_account', 'enterprise_site'));

ALTER TABLE publish_records
    ADD CONSTRAINT ck_publish_records_target_ref
        CHECK (
            (target_type = 'platform_account' AND platform_account_id IS NOT NULL AND target_connection_id IS NULL)
            OR
            (target_type = 'enterprise_site' AND platform_account_id IS NULL AND target_connection_id IS NOT NULL)
        );

CREATE UNIQUE INDEX uk_publish_records_batch_enterprise_site
    ON publish_records (publish_batch_id, target_connection_id)
    WHERE target_type = 'enterprise_site';

CREATE INDEX idx_publish_records_enterprise_site_active
    ON publish_records (tenant_id, article_id, target_connection_id, updated_at DESC, id DESC)
    WHERE target_type = 'enterprise_site';

INSERT INTO media_platforms (platform_id, name, category, short_name, accent_color, login_url, logo_url, status, sort_order)
VALUES ('pbootcms', 'PBootCMS', 'enterprise', 'P', '#1d4ed8', NULL, NULL, 'active', 900)
ON CONFLICT (platform_id)
DO UPDATE SET
    name = EXCLUDED.name,
    category = EXCLUDED.category,
    short_name = EXCLUDED.short_name,
    accent_color = EXCLUDED.accent_color,
    status = EXCLUDED.status,
    sort_order = EXCLUDED.sort_order,
    updated_at = NOW();
