-- Migration 1002: Asset-first subscriptions, billing controls, and price change tracking
-- Adds fields and tables needed for asset-linked subscriptions and flexible billing.

ALTER TABLE sag_subscriptions
ADD COLUMN IF NOT EXISTS billing_direction VARCHAR(20) NOT NULL DEFAULT 'forward'
    CHECK (billing_direction IN ('forward', 'backward')),
ADD COLUMN IF NOT EXISTS advance_months INTEGER NOT NULL DEFAULT 1
    CHECK (advance_months >= 1 AND advance_months <= 24),
ADD COLUMN IF NOT EXISTS first_full_period_start DATE,
ADD COLUMN IF NOT EXISTS binding_months INTEGER NOT NULL DEFAULT 0
    CHECK (binding_months >= 0),
ADD COLUMN IF NOT EXISTS binding_start_date DATE,
ADD COLUMN IF NOT EXISTS binding_end_date DATE,
ADD COLUMN IF NOT EXISTS binding_group_key VARCHAR(80),
ADD COLUMN IF NOT EXISTS billing_blocked BOOLEAN NOT NULL DEFAULT false,
ADD COLUMN IF NOT EXISTS billing_block_reason TEXT,
ADD COLUMN IF NOT EXISTS invoice_merge_key VARCHAR(120),
ADD COLUMN IF NOT EXISTS price_change_case_id INTEGER REFERENCES sag_sager(id),
ADD COLUMN IF NOT EXISTS renewal_case_id INTEGER REFERENCES sag_sager(id);

CREATE INDEX IF NOT EXISTS idx_sag_subscriptions_billing_direction ON sag_subscriptions(billing_direction);
CREATE INDEX IF NOT EXISTS idx_sag_subscriptions_billing_blocked ON sag_subscriptions(billing_blocked) WHERE billing_blocked = true;
CREATE INDEX IF NOT EXISTS idx_sag_subscriptions_binding_end_date ON sag_subscriptions(binding_end_date) WHERE binding_end_date IS NOT NULL;
CREATE INDEX IF NOT EXISTS idx_sag_subscriptions_invoice_merge_key ON sag_subscriptions(invoice_merge_key);

ALTER TABLE sag_subscription_items
ADD COLUMN IF NOT EXISTS asset_id INTEGER REFERENCES hardware_assets(id) ON DELETE RESTRICT,
ADD COLUMN IF NOT EXISTS period_from DATE,
ADD COLUMN IF NOT EXISTS period_to DATE,
ADD COLUMN IF NOT EXISTS requires_serial_number BOOLEAN NOT NULL DEFAULT false,
ADD COLUMN IF NOT EXISTS serial_number VARCHAR(100),
ADD COLUMN IF NOT EXISTS billing_blocked BOOLEAN NOT NULL DEFAULT false,
ADD COLUMN IF NOT EXISTS billing_block_reason TEXT;

CREATE INDEX IF NOT EXISTS idx_sag_subscription_items_asset_id ON sag_subscription_items(asset_id);
CREATE INDEX IF NOT EXISTS idx_sag_subscription_items_blocked ON sag_subscription_items(billing_blocked) WHERE billing_blocked = true;

CREATE TABLE IF NOT EXISTS subscription_asset_bindings (
    id SERIAL PRIMARY KEY,
    subscription_id INTEGER NOT NULL REFERENCES sag_subscriptions(id) ON DELETE CASCADE,
    asset_id INTEGER NOT NULL REFERENCES hardware_assets(id) ON DELETE RESTRICT,
    shared_binding_key VARCHAR(80),
    binding_months INTEGER NOT NULL DEFAULT 0 CHECK (binding_months >= 0),
    start_date DATE NOT NULL,
    end_date DATE,
    notice_period_days INTEGER NOT NULL DEFAULT 30 CHECK (notice_period_days >= 0),
    status VARCHAR(20) NOT NULL DEFAULT 'active' CHECK (status IN ('active', 'ended', 'cancelled')),
    sag_id INTEGER REFERENCES sag_sager(id),
    created_by_user_id INTEGER REFERENCES users(user_id),
    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    deleted_at TIMESTAMP,
    UNIQUE (subscription_id, asset_id, start_date)
);

CREATE INDEX IF NOT EXISTS idx_subscription_asset_bindings_subscription ON subscription_asset_bindings(subscription_id);
CREATE INDEX IF NOT EXISTS idx_subscription_asset_bindings_asset ON subscription_asset_bindings(asset_id);
CREATE INDEX IF NOT EXISTS idx_subscription_asset_bindings_end_date ON subscription_asset_bindings(end_date);

CREATE TRIGGER trigger_subscription_asset_bindings_updated_at
BEFORE UPDATE ON subscription_asset_bindings
FOR EACH ROW
EXECUTE FUNCTION update_updated_at_column();

CREATE TABLE IF NOT EXISTS subscription_price_changes (
    id SERIAL PRIMARY KEY,
    subscription_id INTEGER NOT NULL REFERENCES sag_subscriptions(id) ON DELETE CASCADE,
    subscription_item_id INTEGER REFERENCES sag_subscription_items(id) ON DELETE SET NULL,
    sag_id INTEGER NOT NULL REFERENCES sag_sager(id) ON DELETE RESTRICT,
    change_scope VARCHAR(20) NOT NULL DEFAULT 'subscription' CHECK (change_scope IN ('subscription', 'item')),
    old_unit_price DECIMAL(10,2),
    new_unit_price DECIMAL(10,2) NOT NULL CHECK (new_unit_price >= 0),
    effective_date DATE NOT NULL,
    approval_status VARCHAR(20) NOT NULL DEFAULT 'pending' CHECK (approval_status IN ('pending', 'approved', 'rejected', 'applied')),
    reason TEXT,
    approved_by_user_id INTEGER REFERENCES users(user_id),
    approved_at TIMESTAMP,
    created_by_user_id INTEGER REFERENCES users(user_id),
    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    deleted_at TIMESTAMP
);

CREATE INDEX IF NOT EXISTS idx_subscription_price_changes_subscription ON subscription_price_changes(subscription_id);
CREATE INDEX IF NOT EXISTS idx_subscription_price_changes_effective_date ON subscription_price_changes(effective_date);
CREATE INDEX IF NOT EXISTS idx_subscription_price_changes_status ON subscription_price_changes(approval_status);

CREATE TRIGGER trigger_subscription_price_changes_updated_at
BEFORE UPDATE ON subscription_price_changes
FOR EACH ROW
EXECUTE FUNCTION update_updated_at_column();

ALTER TABLE ordre_drafts
ADD COLUMN IF NOT EXISTS coverage_start DATE,
ADD COLUMN IF NOT EXISTS coverage_end DATE,
ADD COLUMN IF NOT EXISTS billing_direction VARCHAR(20)
    CHECK (billing_direction IN ('forward', 'backward')),
ADD COLUMN IF NOT EXISTS source_subscription_ids INTEGER[] NOT NULL DEFAULT '{}',
ADD COLUMN IF NOT EXISTS invoice_aggregate_key VARCHAR(120),
ADD COLUMN IF NOT EXISTS sync_status VARCHAR(20) NOT NULL DEFAULT 'pending'
    CHECK (sync_status IN ('pending', 'exported', 'failed', 'posted', 'paid')),
ADD COLUMN IF NOT EXISTS economic_order_number VARCHAR(80),
ADD COLUMN IF NOT EXISTS economic_invoice_number VARCHAR(80),
ADD COLUMN IF NOT EXISTS last_sync_at TIMESTAMP;

CREATE INDEX IF NOT EXISTS idx_ordre_drafts_sync_status ON ordre_drafts(sync_status);
CREATE INDEX IF NOT EXISTS idx_ordre_drafts_invoice_aggregate_key ON ordre_drafts(invoice_aggregate_key);

ALTER TABLE products
ADD COLUMN IF NOT EXISTS serial_number_required BOOLEAN NOT NULL DEFAULT false,
ADD COLUMN IF NOT EXISTS asset_required BOOLEAN NOT NULL DEFAULT false,
ADD COLUMN IF NOT EXISTS rental_asset_enabled BOOLEAN NOT NULL DEFAULT false;

COMMENT ON COLUMN products.serial_number_required IS 'If true, subscription line billing requires serial number data.';
COMMENT ON COLUMN products.asset_required IS 'If true, subscription line billing requires linked hardware asset.';
COMMENT ON COLUMN products.rental_asset_enabled IS 'If true, product is eligible for asset-first rental subscription flows.';
