require('dotenv').config({ path: '.env' });
require('dotenv').config({ path: '.env.local' });

const { globSync } = require('glob');
const path = require('path');
const mongoose = require('mongoose');
const { generate: uniqueId } = require('shortid');
const { seedTenantAccessControl } = require('../services/platform/defaultAccessControl');

const adminEmail = String(process.env.ADMIN_EMAIL || process.env.SETUP_ADMIN_EMAIL || '')
  .trim()
  .toLowerCase();
const adminPassword = process.env.ADMIN_PASSWORD || process.env.SETUP_ADMIN_PASSWORD;
const adminName = process.env.ADMIN_NAME || process.env.SETUP_ADMIN_NAME || 'System';
const adminSurname = process.env.ADMIN_SURNAME || process.env.SETUP_ADMIN_SURNAME || 'Administrator';
const tenantName = process.env.ADMIN_TENANT_NAME || process.env.SETUP_TENANT_NAME || 'Ascend Systems';
const tenantSlug = String(process.env.ADMIN_TENANT_SLUG || process.env.SETUP_TENANT_SLUG || 'ascend-systems')
  .trim()
  .toLowerCase();

const registerModels = () => {
  const modelsFiles = globSync('./src/models/**/*.js');
  for (const filePath of modelsFiles) {
    require(path.resolve(filePath));
  }
};

const run = async () => {
  if (!process.env.DATABASE) {
    throw new Error('DATABASE is required');
  }
  if (!adminEmail || !adminPassword) {
    throw new Error('ADMIN_EMAIL and ADMIN_PASSWORD are required');
  }

  await mongoose.connect(process.env.DATABASE);
  registerModels();

  const Tenant = mongoose.model('Tenant');
  const Admin = mongoose.model('Admin');
  const AdminPassword = mongoose.model('AdminPassword');

  const tenant = await Tenant.findOneAndUpdate(
    { slug: tenantSlug },
    {
      $set: {
        name: tenantName,
        slug: tenantSlug,
        status: 'active',
        removed: false,
      },
    },
    { upsert: true, new: true, setDefaultsOnInsert: true }
  );

  const { roles } = await seedTenantAccessControl({ tenantId: tenant._id });
  const adminRole = roles.find((role) => role.key === 'admin');

  const admin = await Admin.findOneAndUpdate(
    { email: adminEmail },
    {
      $set: {
        email: adminEmail,
        name: adminName,
        surname: adminSurname,
        enabled: true,
        removed: false,
        tenant: tenant._id,
        role: 'owner',
        permissions: ['*'],
        roleRefs: adminRole ? [adminRole._id] : [],
      },
    },
    { upsert: true, new: true, setDefaultsOnInsert: true }
  );

  const passwordRecord = new AdminPassword();
  const salt = uniqueId();
  const passwordHash = passwordRecord.generateHash(salt, adminPassword);

  await AdminPassword.findOneAndUpdate(
    { user: admin._id },
    {
      $set: {
        password: passwordHash,
        salt,
        emailVerified: true,
        removed: false,
        authType: 'email',
      },
      $setOnInsert: {
        user: admin._id,
      },
    },
    { upsert: true, new: true, setDefaultsOnInsert: true }
  );

  console.log(`Admin login provisioned for ${admin.email}`);
  console.log(`Tenant: ${tenant.name} (${tenant.slug})`);
};

run()
  .catch((error) => {
    console.error(error);
    process.exitCode = 1;
  })
  .finally(async () => {
    await mongoose.disconnect();
  });
