import { QueryInterface, DataTypes } from 'sequelize';

/**
 * Migration: Create users table
 * 
 * Purpose: Create the main users table with all fields including RBAC and SSO fields
 * 
 * This must run FIRST before other tables that reference users
 * 
 * Includes:
 * - Basic user information (email, name, etc.)
 * - SSO/Okta fields (manager, job_title, etc.)
 * - RBAC role system (USER, MANAGEMENT, ADMIN)
 * - Location and AD group information
 * 
 * Created: 2025-11-12 (Updated for fresh setup)
 */
export async function up(queryInterface: QueryInterface): Promise<void> {
  console.log('📋 Creating users table with RBAC and extended SSO fields...');
  
  try {
    // Step 1: Create ENUM type for roles
    console.log('   ✓ Creating user_role_enum...');
    await queryInterface.sequelize.query(`
      CREATE TYPE user_role_enum AS ENUM ('USER', 'MANAGEMENT', 'ADMIN');
    `);
    
    // Step 2: Create users table
    console.log('   ✓ Creating users table...');
    await queryInterface.createTable('users', {
      user_id: {
        type: DataTypes.UUID,
        primaryKey: true,
        defaultValue: DataTypes.UUIDV4,
        field: 'user_id',
        comment: 'Primary key - UUID'
      },
      employee_id: {
        type: DataTypes.STRING(50),
        allowNull: true,
        field: 'employee_id',
        comment: 'HR System Employee ID (optional) - some users may not have'
      },
      okta_sub: {
        type: DataTypes.STRING(100),
        allowNull: false,
        unique: true,
        field: 'okta_sub',
        comment: 'Okta user subject identifier - unique identifier from SSO'
      },
      email: {
        type: DataTypes.STRING(255),
        allowNull: false,
        unique: true,
        field: 'email',
        comment: 'Primary email address - unique and required'
      },
      first_name: {
        type: DataTypes.STRING(100),
        allowNull: true,
        defaultValue: '',
        field: 'first_name',
        comment: 'First name from SSO (optional)'
      },
      last_name: {
        type: DataTypes.STRING(100),
        allowNull: true,
        defaultValue: '',
        field: 'last_name',
        comment: 'Last name from SSO (optional)'
      },
      display_name: {
        type: DataTypes.STRING(200),
        allowNull: true,
        defaultValue: '',
        field: 'display_name',
        comment: 'Full display name for UI'
      },
      department: {
        type: DataTypes.STRING(100),
        allowNull: true,
        comment: 'Department/Division from SSO'
      },
      designation: {
        type: DataTypes.STRING(100),
        allowNull: true,
        comment: 'Job designation/position'
      },
      phone: {
        type: DataTypes.STRING(20),
        allowNull: true,
        comment: 'Office phone number'
      },
      
      // ============ Extended SSO/Okta Fields ============
      manager: {
        type: DataTypes.STRING(200),
        allowNull: true,
        comment: 'Reporting manager name from SSO/AD'
      },
      second_email: {
        type: DataTypes.STRING(255),
        allowNull: true,
        field: 'second_email',
        comment: 'Alternate email address from SSO'
      },
      job_title: {
        type: DataTypes.TEXT,
        allowNull: true,
        field: 'job_title',
        comment: 'Detailed job title/description from SSO'
      },
      employee_number: {
        type: DataTypes.STRING(50),
        allowNull: true,
        field: 'employee_number',
        comment: 'HR system employee number from SSO (e.g., "00020330")'
      },
      postal_address: {
        type: DataTypes.STRING(500),
        allowNull: true,
        field: 'postal_address',
        comment: 'Work location/office address from SSO'
      },
      mobile_phone: {
        type: DataTypes.STRING(20),
        allowNull: true,
        field: 'mobile_phone',
        comment: 'Mobile contact number from SSO'
      },
      ad_groups: {
        type: DataTypes.JSONB,
        allowNull: true,
        field: 'ad_groups',
        comment: 'Active Directory group memberships from SSO (memberOf array)'
      },
      
      // ============ System Fields ============
      location: {
        type: DataTypes.JSONB,
        allowNull: true,
        comment: 'JSON object: {city, state, country, office, timezone}'
      },
      is_active: {
        type: DataTypes.BOOLEAN,
        defaultValue: true,
        field: 'is_active',
        comment: 'Account status - true=active, false=disabled'
      },
      role: {
        type: DataTypes.ENUM('USER', 'MANAGEMENT', 'ADMIN'),
        allowNull: false,
        defaultValue: 'USER',
        comment: 'RBAC role: USER (default), MANAGEMENT (read all), ADMIN (full access)'
      },
      last_login: {
        type: DataTypes.DATE,
        allowNull: true,
        field: 'last_login',
        comment: 'Last successful login timestamp'
      },
      created_at: {
        type: DataTypes.DATE,
        allowNull: false,
        defaultValue: DataTypes.NOW,
        field: 'created_at'
      },
      updated_at: {
        type: DataTypes.DATE,
        allowNull: false,
        defaultValue: DataTypes.NOW,
        field: 'updated_at'
      }
    });

    // Step 3: Create indexes
    console.log('   ✓ Creating indexes...');
    
    await queryInterface.addIndex('users', ['email'], {
      name: 'users_email_idx',
      unique: true
    });

    await queryInterface.addIndex('users', ['okta_sub'], {
      name: 'users_okta_sub_idx',
      unique: true
    });

    await queryInterface.addIndex('users', ['employee_id'], {
      name: 'users_employee_id_idx'
    });

    await queryInterface.addIndex('users', ['department'], {
      name: 'idx_users_department'
    });

    await queryInterface.addIndex('users', ['is_active'], {
      name: 'idx_users_is_active'
    });

    await queryInterface.addIndex('users', ['role'], {
      name: 'idx_users_role'
    });

    await queryInterface.addIndex('users', ['manager'], {
      name: 'idx_users_manager'
    });

    await queryInterface.addIndex('users', ['postal_address'], {
      name: 'idx_users_postal_address'
    });

    // GIN indexes for JSONB fields
    await queryInterface.sequelize.query(`
      CREATE INDEX idx_users_location ON users USING gin(location jsonb_path_ops);
      CREATE INDEX idx_users_ad_groups ON users USING gin(ad_groups);
    `);

    console.log('✅ Users table created successfully with all indexes!');
  } catch (error) {
    console.error('❌ Failed to create users table:', error);
    throw error;
  }
}

export async function down(queryInterface: QueryInterface): Promise<void> {
  console.log('📋 Dropping users table...');
  
  await queryInterface.dropTable('users');
  
  // Drop ENUM type
  await queryInterface.sequelize.query(`
    DROP TYPE IF EXISTS user_role_enum;
  `);
  
  console.log('✅ Users table dropped!');
}
