-- Migration 024: Backup System
-- Adds tables for automated backup/restore with offsite upload and notifications

-- Backup Jobs Table
CREATE TABLE IF NOT EXISTS backup_jobs (
    id SERIAL PRIMARY KEY,
    job_type VARCHAR(20) NOT NULL CHECK (job_type IN ('database', 'files', 'full')),
    status VARCHAR(20) NOT NULL DEFAULT 'pending' CHECK (status IN ('pending', 'running', 'completed', 'failed')),
    backup_format VARCHAR(10) NOT NULL CHECK (backup_format IN ('dump', 'sql', 'tar.gz')),
    file_path VARCHAR(500),
    file_size_bytes BIGINT,
    checksum_sha256 VARCHAR(64),
    is_monthly BOOLEAN DEFAULT FALSE,
    includes_uploads BOOLEAN DEFAULT FALSE,
    includes_logs BOOLEAN DEFAULT FALSE,
    includes_data BOOLEAN DEFAULT FALSE,
    started_at TIMESTAMP,
    completed_at TIMESTAMP,
    error_message TEXT,
    retention_until DATE,
    offsite_uploaded_at TIMESTAMP,
    offsite_retry_count INTEGER DEFAULT 0,
    notification_sent BOOLEAN DEFAULT FALSE,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- Indexes for backup_jobs
CREATE INDEX idx_backup_jobs_status ON backup_jobs(status);
CREATE INDEX idx_backup_jobs_created ON backup_jobs(created_at DESC);
CREATE INDEX idx_backup_jobs_type ON backup_jobs(job_type);
CREATE INDEX idx_backup_jobs_is_monthly ON backup_jobs(is_monthly) WHERE is_monthly = TRUE;
CREATE INDEX idx_backup_jobs_retention ON backup_jobs(retention_until) WHERE retention_until IS NOT NULL;
CREATE INDEX idx_backup_jobs_offsite_pending ON backup_jobs(offsite_uploaded_at) WHERE offsite_uploaded_at IS NULL AND status = 'completed';

-- System Status Table (for maintenance mode)
CREATE TABLE IF NOT EXISTS system_status (
    id SERIAL PRIMARY KEY,
    maintenance_mode BOOLEAN DEFAULT FALSE,
    maintenance_message TEXT DEFAULT 'System under vedligeholdelse',
    maintenance_eta_minutes INTEGER,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- Insert default system status
INSERT INTO system_status (maintenance_mode, maintenance_message, maintenance_eta_minutes)
VALUES (FALSE, 'System under vedligeholdelse', NULL)
ON CONFLICT DO NOTHING;

-- Backup Notifications Table
CREATE TABLE IF NOT EXISTS backup_notifications (
    id SERIAL PRIMARY KEY,
    backup_job_id INTEGER REFERENCES backup_jobs(id) ON DELETE SET NULL,
    event_type VARCHAR(30) NOT NULL CHECK (event_type IN ('backup_failed', 'offsite_failed', 'offsite_retry', 'storage_low', 'restore_started', 'backup_success')),
    message TEXT NOT NULL,
    mattermost_payload JSONB,
    sent_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    acknowledged BOOLEAN DEFAULT FALSE,
    acknowledged_at TIMESTAMP
);

-- Indexes for backup_notifications
CREATE INDEX idx_backup_notifications_event ON backup_notifications(event_type);
CREATE INDEX idx_backup_notifications_sent ON backup_notifications(sent_at DESC);
CREATE INDEX idx_backup_notifications_unacked ON backup_notifications(acknowledged) WHERE acknowledged = FALSE;
CREATE INDEX idx_backup_notifications_job ON backup_notifications(backup_job_id) WHERE backup_job_id IS NOT NULL;

-- Trigger to update updated_at on backup_jobs
CREATE OR REPLACE FUNCTION update_backup_jobs_timestamp()
RETURNS TRIGGER AS $$
BEGIN
    NEW.updated_at = CURRENT_TIMESTAMP;
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER backup_jobs_update_timestamp
    BEFORE UPDATE ON backup_jobs
    FOR EACH ROW
    EXECUTE FUNCTION update_backup_jobs_timestamp();

-- Comments for documentation
COMMENT ON TABLE backup_jobs IS 'Tracks all backup operations (database, files, full) with retention and offsite upload status';
COMMENT ON TABLE system_status IS 'Global system maintenance mode flag for restore operations';
COMMENT ON TABLE backup_notifications IS 'Notification log for Mattermost alerts on backup events';

COMMENT ON COLUMN backup_jobs.job_type IS 'Type of backup: database (pg_dump), files (tar.gz), or full (both)';
COMMENT ON COLUMN backup_jobs.backup_format IS 'Format: dump (compressed), sql (plain text), or tar.gz (files archive)';
COMMENT ON COLUMN backup_jobs.is_monthly IS 'TRUE for monthly backups kept for 12 months, FALSE for daily 30-day retention';
COMMENT ON COLUMN backup_jobs.offsite_retry_count IS 'Number of times offsite upload has been retried (max 3)';
COMMENT ON COLUMN system_status.maintenance_eta_minutes IS 'Estimated time in minutes until maintenance is complete';
