const { pool } = require('../config/database');
class Organization {
    constructor(data) {
        this.id = data.id;
        this.name = data.name;
        this.code = data.code;
        this.type = data.type;
        this.description = data.description;
        this.address = data.address;
        this.phone = data.phone;
        this.email = data.email;
        this.website = data.website;
        this.logo = data.logo;
        this.theme = data.theme;
        this.is_active = data.is_active;
        this.created_by = data.created_by;
        this.created_by_name = data.created_by_name;
        this.created_at = data.created_at;
        this.updated_at = data.updated_at;
        // Additional calculated fields
        this.total_units = data.total_units;
        this.total_users = data.total_users;
        // Optional role permissions (may not exist in all DBs)
        this.role_permissions = data.role_permissions;
        // Optional homepage view toggles (may not exist in all DBs)
        this.homepage_view_home = (data.homepage_view_home !== undefined ? data.homepage_view_home : data.view_home);
        this.homepage_view_units = (data.homepage_view_units !== undefined ? data.homepage_view_units : data.view_units);
        this.homepage_view_contacts = (data.homepage_view_contacts !== undefined ? data.homepage_view_contacts : data.view_contacts);
        this.homepage_view_department_grid = (data.homepage_view_department_grid !== undefined ? data.homepage_view_department_grid : data.view_department_grid);
        this.auto_user_create = (data.auto_user_create !== undefined ? data.auto_user_create : data.auto_user_crete);
        this.department_grid = data.department_grid;
        this.required_field_permissions = data.required_field_permissions;
    }
    static async getExistingColumns() {
        if (this._existingColumns)
            return this._existingColumns;
        const sql = 'SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = \'organizations\'';
        const [rows] = await pool.query(sql);
        this._existingColumns = new Set(rows.map(r => r.COLUMN_NAME));
        return this._existingColumns;
    }
    // Create a new organization
    static async create(organizationData) {
        const { name, code, type, description, address, phone, email, website, logo, theme, created_by } = organizationData;
        // Dynamic column inclusion for optional fields
        const existing = await Organization.getExistingColumns();
        const columns = ['name', 'code', 'type', 'description', 'address', 'phone', 'email', 'website', 'logo', 'theme', 'created_by'];
        const values = [name, code || null, type || null, description || null, address || null, phone || null, email || null, website || null, logo || null, theme || null, created_by || null];
        if (existing.has('homepage_view_home') || existing.has('view_home')) {
            columns.push(existing.has('homepage_view_home') ? 'homepage_view_home' : 'view_home');
            values.push(organizationData.homepage_view_home ? 1 : 0);
        }
        if (existing.has('homepage_view_units') || existing.has('view_units')) {
            columns.push(existing.has('homepage_view_units') ? 'homepage_view_units' : 'view_units');
            values.push(organizationData.homepage_view_units ? 1 : 0);
        }
        if (existing.has('homepage_view_contacts') || existing.has('view_contacts')) {
            columns.push(existing.has('homepage_view_contacts') ? 'homepage_view_contacts' : 'view_contacts');
            values.push(organizationData.homepage_view_contacts ? 1 : 0);
        }
        if (existing.has('homepage_view_department_grid') || existing.has('view_department_grid')) {
            columns.push(existing.has('homepage_view_department_grid') ? 'homepage_view_department_grid' : 'view_department_grid');
            values.push(organizationData.homepage_view_department_grid ? 1 : 0);
        }
        // Optional role_permissions column (TEXT/JSON)
        if (existing.has('role_permissions')) {
            columns.push('role_permissions');
            const rp = organizationData.role_permissions;
            if (Array.isArray(rp)) {
                values.push(JSON.stringify(rp));
            }
            else if (rp && typeof rp === 'object') {
                values.push(JSON.stringify(rp));
            }
            else if (typeof rp === 'string') {
                values.push(rp);
            }
            else {
                values.push(null);
            }
        }
        if (existing.has('required_field_permissions')) {
            columns.push('required_field_permissions');
            const rfp = organizationData.required_field_permissions;
            if (Array.isArray(rfp)) {
                values.push(JSON.stringify(rfp));
            }
            else if (rfp && typeof rfp === 'object') {
                values.push(JSON.stringify(rfp));
            }
            else if (typeof rfp === 'string') {
                values.push(rfp);
            }
            else {
                values.push(null);
            }
        }
        if (existing.has('auto_user_create') || existing.has('auto_user_crete')) {
            columns.push(existing.has('auto_user_create') ? 'auto_user_create' : 'auto_user_crete');
            values.push(organizationData.auto_user_create ? 1 : 0);
        }
        if (existing.has('department_grid')) {
            columns.push('department_grid');
            values.push(organizationData.department_grid ? 1 : 0);
        }
        const placeholders = columns.map(() => '?').join(', ');
        const query = `INSERT INTO organizations (${columns.join(', ')}) VALUES (${placeholders})`;
        try {
            const [result] = await pool.execute(query, values);
            return result.insertId;
        }
        catch (error) {
            throw new Error(`Error creating organization: ${error.message}`);
        }
    }
    // Find organization by ID
    static async findById(id) {
        const existing = await Organization.getExistingColumns();
        const extraCols = [];
        if (existing.has('homepage_view_home'))
            extraCols.push('o.homepage_view_home');
        else if (existing.has('view_home'))
            extraCols.push('o.view_home');
        if (existing.has('homepage_view_units'))
            extraCols.push('o.homepage_view_units');
        else if (existing.has('view_units'))
            extraCols.push('o.view_units');
        if (existing.has('homepage_view_contacts'))
            extraCols.push('o.homepage_view_contacts');
        else if (existing.has('view_contacts'))
            extraCols.push('o.view_contacts');
        if (existing.has('role_permissions'))
            extraCols.push('o.role_permissions');
        if (existing.has('required_field_permissions'))
            extraCols.push('o.required_field_permissions');
        if (existing.has('auto_user_create'))
            extraCols.push('o.auto_user_create');
        else if (existing.has('auto_user_crete'))
            extraCols.push('o.auto_user_crete');
        if (existing.has('department_grid'))
            extraCols.push('o.department_grid');
        if (existing.has('homepage_view_department_grid'))
            extraCols.push('o.homepage_view_department_grid');
        else if (existing.has('view_department_grid'))
            extraCols.push('o.view_department_grid');
        const query = `
      SELECT 
        o.*,
        ${extraCols.join(', ') || 'o.id'},
        u.name as created_by_name,
        (SELECT COUNT(*) FROM units WHERE organization_id = o.id) as total_units,
        (SELECT COUNT(*) FROM users WHERE organization_id = o.id) as total_users
      FROM organizations o
      LEFT JOIN users u ON o.created_by = u.id
      WHERE o.id = ?
    `;
        try {
            const [rows] = await pool.execute(query, [id]);
            return rows.length > 0 ? new Organization(rows[0]) : null;
        }
        catch (error) {
            if (error && (error.code === 'ER_NO_SUCH_TABLE' || /Table '.*\.units' doesn't exist/i.test(error.message))) {
                const fallbackQuery = `
          SELECT 
            o.*, 
            ${extraCols.join(', ') || 'o.id'},
            u.name as created_by_name,
            0 as total_units,
            (SELECT COUNT(*) FROM users WHERE organization_id = o.id) as total_users
          FROM organizations o
          LEFT JOIN users u ON o.created_by = u.id
          WHERE o.id = ?
        `;
                const [rows] = await pool.execute(fallbackQuery, [id]);
                return rows.length > 0 ? new Organization(rows[0]) : null;
            }
            throw new Error(`Error finding organization: ${error.message}`);
        }
    }
    // Find all organizations with filtering and pagination
    static async findAll(options = {}) {
        try {
            // Extract and validate options
            const page = parseInt(options.page) || 1;
            const limit = parseInt(options.limit) || 50;
            const search = options.search || '';
            const is_active = options.is_active;
            const type = options.type || '';
            const organizationId = options.organization_id;
            // Ensure valid pagination values
            const validPage = Math.max(1, page);
            const validLimit = Math.max(1, Math.min(100, limit));
            const offset = (validPage - 1) * validLimit;
            // Build WHERE conditions
            const whereConditions = [];
            const countParams = [];
            const queryParams = [];
            // Add search filter
            if (search && search.length > 0) {
                whereConditions.push('(o.name LIKE ? OR o.code LIKE ? OR o.description LIKE ?)');
                const searchTerm = '%' + search + '%';
                countParams.push(searchTerm, searchTerm, searchTerm);
                queryParams.push(searchTerm, searchTerm, searchTerm);
            }
            // Add active status filter
            if (is_active === 'true' || is_active === true || is_active === 1 || is_active === '1') {
                whereConditions.push('o.is_active = 1');
            }
            else if (is_active === 'false' || is_active === false || is_active === 0 || is_active === '0') {
                whereConditions.push('o.is_active = 0');
            }
            // Add type filter
            if (type && type.length > 0) {
                whereConditions.push('o.type = ?');
                countParams.push(type);
                queryParams.push(type);
            }
            // Restrict to a specific organization if provided
            if (organizationId) {
                whereConditions.push('o.id = ?');
                countParams.push(organizationId);
                queryParams.push(organizationId);
            }
            // Build WHERE clause
            const whereSQL = whereConditions.length > 0
                ? 'WHERE ' + whereConditions.join(' AND ')
                : '';
            // Count total records
            const countSQL = 'SELECT COUNT(*) as total FROM organizations o ' + whereSQL;
            const [countResult] = await pool.execute(countSQL, countParams);
            const total = parseInt(countResult[0].total) || 0;
            // Get paginated records
            const existing = await Organization.getExistingColumns();
            const extraCols = [];
            if (existing.has('homepage_view_home'))
                extraCols.push('o.homepage_view_home');
            else if (existing.has('view_home'))
                extraCols.push('o.view_home');
            if (existing.has('homepage_view_units'))
                extraCols.push('o.homepage_view_units');
            else if (existing.has('view_units'))
                extraCols.push('o.view_units');
            if (existing.has('homepage_view_contacts'))
                extraCols.push('o.homepage_view_contacts');
            else if (existing.has('view_contacts'))
                extraCols.push('o.view_contacts');
            if (existing.has('role_permissions'))
                extraCols.push('o.role_permissions');
            if (existing.has('required_field_permissions'))
                extraCols.push('o.required_field_permissions');
            if (existing.has('homepage_view_department_grid'))
                extraCols.push('o.homepage_view_department_grid');
            else if (existing.has('view_department_grid'))
                extraCols.push('o.view_department_grid');
            if (existing.has('auto_user_create'))
                extraCols.push('o.auto_user_create');
            else if (existing.has('auto_user_crete'))
                extraCols.push('o.auto_user_crete');
            if (existing.has('department_grid'))
                extraCols.push('o.department_grid');
            if (existing.has('auto_user_create'))
                extraCols.push('o.auto_user_create');
            else if (existing.has('auto_user_crete'))
                extraCols.push('o.auto_user_crete');
            const dataSQL = 'SELECT o.id, o.name, o.code, o.type, o.description, o.address, ' +
                'o.phone, o.email, o.website, o.logo, o.theme, o.is_active, ' +
                (extraCols.length ? extraCols.join(', ') + ', ' : '') +
                'o.created_by, o.created_at, o.updated_at, u.name as created_by_name ' +
                'FROM organizations o ' +
                'LEFT JOIN users u ON o.created_by = u.id ' +
                whereSQL + ' ' +
                'ORDER BY o.created_at DESC ' +
                'LIMIT ' + validLimit + ' OFFSET ' + offset;
            const [rows] = await pool.query(dataSQL, queryParams);
            // Get counts for each organization
            const organizations = [];
            for (const row of rows) {
                let unitCount = [{ count: 0 }];
                try {
                    const [uc] = await pool.query('SELECT COUNT(*) as count FROM units WHERE organization_id = ?', [row.id]);
                    unitCount = uc;
                }
                catch (e) {
                    if (!(e && (e.code === 'ER_NO_SUCH_TABLE' || /Table '.*\.units' doesn't exist/i.test(e.message)))) {
                        throw e;
                    }
                }
                const [userCount] = await pool.query('SELECT COUNT(*) as count FROM users WHERE organization_id = ?', [row.id]);
                organizations.push(new Organization({
                    ...row,
                    total_units: unitCount[0].count || 0,
                    total_users: userCount[0].count || 0
                }));
            }
            return {
                data: organizations,
                pagination: {
                    page: validPage,
                    limit: validLimit,
                    total,
                    totalPages: Math.ceil(total / validLimit)
                }
            };
        }
        catch (error) {
            console.error('Error in Organization.findAll:', error);
            throw new Error(`Error finding organizations: ${error.message}`);
        }
    }
    // Get organization statistics
    static async getStatistics() {
        const query = `
      SELECT 
        COUNT(*) as total_organizations,
        SUM(CASE WHEN is_active = 1 THEN 1 ELSE 0 END) as active_organizations,
        SUM(CASE WHEN is_active = 0 THEN 1 ELSE 0 END) as inactive_organizations
      FROM organizations
    `;
        try {
            const [rows] = await pool.execute(query);
            return rows[0];
        }
        catch (error) {
            throw new Error(`Error getting organization statistics: ${error.message}`);
        }
    }
    // Update organization
    static async update(id, organizationData) {
        const { name, code, type, description, address, phone, email, website, logo, theme, is_active, homepage_view_home, homepage_view_units, homepage_view_contacts, homepage_view_department_grid, role_permissions, required_field_permissions, auto_user_create, department_grid } = organizationData;
        const updates = [];
        const values = [];
        if (name !== undefined) {
            updates.push('name = ?');
            values.push(name);
        }
        if (code !== undefined) {
            updates.push('code = ?');
            values.push(code);
        }
        if (type !== undefined) {
            updates.push('type = ?');
            values.push(type);
        }
        if (description !== undefined) {
            updates.push('description = ?');
            values.push(description);
        }
        if (address !== undefined) {
            updates.push('address = ?');
            values.push(address);
        }
        if (phone !== undefined) {
            updates.push('phone = ?');
            values.push(phone);
        }
        if (email !== undefined) {
            updates.push('email = ?');
            values.push(email);
        }
        if (website !== undefined) {
            updates.push('website = ?');
            values.push(website);
        }
        if (logo !== undefined) {
            updates.push('logo = ?');
            values.push(logo);
        }
        if (theme !== undefined) {
            updates.push('theme = ?');
            values.push(theme);
        }
        if (is_active !== undefined) {
            updates.push('is_active = ?');
            values.push(is_active ? 1 : 0);
        }
        const existing = await Organization.getExistingColumns();
        if ((existing.has('homepage_view_home') || existing.has('view_home')) && homepage_view_home !== undefined) {
            updates.push((existing.has('homepage_view_home') ? 'homepage_view_home' : 'view_home') + ' = ?');
            values.push(homepage_view_home ? 1 : 0);
        }
        if ((existing.has('homepage_view_units') || existing.has('view_units')) && homepage_view_units !== undefined) {
            updates.push((existing.has('homepage_view_units') ? 'homepage_view_units' : 'view_units') + ' = ?');
            values.push(homepage_view_units ? 1 : 0);
        }
        if ((existing.has('homepage_view_contacts') || existing.has('view_contacts')) && homepage_view_contacts !== undefined) {
            updates.push((existing.has('homepage_view_contacts') ? 'homepage_view_contacts' : 'view_contacts') + ' = ?');
            values.push(homepage_view_contacts ? 1 : 0);
        }
        if ((existing.has('homepage_view_department_grid') || existing.has('view_department_grid')) && homepage_view_department_grid !== undefined) {
            updates.push((existing.has('homepage_view_department_grid') ? 'homepage_view_department_grid' : 'view_department_grid') + ' = ?');
            values.push(homepage_view_department_grid ? 1 : 0);
        }
        if (existing.has('role_permissions') && role_permissions !== undefined) {
            updates.push('role_permissions = ?');
            if (Array.isArray(role_permissions)) {
                values.push(JSON.stringify(role_permissions));
            }
            else if (role_permissions && typeof role_permissions === 'object') {
                values.push(JSON.stringify(role_permissions));
            }
            else if (typeof role_permissions === 'string') {
                values.push(role_permissions);
            }
            else {
                values.push(null);
            }
        }
        if (existing.has('required_field_permissions') && required_field_permissions !== undefined) {
            updates.push('required_field_permissions = ?');
            if (Array.isArray(required_field_permissions)) {
                values.push(JSON.stringify(required_field_permissions));
            }
            else if (required_field_permissions && typeof required_field_permissions === 'object') {
                values.push(JSON.stringify(required_field_permissions));
            }
            else if (typeof required_field_permissions === 'string') {
                values.push(required_field_permissions);
            }
            else {
                values.push(null);
            }
        }
        if ((existing.has('auto_user_create') || existing.has('auto_user_crete')) && auto_user_create !== undefined) {
            updates.push((existing.has('auto_user_create') ? 'auto_user_create' : 'auto_user_crete') + ' = ?');
            values.push(auto_user_create ? 1 : 0);
        }
        if (existing.has('department_grid') && department_grid !== undefined) {
            updates.push('department_grid = ?');
            values.push(department_grid ? 1 : 0);
        }
        if (updates.length === 0) {
            throw new Error('No fields to update');
        }
        updates.push('updated_at = CURRENT_TIMESTAMP');
        values.push(id);
        const query = `UPDATE organizations SET ${updates.join(', ')} WHERE id = ?`;
        try {
            const [result] = await pool.execute(query, values);
            if (result.affectedRows === 0) {
                throw new Error('Organization not found');
            }
            return result.affectedRows;
        }
        catch (error) {
            throw new Error(`Error updating organization: ${error.message}`);
        }
    }
    // Delete organization
    static async delete(id) {
        // Check if organization has any related data
        const checkQuery = `
      SELECT 
        (SELECT COUNT(*) FROM units WHERE organization_id = ?) as units_count,
        (SELECT COUNT(*) FROM users WHERE organization_id = ?) as users_count
    `;
        try {
            let units_count = 0;
            let users_count = 0;
            try {
                const [checkRows] = await pool.execute(checkQuery, [id, id]);
                units_count = checkRows[0].units_count;
                users_count = checkRows[0].users_count;
            }
            catch (e) {
                if (e && (e.code === 'ER_NO_SUCH_TABLE' || /Table '.*\.units' doesn't exist/i.test(e.message))) {
                    const [userRows] = await pool.execute('SELECT COUNT(*) as users_count FROM users WHERE organization_id = ?', [id]);
                    users_count = userRows[0].users_count;
                    units_count = 0;
                }
                else {
                    throw e;
                }
            }
            if (units_count > 0 || users_count > 0) {
                throw new Error('Cannot delete organization with existing units or users. Please remove or reassign them first.');
            }
            const query = 'DELETE FROM organizations WHERE id = ?';
            const [result] = await pool.execute(query, [id]);
            if (result.affectedRows === 0) {
                throw new Error('Organization not found');
            }
            return result.affectedRows;
        }
        catch (error) {
            throw new Error(`Error deleting organization: ${error.message}`);
        }
    }
    // Get organization types (distinct)
    static async getTypes() {
        const query = `
      SELECT DISTINCT type 
      FROM organizations 
      WHERE type IS NOT NULL AND type != ''
      ORDER BY type
    `;
        try {
            const [rows] = await pool.execute(query);
            return rows.map(row => row.type);
        }
        catch (error) {
            throw new Error(`Error getting organization types: ${error.message}`);
        }
    }
    // Convert to JSON
    toJSON() {
        // Parse role_permissions to array if possible
        let parsedRoles = null;
        if (this.role_permissions !== undefined) {
            const raw = this.role_permissions;
            if (Array.isArray(raw)) {
                parsedRoles = raw;
            }
            else if (typeof raw === 'string') {
                const s = raw.trim();
                if (s) {
                    if (s.startsWith('[')) {
                        try {
                            parsedRoles = JSON.parse(s);
                        }
                        catch (e) {
                            parsedRoles = null;
                        }
                    }
                    else {
                        parsedRoles = s.split(',').map(v => {
                            const t = v.trim();
                            const n = Number(t);
                            return Number.isNaN(n) ? t : n;
                        });
                    }
                }
            }
        }
        let parsedRequiredFields = null;
        if (this.required_field_permissions !== undefined) {
            const rawReq = this.required_field_permissions;
            if (Array.isArray(rawReq)) {
                parsedRequiredFields = rawReq;
            }
            else if (typeof rawReq === 'string') {
                const s = rawReq.trim();
                if (s) {
                    if (s.startsWith('[')) {
                        try {
                            parsedRequiredFields = JSON.parse(s);
                        }
                        catch (e) {
                            parsedRequiredFields = null;
                        }
                    }
                    else {
                        parsedRequiredFields = s.split(',').map(v => v.trim()).filter(Boolean);
                    }
                }
            }
        }
        return {
            id: this.id,
            name: this.name,
            code: this.code,
            type: this.type,
            description: this.description,
            address: this.address,
            phone: this.phone,
            email: this.email,
            website: this.website,
            logo: this.logo,
            theme: this.theme,
            is_active: this.is_active,
            created_by: this.created_by,
            created_by_name: this.created_by_name,
            created_at: this.created_at,
            updated_at: this.updated_at,
            total_units: this.total_units,
            total_users: this.total_users,
            // expose unified fields for UI
            homepage_view_home: this.homepage_view_home ? 1 : 0,
            homepage_view_units: this.homepage_view_units ? 1 : 0,
            homepage_view_contacts: this.homepage_view_contacts ? 1 : 0,
            homepage_view_department_grid: this.homepage_view_department_grid ? 1 : 0,
            role_permissions: parsedRoles,
            auto_user_create: this.auto_user_create ? 1 : 0,
            department_grid: this.department_grid ? 1 : 0,
            required_field_permissions: parsedRequiredFields
        };
    }
}
module.exports = Organization;
//# sourceMappingURL=Organization.js.map