/**
 * AdminJS setup — ESM modules loaded via dynamic import.
 * Exports async function that mounts admin panel on the Express app.
 */

const { Sequelize, DataTypes } = require('sequelize');

// Sequelize connection (reuses same DB as lib/db.js)
const sequelize = new Sequelize(
  process.env.DB_NAME || 'wa_tools',
  process.env.DB_USER || 'wa_tools',
  process.env.DB_PASSWORD || '',
  {
    host: process.env.DB_HOST || 'localhost',
    dialect: 'mariadb',
    logging: false,
  }
);

// Define models
const User = sequelize.define('User', {
  id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true },
  email: { type: DataTypes.STRING(255), allowNull: false, unique: true },
  password_hash: { type: DataTypes.STRING(255), allowNull: false },
  display_name: { type: DataTypes.STRING(100) },
  role: { type: DataTypes.ENUM('user', 'admin'), defaultValue: 'user' },
  is_blocked: { type: DataTypes.BOOLEAN, defaultValue: false },
  created_at: { type: DataTypes.DATE, defaultValue: DataTypes.NOW },
  last_login: { type: DataTypes.DATE },
}, { tableName: 'users', timestamps: false });

const Setting = sequelize.define('Setting', {
  id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true },
  setting_key: { type: DataTypes.STRING(100), allowNull: false, unique: true },
  setting_value: { type: DataTypes.TEXT },
  description: { type: DataTypes.STRING(255) },
  updated_at: { type: DataTypes.DATE },
}, { tableName: 'settings', timestamps: false });

const Category = sequelize.define('Category', {
  id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true },
  slug: { type: DataTypes.STRING(50), allowNull: false, unique: true },
  title: { type: DataTypes.STRING(100), allowNull: false },
  description: { type: DataTypes.STRING(255) },
  icon_svg: { type: DataTypes.TEXT },
  color: { type: DataTypes.STRING(20), defaultValue: '#0054e6' },
  sort_order: { type: DataTypes.INTEGER, defaultValue: 0 },
}, { tableName: 'categories', timestamps: false });

const Tool = sequelize.define('Tool', {
  id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true },
  slug: { type: DataTypes.STRING(50), allowNull: false, unique: true },
  title: { type: DataTypes.STRING(100), allowNull: false },
  description: { type: DataTypes.STRING(255) },
  path: { type: DataTypes.STRING(100), allowNull: false },
  icon_svg: { type: DataTypes.TEXT },
  category_id: { type: DataTypes.INTEGER },
  sort_order: { type: DataTypes.INTEGER, defaultValue: 0 },
  is_enabled: { type: DataTypes.BOOLEAN, defaultValue: true },
}, { tableName: 'tools', timestamps: false });

const ContentBlock = sequelize.define('ContentBlock', {
  id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true },
  block_key: { type: DataTypes.STRING(100), allowNull: false, unique: true },
  title: { type: DataTypes.STRING(255) },
  body: { type: DataTypes.TEXT },
  section: { type: DataTypes.STRING(50) },
  sort_order: { type: DataTypes.INTEGER, defaultValue: 0 },
  is_visible: { type: DataTypes.BOOLEAN, defaultValue: true },
  updated_at: { type: DataTypes.DATE },
}, { tableName: 'content_blocks', timestamps: false });

Tool.belongsTo(Category, { foreignKey: 'category_id' });
Category.hasMany(Tool, { foreignKey: 'category_id' });

/**
 * Mount AdminJS on the Express app at /admin
 */
async function setupAdmin(app) {
  const AdminJS = (await import('adminjs')).default;
  const AdminJSExpress = (await import('@adminjs/express')).default;
  const AdminJSSequelize = (await import('@adminjs/sequelize')).default;

  AdminJS.registerAdapter({
    Resource: AdminJSSequelize.Resource,
    Database: AdminJSSequelize.Database,
  });

  const adminJs = new AdminJS({
    rootPath: '/admin',
    loginPath: '/admin/login',
    logoutPath: '/admin/logout',
    branding: {
      companyName: 'WA Dev Tools',
      logo: false,
      softwareBrothers: false,
    },
    resources: [
      {
        resource: User,
        options: {
          navigation: { name: 'Пользователи', icon: 'User' },
          listProperties: ['id', 'email', 'display_name', 'role', 'is_blocked', 'last_login'],
          editProperties: ['email', 'display_name', 'role', 'is_blocked', 'password', 'password_confirm'],
          showProperties: ['id', 'email', 'display_name', 'role', 'is_blocked', 'created_at', 'last_login'],
          properties: {
            password_hash: { isVisible: false },
            password: {
              type: 'password',
              isVisible: { list: false, show: false, edit: true, filter: false },
              description: 'Оставьте пустым чтобы не менять',
            },
            password_confirm: {
              type: 'password',
              isVisible: { list: false, show: false, edit: true, filter: false },
              description: 'Повторите пароль',
            },
            role: { availableValues: [{ value: 'user', label: 'User' }, { value: 'admin', label: 'Admin' }] },
          },
          actions: {
            edit: {
              before: async (request) => {
                const pw = (request.payload?.password || '').trim();
                const pw2 = (request.payload?.password_confirm || '').trim();
                if (pw) {
                  if (pw2 && pw !== pw2) {
                    request.payload.errors = request.payload.errors || {};
                    request.payload.errors.password_confirm = { message: 'Пароли не совпадают' };
                    return request;
                  }
                  if (pw.length < 6) {
                    request.payload.errors = request.payload.errors || {};
                    request.payload.errors.password = { message: 'Минимум 6 символов' };
                    return request;
                  }
                  const bcrypt = require('bcrypt');
                  request.payload.password_hash = await bcrypt.hash(pw, 10);
                }
                delete request.payload.password;
                delete request.payload.password_confirm;
                return request;
              },
            },
            new: {
              before: async (request) => {
                const pw = (request.payload?.password || '').trim();
                const pw2 = (request.payload?.password_confirm || '').trim();
                if (!pw) {
                  request.payload.errors = request.payload.errors || {};
                  request.payload.errors.password = { message: 'Пароль обязателен' };
                  return request;
                }
                if (pw2 && pw !== pw2) {
                  request.payload.errors = request.payload.errors || {};
                  request.payload.errors.password_confirm = { message: 'Пароли не совпадают' };
                  return request;
                }
                if (pw.length < 6) {
                  request.payload.errors = request.payload.errors || {};
                  request.payload.errors.password = { message: 'Минимум 6 символов' };
                  return request;
                }
                const bcrypt = require('bcrypt');
                request.payload.password_hash = await bcrypt.hash(pw, 10);
                delete request.payload.password;
                delete request.payload.password_confirm;
                return request;
              },
            },
          },
        },
      },
      {
        resource: Category,
        options: {
          navigation: { name: 'Контент', icon: 'Grid' },
          listProperties: ['id', 'slug', 'title', 'color', 'sort_order'],
          sort: { sortBy: 'sort_order', direction: 'asc' },
        },
      },
      {
        resource: Tool,
        options: {
          navigation: { name: 'Контент', icon: 'Grid' },
          listProperties: ['id', 'slug', 'title', 'path', 'category_id', 'is_enabled', 'sort_order'],
          sort: { sortBy: 'sort_order', direction: 'asc' },
          properties: {
            icon_svg: { type: 'textarea' },
          },
        },
      },
      {
        resource: ContentBlock,
        options: {
          navigation: { name: 'Контент', icon: 'Edit' },
          listProperties: ['id', 'block_key', 'title', 'section', 'is_visible', 'sort_order'],
          properties: {
            body: { type: 'richtext' },
          },
        },
      },
      {
        resource: Setting,
        options: {
          navigation: { name: 'Настройки', icon: 'Settings' },
          listProperties: ['id', 'setting_key', 'setting_value', 'description'],
          editProperties: ['setting_value', 'description'],
          properties: {
            setting_key: { isDisabled: true },
          },
        },
      },
    ],
  });

  // Auth: use main site session — admin role required
  const adminRouter = AdminJSExpress.buildRouter(adminJs);

  // Middleware: check main session for admin role before AdminJS
  app.use(adminJs.options.rootPath, (req, res, next) => {
    // Allow only AdminJS's own bundled frontend assets — NOT arbitrary paths ending in .js/.css
    // (a data endpoint ending in such a suffix would otherwise bypass the role check).
    if (req.path.startsWith('/frontend/') && /\.(js|css|png|svg|ico|map|woff2?|ttf)$/.test(req.path)) return next();

    if (req.session && req.session.user && req.session.user.role === 'admin') {
      return next();
    }

    // Not admin — redirect to login with return URL
    req.session.returnTo = '/admin';
    return res.redirect('/auth/login');
  }, adminRouter);

  return adminJs;
}

module.exports = { setupAdmin, sequelize, User, Setting, Category, Tool, ContentBlock };
