-- Migration 000: Migration Tracking System
-- This MUST be the first migration to run
-- Creates the infrastructure for tracking migration state

-- =============================================
-- Migration Tracking Infrastructure
-- =============================================

-- Create schema_migrations table to track applied migrations
CREATE TABLE IF NOT EXISTS schema_migrations (
  id SERIAL PRIMARY KEY,
  version VARCHAR(255) NOT NULL UNIQUE,
  filename VARCHAR(500) NOT NULL,
  checksum VARCHAR(64), -- SHA-256 of migration content
  applied_at TIMESTAMP DEFAULT NOW(),
  execution_time_ms INTEGER,
  success BOOLEAN DEFAULT true,
  error_message TEXT,
  rollback_sql TEXT, -- Optional rollback instructions
  created_by VARCHAR(100) DEFAULT 'system'
);

-- Create index for fast lookups
CREATE INDEX IF NOT EXISTS idx_schema_migrations_version ON schema_migrations(version);
CREATE INDEX IF NOT EXISTS idx_schema_migrations_applied_at ON schema_migrations(applied_at);
CREATE INDEX IF NOT EXISTS idx_schema_migrations_success ON schema_migrations(success);

-- Create migration_locks table to prevent concurrent migrations
CREATE TABLE IF NOT EXISTS migration_locks (
  id INTEGER PRIMARY KEY DEFAULT 1,
  locked_at TIMESTAMP DEFAULT NOW(),
  locked_by VARCHAR(100) DEFAULT 'system',
  process_id VARCHAR(100),
  CONSTRAINT single_lock CHECK (id = 1)
);

-- =============================================
-- Migration Helper Functions
-- =============================================

-- Function to check if migration has been applied
CREATE OR REPLACE FUNCTION migration_applied(migration_version VARCHAR(255))
RETURNS BOOLEAN AS $$
BEGIN
  RETURN EXISTS (
    SELECT 1 FROM schema_migrations 
    WHERE version = migration_version AND success = true
  );
END;
$$ LANGUAGE plpgsql;

-- Function to record migration execution
CREATE OR REPLACE FUNCTION record_migration(
  migration_version VARCHAR(255),
  migration_filename VARCHAR(500),
  migration_checksum VARCHAR(64) DEFAULT NULL,
  execution_time INTEGER DEFAULT NULL,
  migration_success BOOLEAN DEFAULT true,
  error_msg TEXT DEFAULT NULL
)
RETURNS VOID AS $$
BEGIN
  INSERT INTO schema_migrations (
    version, filename, checksum, execution_time_ms, success, error_message
  ) VALUES (
    migration_version, migration_filename, migration_checksum, 
    execution_time, migration_success, error_msg
  )
  ON CONFLICT (version) DO UPDATE SET
    applied_at = NOW(),
    execution_time_ms = EXCLUDED.execution_time_ms,
    success = EXCLUDED.success,
    error_message = EXCLUDED.error_message;
END;
$$ LANGUAGE plpgsql;

-- Function to acquire migration lock
CREATE OR REPLACE FUNCTION acquire_migration_lock(process_identifier VARCHAR(100))
RETURNS BOOLEAN AS $$
BEGIN
  -- Try to acquire lock
  INSERT INTO migration_locks (locked_by, process_id)
  VALUES ('system', process_identifier)
  ON CONFLICT (id) DO NOTHING;
  
  -- Check if we got the lock
  RETURN EXISTS (
    SELECT 1 FROM migration_locks 
    WHERE process_id = process_identifier
  );
END;
$$ LANGUAGE plpgsql;

-- Function to release migration lock
CREATE OR REPLACE FUNCTION release_migration_lock(process_identifier VARCHAR(100))
RETURNS VOID AS $$
BEGIN
  DELETE FROM migration_locks WHERE process_id = process_identifier;
END;
$$ LANGUAGE plpgsql;

-- =============================================
-- Database Metadata Functions
-- =============================================

-- Function to get current schema version
CREATE OR REPLACE FUNCTION get_current_schema_version()
RETURNS VARCHAR(255) AS $$
BEGIN
  RETURN (
    SELECT version 
    FROM schema_migrations 
    WHERE success = true 
    ORDER BY applied_at DESC 
    LIMIT 1
  );
END;
$$ LANGUAGE plpgsql;

-- Function to get migration history
CREATE OR REPLACE FUNCTION get_migration_history()
RETURNS TABLE (
  version VARCHAR(255),
  filename VARCHAR(500),
  applied_at TIMESTAMP,
  execution_time_ms INTEGER,
  success BOOLEAN
) AS $$
BEGIN
  RETURN QUERY
  SELECT 
    sm.version,
    sm.filename,
    sm.applied_at,
    sm.execution_time_ms,
    sm.success
  FROM schema_migrations sm
  ORDER BY sm.applied_at DESC;
END;
$$ LANGUAGE plpgsql;

-- =============================================
-- Initial Migration Record
-- =============================================

-- Record this migration as applied
SELECT record_migration('000', '000_migration_tracking_system.sql', NULL, NULL, true, NULL);

-- Display current status
DO $$
BEGIN
  RAISE NOTICE '✅ Migration tracking system initialized';
  RAISE NOTICE 'Current schema version: %', get_current_schema_version();
END $$;
