import { Model, DataTypes, Sequelize } from 'sequelize';
import { APPLICATION_STAGES, APPLICATION_STATUS, BUSINESS_TYPES } from '../../../common/config/constants.js';

export interface ApplicationAttributes {
    id: string;
    applicationId: string;
    opportunityId: string | null;
    applicantName: string;
    email: string;
    phone: string;
    businessType: string;
    preferredLocation: string | null;
    city: string | null;
    state: string | null;
    experienceYears: number | null;
    investmentCapacity: string | null;
    age: number | null;
    education: string | null;
    companyName: string | null;
    source: string | null;
    existingDealer: string | null;
    ownRoyalEnfield: string | null;
    royalEnfieldModel: string | null;
    description: string | null;
    address: string | null;
    pincode: string | null;
    constitutionType: string | null;
    currentStage: string;
    overallStatus: string;
    progressPercentage: number;
    isShortlisted: boolean;
    ddLeadShortlisted: boolean;
    assignedTo: string | null;
    architectureAssignedTo: string | null;
    architectureStatus: string | null;
    statutoryStatus: string | null;
    submittedBy: string | null;
    districtId: string | null;
    architectureAssignedDate: Date | null;
    architectureDocumentDate: Date | null;
    architectureCompletionDate: Date | null;
    score: number;
    // Statutory & Bank Details
    panNumber: string | null;
    gstNumber: string | null;
    bankName: string | null;
    accountNumber: string | null;
    ifscCode: string | null;
    branchName: string | null;
    accountHolderName: string | null;
    registeredAddress: string | null;
    documents: any[];
    timeline: any[];
}

export interface ApplicationInstance extends Model<ApplicationAttributes>, ApplicationAttributes { }

export default (sequelize: Sequelize) => {
    const Application = sequelize.define<ApplicationInstance>('Application', {
        id: {
            type: DataTypes.UUID,
            defaultValue: DataTypes.UUIDV4,
            primaryKey: true
        },
        applicationId: {
            type: DataTypes.STRING,
            unique: true,
            allowNull: false
        },
        opportunityId: {
            type: DataTypes.UUID,
            allowNull: true,
            references: {
                model: 'opportunities',
                key: 'id'
            }
        },
        applicantName: {
            type: DataTypes.STRING,
            allowNull: false
        },
        email: {
            type: DataTypes.STRING,
            allowNull: false,
            validate: { isEmail: true }
        },
        phone: {
            type: DataTypes.STRING,
            allowNull: false
        },
        businessType: {
            type: DataTypes.ENUM(...Object.values(BUSINESS_TYPES)),
            allowNull: false
        },
        preferredLocation: {
            type: DataTypes.STRING,
            allowNull: true
        },
        city: {
            type: DataTypes.STRING,
            allowNull: true
        },
        state: {
            type: DataTypes.STRING,
            allowNull: true
        },
        experienceYears: {
            type: DataTypes.INTEGER,
            allowNull: true
        },
        investmentCapacity: {
            type: DataTypes.STRING,
            allowNull: true
        },
        age: {
            type: DataTypes.INTEGER,
            allowNull: true
        },
        education: {
            type: DataTypes.STRING,
            allowNull: true
        },
        companyName: {
            type: DataTypes.STRING,
            allowNull: true
        },
        source: {
            type: DataTypes.STRING,
            allowNull: true
        },
        existingDealer: {
            type: DataTypes.STRING, // Storing 'yes'/'no'
            allowNull: true
        },
        ownRoyalEnfield: {
            type: DataTypes.STRING, // Storing 'yes'/'no'
            allowNull: true
        },
        royalEnfieldModel: {
            type: DataTypes.STRING,
            allowNull: true
        },
        description: {
            type: DataTypes.TEXT,
            allowNull: true
        },
        address: {
            type: DataTypes.TEXT,
            allowNull: true
        },
        pincode: {
            type: DataTypes.STRING,
            allowNull: true
        },
        constitutionType: {
            type: DataTypes.STRING,
            allowNull: true
        },
        currentStage: {
            type: DataTypes.ENUM(...Object.values(APPLICATION_STAGES)),
            defaultValue: APPLICATION_STAGES.DD
        },
        overallStatus: {
            type: DataTypes.ENUM(...Object.values(APPLICATION_STATUS)),
            defaultValue: APPLICATION_STATUS.PENDING
        },
        progressPercentage: {
            type: DataTypes.INTEGER,
            defaultValue: 0
        },
        isShortlisted: {
            type: DataTypes.BOOLEAN,
            defaultValue: false
        },
        ddLeadShortlisted: {
            type: DataTypes.BOOLEAN,
            defaultValue: false
        },
        score: {
            type: DataTypes.DECIMAL(10, 2),
            allowNull: true,
            defaultValue: 0
        },
        assignedTo: {
            type: DataTypes.UUID,
            allowNull: true,
            references: {
                model: 'users',
                key: 'id'
            }
        },
        architectureAssignedTo: {
            type: DataTypes.UUID,
            allowNull: true,
            references: {
                model: 'users',
                key: 'id'
            }
        },
        architectureStatus: {
            type: DataTypes.STRING,
            allowNull: true,
            defaultValue: 'Pending'
        },
        statutoryStatus: {
            type: DataTypes.STRING,
            allowNull: true,
            defaultValue: 'Pending'
        },
        registeredAddress: {
            type: DataTypes.TEXT,
            allowNull: true
        },
        submittedBy: {
            type: DataTypes.UUID,
            allowNull: true,
            references: {
                model: 'users',
                key: 'id'
            }
        },
        districtId: {
            type: DataTypes.UUID,
            allowNull: true,
            references: {
                model: 'districts',
                key: 'id'
            }
        },
        architectureAssignedDate: {
            type: DataTypes.DATE,
            allowNull: true
        },
        architectureDocumentDate: {
            type: DataTypes.DATE,
            allowNull: true
        },
        architectureCompletionDate: {
            type: DataTypes.DATE,
            allowNull: true
        },
        panNumber: {
            type: DataTypes.STRING,
            allowNull: true
        },
        gstNumber: {
            type: DataTypes.STRING,
            allowNull: true
        },
        bankName: {
            type: DataTypes.STRING,
            allowNull: true
        },
        accountNumber: {
            type: DataTypes.STRING,
            allowNull: true
        },
        ifscCode: {
            type: DataTypes.STRING,
            allowNull: true
        },
        branchName: {
            type: DataTypes.STRING,
            allowNull: true
        },
        accountHolderName: {
            type: DataTypes.STRING,
            allowNull: true
        },
        documents: {
            type: DataTypes.JSON,
            defaultValue: []
        },
        timeline: {
            type: DataTypes.JSON,
            defaultValue: []
        }
    }, {
        tableName: 'applications',
        timestamps: true,
        indexes: [
            { fields: ['applicationId'] },
            { fields: ['email'] },
            { fields: ['currentStage'] },
            { fields: ['overallStatus'] },
            { fields: ['opportunityId'] }
        ]
    });

    (Application as any).associate = (models: any) => {
        Application.belongsTo(models.User, { foreignKey: 'submittedBy', as: 'submitter' });
        Application.belongsTo(models.User, { foreignKey: 'assignedTo', as: 'assignee' });
        Application.belongsTo(models.User, { foreignKey: 'architectureAssignedTo', as: 'architectureAssignee' });
        Application.belongsTo(models.Opportunity, { foreignKey: 'opportunityId', as: 'opportunity' });
        Application.belongsTo(models.District, { foreignKey: 'districtId', as: 'district' });

        Application.hasMany(models.ApplicationStatusHistory, { foreignKey: 'applicationId', as: 'statusHistory' });
        Application.hasMany(models.ApplicationProgress, { foreignKey: 'applicationId', as: 'progressTracking' });

        Application.hasMany(models.OnboardingDocument, {
            foreignKey: 'applicationId',
            as: 'uploadedDocuments'
        });

        Application.hasMany(models.QuestionnaireResponse, { foreignKey: 'applicationId', as: 'questionnaireResponses' });
        Application.hasMany(models.Worknote, {
            foreignKey: 'requestId',
            as: 'worknotes',
            scope: { requestType: 'application' },
            constraints: false
        });
        Application.hasMany(models.RequestParticipant, {
            foreignKey: 'requestId',
            as: 'participants',
            scope: { requestType: 'application' },
            constraints: false
        });
        Application.hasOne(models.DealerCode, { foreignKey: 'applicationId', as: 'dealerCode' });
        Application.hasMany(models.StageApprovalAction, { foreignKey: 'applicationId', as: 'stageApprovals' });
        Application.hasOne(models.Dealer, { foreignKey: 'applicationId', as: 'dealer' });
        Application.hasMany(models.SecurityDeposit, { foreignKey: 'applicationId', as: 'securityDeposits' });
        Application.hasOne(models.EorChecklist, { foreignKey: 'applicationId', as: 'eorChecklist' });
        Application.hasMany(models.FddAssignment, { foreignKey: 'applicationId', as: 'fddAssignments' });
        Application.hasMany(models.LoiRequest, { foreignKey: 'applicationId', as: 'loiRequests' });
        Application.hasMany(models.LoaRequest, { foreignKey: 'applicationId', as: 'loaRequests' });
    };

    return Application;
};
