import { Request, Response } from 'express';
import db from '../../database/models/index.js';
import { Op } from 'sequelize';
import {
    SYSTEM_AUDIT_MODULES,
    SYSTEM_AUDIT_ACTIONS
} from '../../common/config/constants.js';
import { logSystemAudit } from '../../services/systemAuditLog.service.js';

const { InterviewConfig, InterviewConfigItem, InterviewConfigItemOption } = db;

// --- GET active config by type ---
export const getInterviewConfigByType = async (req: Request, res: Response) => {
    try {
        const { configType } = req.params;
        const config = await InterviewConfig.findOne({
            where: { configType, isActive: true },
            include: [{
                model: InterviewConfigItem,
                as: 'items',
                order: [['order', 'ASC']],
                include: [{
                    model: InterviewConfigItemOption,
                    as: 'options',
                    order: [['order', 'ASC']]
                }]
            }],
            order: [['createdAt', 'DESC']]
        });

        if (!config) {
            return res.status(404).json({ success: false, message: `No active config found for ${configType}` });
        }

        res.json({ success: true, data: config });
    } catch (error) {
        console.error('Get interview config error:', error);
        res.status(500).json({ success: false, message: 'Error fetching interview configuration' });
    }
};

// --- GET all configs (optionally filtered by type) ---
export const getInterviewConfigs = async (req: Request, res: Response) => {
    try {
        const { configType } = req.query;
        const where: any = {};
        if (configType) where.configType = configType;

        const configs = await InterviewConfig.findAll({
            where,
            order: [['createdAt', 'DESC']],
            attributes: ['id', 'configType', 'name', 'version', 'isActive', 'createdAt']
        });

        res.json({ success: true, data: configs });
    } catch (error) {
        console.error('Get interview configs error:', error);
        res.status(500).json({ success: false, message: 'Error fetching interview configurations' });
    }
};

// --- GET config by ID (with full items/options) ---
export const getInterviewConfigById = async (req: Request, res: Response) => {
    try {
        const { id } = req.params;
        const config = await InterviewConfig.findByPk(id, {
            include: [{
                model: InterviewConfigItem,
                as: 'items',
                order: [['order', 'ASC']],
                include: [{
                    model: InterviewConfigItemOption,
                    as: 'options',
                    order: [['order', 'ASC']]
                }]
            }]
        });

        if (!config) {
            return res.status(404).json({ success: false, message: 'Configuration not found' });
        }

        res.json({ success: true, data: config });
    } catch (error) {
        console.error('Get interview config by id error:', error);
        res.status(500).json({ success: false, message: 'Error fetching configuration' });
    }
};

// --- CREATE / PUBLISH new config version ---
export const createInterviewConfig = async (req: Request, res: Response) => {
    const transaction = await db.sequelize.transaction();
    try {
        const { configType, name, version, items } = req.body;

        // Deactivate old versions for this configType
        await InterviewConfig.update({ isActive: false }, { where: { configType }, transaction });

        const config = await InterviewConfig.create({
            configType,
            name: name || `${configType} Config`,
            version: version || 'v1.0',
            isActive: true
        }, { transaction });

        if (items && Array.isArray(items) && items.length > 0) {
            for (const [index, item] of items.entries()) {
                const createdItem = await InterviewConfigItem.create({
                    configId: config.id,
                    itemKey: item.itemKey,
                    label: item.label,
                    type: item.type || 'text',
                    order: item.order || index + 1,
                    isRequired: item.isRequired !== false,
                    weight: item.weight || null,
                    maxScore: item.maxScore || null
                }, { transaction });

                if (item.options && Array.isArray(item.options) && item.options.length > 0) {
                    const optionRecords = item.options.map((opt: any, idx: number) => ({
                        itemId: createdItem.id,
                        optionLabel: opt.optionLabel || opt.label,
                        optionValue: opt.optionValue || opt.value,
                        score: opt.score || 0,
                        order: opt.order || idx + 1
                    }));
                    await InterviewConfigItemOption.bulkCreate(optionRecords, { transaction });
                }
            }
        }

        await transaction.commit();

        const fullConfig = await InterviewConfig.findByPk(config.id, {
            include: [{
                model: InterviewConfigItem,
                as: 'items',
                include: [{ model: InterviewConfigItemOption, as: 'options' }]
            }]
        });

        await logSystemAudit(req, {
            module: SYSTEM_AUDIT_MODULES.INTERVIEW_CONFIG,
            entityType: configType,
            entityId: config.id,
            entityLabel: `${name || `${configType} Config`} (${version || 'v1.0'})`,
            action: SYSTEM_AUDIT_ACTIONS.CREATED,
            description: `Published new ${configType} interview config; previous active version deactivated`,
            newData: {
                configType,
                version: version || 'v1.0',
                itemCount: Array.isArray(items) ? items.length : 0
            }
        });

        res.status(201).json({ success: true, data: fullConfig });
    } catch (error) {
        await transaction.rollback();
        console.error('Create interview config error:', error);
        res.status(500).json({ success: false, message: 'Error creating interview configuration' });
    }
};

// --- UPDATE config (only non-active versions, or deactivate + recreate) ---
export const updateInterviewConfig = async (req: Request, res: Response) => {
    const transaction = await db.sequelize.transaction();
    try {
        const { id } = req.params;
        const { name, version, isActive, items } = req.body;

        const config = await InterviewConfig.findByPk(id, { transaction });
        if (!config) {
            await transaction.rollback();
            return res.status(404).json({ success: false, message: 'Configuration not found' });
        }

        const previousSnapshot = {
            name: config.name,
            version: config.version,
            isActive: config.isActive
        };

        await config.update({ name, version, isActive }, { transaction });

        // If items are provided, replace them
        if (items && Array.isArray(items)) {
            // Delete old items (cascade will handle options if DB has onDelete CASCADE)
            await InterviewConfigItem.destroy({ where: { configId: id }, transaction });

            for (const [index, item] of items.entries()) {
                const createdItem = await InterviewConfigItem.create({
                    configId: id,
                    itemKey: item.itemKey,
                    label: item.label,
                    type: item.type || 'text',
                    order: item.order || index + 1,
                    isRequired: item.isRequired !== false,
                    weight: item.weight || null,
                    maxScore: item.maxScore || null
                }, { transaction });

                if (item.options && Array.isArray(item.options) && item.options.length > 0) {
                    const optionRecords = item.options.map((opt: any, idx: number) => ({
                        itemId: createdItem.id,
                        optionLabel: opt.optionLabel || opt.label,
                        optionValue: opt.optionValue || opt.value,
                        score: opt.score || 0,
                        order: opt.order || idx + 1
                    }));
                    await InterviewConfigItemOption.bulkCreate(optionRecords, { transaction });
                }
            }
        }

        await transaction.commit();

        const fullConfig = await InterviewConfig.findByPk(id, {
            include: [{
                model: InterviewConfigItem,
                as: 'items',
                include: [{ model: InterviewConfigItemOption, as: 'options' }]
            }]
        });

        await logSystemAudit(req, {
            module: SYSTEM_AUDIT_MODULES.INTERVIEW_CONFIG,
            entityType: config.configType,
            entityId: id as string,
            entityLabel: `${name || config.name} (${version || config.version})`,
            action: SYSTEM_AUDIT_ACTIONS.UPDATED,
            description: `Updated ${config.configType} interview config${
                Array.isArray(items) ? ` and replaced ${items.length} item(s)` : ''
            }`,
            oldData: previousSnapshot,
            newData: { name, version, isActive }
        });

        res.json({ success: true, data: fullConfig });
    } catch (error) {
        await transaction.rollback();
        console.error('Update interview config error:', error);
        res.status(500).json({ success: false, message: 'Error updating interview configuration' });
    }
};

// --- DELETE config ---
export const deleteInterviewConfig = async (req: Request, res: Response) => {
    try {
        const { id } = req.params;
        const config = await InterviewConfig.findByPk(id);
        if (!config) {
            return res.status(404).json({ success: false, message: 'Configuration not found' });
        }

        const snapshot = {
            configType: config.configType,
            name: config.name,
            version: config.version,
            isActive: config.isActive
        };

        await config.destroy();

        await logSystemAudit(req, {
            module: SYSTEM_AUDIT_MODULES.INTERVIEW_CONFIG,
            entityType: snapshot.configType,
            entityId: id as string,
            entityLabel: `${snapshot.name} (${snapshot.version})`,
            action: SYSTEM_AUDIT_ACTIONS.DELETED,
            description: `Deleted interview config ${snapshot.name} (${snapshot.version})`,
            oldData: snapshot
        });

        res.json({ success: true, message: 'Configuration deleted successfully' });
    } catch (error) {
        console.error('Delete interview config error:', error);
        res.status(500).json({ success: false, message: 'Error deleting configuration' });
    }
};

// --- Seed / Initialize with defaults ---
export const initializeDefaultInterviewConfigs = async (req: Request, res: Response) => {
    try {
        const transaction = await db.sequelize.transaction();

        // Helper to deactivate existing
        const deactivate = async (configType: string) => {
            await InterviewConfig.update({ isActive: false }, { where: { configType }, transaction });
        };

        // --- KT Matrix Defaults ---
        await deactivate('KT_MATRIX');
        const ktConfig = await InterviewConfig.create({
            configType: 'KT_MATRIX',
            name: 'Default KT Matrix',
            version: 'v1.0',
            isActive: true
        }, { transaction });

        const ktDefaults = [
            { itemKey: 'age', label: 'Age', type: 'select', weight: 5, maxScore: 10, options: [
                { optionLabel: '20 to 40 years old', optionValue: '20-40', score: 10 },
                { optionLabel: '40 to 50 years old', optionValue: '40-50', score: 5 },
                { optionLabel: 'Above 50 years old', optionValue: 'above-50', score: 0 }
            ]},
            { itemKey: 'qualification', label: 'Qualification', type: 'select', weight: 5, maxScore: 10, options: [
                { optionLabel: 'Post Graduate', optionValue: 'post-graduate', score: 10 },
                { optionLabel: 'Graduate', optionValue: 'graduate', score: 5 },
                { optionLabel: 'SSLC', optionValue: 'sslc', score: 0 }
            ]},
            { itemKey: 'local_knowledge', label: 'Local Knowledge and Influence', type: 'select', weight: 5, maxScore: 10, options: [
                { optionLabel: 'Excellent PR', optionValue: 'excellent', score: 10 },
                { optionLabel: 'Good PR', optionValue: 'good', score: 5 },
                { optionLabel: 'Poor PR', optionValue: 'poor', score: 0 }
            ]},
            { itemKey: 'base_location', label: 'Base Location vs Applied Location', type: 'select', weight: 10, maxScore: 10, options: [
                { optionLabel: 'Native of the Applied location', optionValue: 'native', score: 10 },
                { optionLabel: 'Willing to relocate', optionValue: 'relocate', score: 5 },
                { optionLabel: 'Will manage remotely with occasional visits', optionValue: 'remote', score: 0 }
            ]},
            { itemKey: 'interest_reason', label: 'Why Interested in Royal Enfield Business?', type: 'select', weight: 10, maxScore: 10, options: [
                { optionLabel: 'Passion', optionValue: 'passion', score: 10 },
                { optionLabel: 'Business expansion / Status symbol', optionValue: 'business', score: 5 }
            ]},
            { itemKey: 'passion_re', label: 'Passion for Royal Enfield', type: 'select', weight: 10, maxScore: 10, options: [
                { optionLabel: 'Currently owns a Royal Enfield', optionValue: 'owns', score: 10 },
                { optionLabel: 'Owned by Immediate Relative', optionValue: 'relative', score: 5 },
                { optionLabel: 'Does not own Royal Enfield', optionValue: 'none', score: 0 }
            ]},
            { itemKey: 'passion_rides', label: 'Passion For Rides', type: 'select', weight: 10, maxScore: 10, options: [
                { optionLabel: 'Goes for long rides regularly', optionValue: 'regular', score: 10 },
                { optionLabel: 'Goes for long rides rarely', optionValue: 'rarely', score: 5 },
                { optionLabel: "Doesn't go for rides", optionValue: 'never', score: 0 }
            ]},
            { itemKey: 'partnering', label: 'With Whom Partnering?', type: 'select', weight: 5, maxScore: 10, options: [
                { optionLabel: 'Within family', optionValue: 'family', score: 10 },
                { optionLabel: 'Outside family', optionValue: 'outside', score: 0 }
            ]},
            { itemKey: 'who_manages', label: 'Who Will Manage the Firm?', type: 'select', weight: 10, maxScore: 10, options: [
                { optionLabel: 'Owner managed', optionValue: 'owner', score: 10 },
                { optionLabel: 'Partly owner / partly manager model', optionValue: 'partly', score: 5 },
                { optionLabel: 'Fully manager model', optionValue: 'manager', score: 0 }
            ]},
            { itemKey: 'business_acumen', label: 'Business Acumen', type: 'select', weight: 5, maxScore: 10, options: [
                { optionLabel: 'Has similar automobile experience', optionValue: 'automobile', score: 10 },
                { optionLabel: 'Has successful business but not automobile', optionValue: 'other-business', score: 5 },
                { optionLabel: 'No business experience', optionValue: 'no-experience', score: 0 }
            ]},
            { itemKey: 'time_availability', label: 'Time Availability', type: 'select', weight: 5, maxScore: 10, options: [
                { optionLabel: 'Full Time Availability for RE Business', optionValue: 'full-time', score: 10 },
                { optionLabel: 'Part Time Availability for RE Business', optionValue: 'part-time', score: 5 },
                { optionLabel: 'Not Available personally, Manager will handle', optionValue: 'manager', score: 0 }
            ]},
            { itemKey: 'property_ownership', label: 'Property Ownership', type: 'select', weight: 5, maxScore: 10, options: [
                { optionLabel: 'Has own property in proposed location', optionValue: 'own', score: 10 },
                { optionLabel: 'Will rent / lease', optionValue: 'rent', score: 0 }
            ]},
            { itemKey: 'investment', label: 'Investment in the Business', type: 'select', weight: 5, maxScore: 10, options: [
                { optionLabel: 'Full own funds', optionValue: 'own-funds', score: 10 },
                { optionLabel: 'Partially from the bank', optionValue: 'partial-bank', score: 5 },
                { optionLabel: 'Completely bank funded', optionValue: 'full-bank', score: 0 }
            ]},
            { itemKey: 'expand_oems', label: 'Will Expand to Other 2W/4W OEMs?', type: 'select', weight: 5, maxScore: 10, options: [
                { optionLabel: 'No', optionValue: 'no', score: 10 },
                { optionLabel: 'Yes', optionValue: 'yes', score: 0 }
            ]},
            { itemKey: 'expansion_plans', label: 'Plans of Expansion with RE', type: 'select', weight: 5, maxScore: 10, options: [
                { optionLabel: 'Immediate blood relation will join & expand', optionValue: 'blood-relation', score: 10 },
                { optionLabel: 'Wants to expand by himself into more clusters', optionValue: 'self-expand', score: 5 },
                { optionLabel: 'No plans for expansion', optionValue: 'no-plans', score: 0 }
            ]}
        ];

        for (const [index, item] of ktDefaults.entries()) {
            const createdItem = await InterviewConfigItem.create({
                configId: ktConfig.id,
                itemKey: item.itemKey,
                label: item.label,
                type: item.type,
                order: index + 1,
                isRequired: true,
                weight: item.weight,
                maxScore: item.maxScore
            }, { transaction });
            if (item.options) {
                await InterviewConfigItemOption.bulkCreate(
                    item.options.map((o: any, idx: number) => ({ ...o, itemId: createdItem.id, order: idx + 1 })),
                    { transaction }
                );
            }
        }

        // --- Level 2 Feedback Defaults ---
        await deactivate('LEVEL2_FEEDBACK');
        const l2Config = await InterviewConfig.create({
            configType: 'LEVEL2_FEEDBACK',
            name: 'Default Level 2 Feedback',
            version: 'v1.0',
            isActive: true
        }, { transaction });

        const l2Defaults = [
            { itemKey: 'strategicVision', label: 'Strategic Vision', type: 'textarea', isRequired: true },
            { itemKey: 'managementCapabilities', label: 'Management Capabilities', type: 'textarea', isRequired: true },
            { itemKey: 'operationalUnderstanding', label: 'Operational Understanding', type: 'textarea', isRequired: true },
            { itemKey: 'keyStrengths', label: 'Key Strengths', type: 'textarea', isRequired: true },
            { itemKey: 'areasOfConcern', label: 'Areas of Concern', type: 'textarea', isRequired: true },
            { itemKey: 'additionalComments', label: 'Additional Comments', type: 'textarea', isRequired: false }
        ];

        for (const [index, item] of l2Defaults.entries()) {
            await InterviewConfigItem.create({
                configId: l2Config.id,
                itemKey: item.itemKey,
                label: item.label,
                type: item.type,
                order: index + 1,
                isRequired: item.isRequired,
                weight: null,
                maxScore: null
            }, { transaction });
        }

        // --- Level 3 Feedback Defaults ---
        await deactivate('LEVEL3_FEEDBACK');
        const l3Config = await InterviewConfig.create({
            configType: 'LEVEL3_FEEDBACK',
            name: 'Default Level 3 Feedback',
            version: 'v1.0',
            isActive: true
        }, { transaction });

        const l3Defaults = [
            { itemKey: 'strategicVision', label: 'Business Vision & Strategy', type: 'textarea', isRequired: true },
            { itemKey: 'managementCapabilities', label: 'Leadership & Decision Making', type: 'textarea', isRequired: true },
            { itemKey: 'operationalUnderstanding', label: 'Operational & Financial Readiness', type: 'textarea', isRequired: true },
            { itemKey: 'brandAlignment', label: 'Brand Alignment', type: 'textarea', isRequired: true },
            { itemKey: 'keyStrengths', label: 'Key Strengths', type: 'textarea', isRequired: true },
            { itemKey: 'areasOfConcern', label: 'Areas of Concern', type: 'textarea', isRequired: true },
            { itemKey: 'executiveSummary', label: 'Executive Summary', type: 'textarea', isRequired: false },
            { itemKey: 'additionalComments', label: 'Additional Comments', type: 'textarea', isRequired: false }
        ];

        for (const [index, item] of l3Defaults.entries()) {
            await InterviewConfigItem.create({
                configId: l3Config.id,
                itemKey: item.itemKey,
                label: item.label,
                type: item.type,
                order: index + 1,
                isRequired: item.isRequired,
                weight: null,
                maxScore: null
            }, { transaction });
        }

        await transaction.commit();

        await logSystemAudit(req, {
            module: SYSTEM_AUDIT_MODULES.INTERVIEW_CONFIG,
            entityType: 'BULK_DEFAULTS',
            entityId: null,
            entityLabel: 'KT_MATRIX + LEVEL2_FEEDBACK + LEVEL3_FEEDBACK',
            action: SYSTEM_AUDIT_ACTIONS.INITIALIZED,
            description: 'Initialized default interview configs (KT Matrix, Level 2 Feedback, Level 3 Feedback) — previous active versions were deactivated',
            metadata: {
                ktMatrixItems: ktDefaults.length,
                level2Items: l2Defaults.length,
                level3Items: l3Defaults.length
            }
        });

        res.json({ success: true, message: 'Default interview configurations initialized successfully' });
    } catch (error) {
        console.error('Initialize defaults error:', error);
        res.status(500).json({ success: false, message: 'Error initializing default configurations' });
    }
};
