const mongoose = require('mongoose');
const bcrypt = require('bcryptjs');
const jwt = require("jsonwebtoken");
const Vendor = require('./vendor.model');


// 1. Sub-schema for Documents
const DocumentSchema = new mongoose.Schema({
    docType: {
        type: String,
        enum: ['drivinglicense', 'idproof', 'policeclearance', 'addressproof', 'bankstatement', 'aadhaar', 'pancard']
    },
    fileUrl: { type: String, required: true },
    uploadDate: { type: Date, default: Date.now },
    isVerified: { type: Boolean, default: false }
});

// 2. Sub-schema for bank details
const accountDetailsSchema = new mongoose.Schema({
    accountHolderName: {
        type: String,
        required: [true, 'Account Holder Name is required']
    },
    accountNumber: {
        type: String,
        required: [true, 'Account Number is required']
    },
    ifscCode: {
        type: String,
        required: [true, 'IFSC Code is required']
    },
    bankName: {
        type: String,
        required: [true, 'Bank Name is required']
    },
    branchName: {
        type: String,
        required: [true, 'Branch Name is required']
    },
    upiId: {
        type: String,
        required: [true, 'UPI ID is required']
    },
    uploadDate: { type: Date, default: Date.now },
    isVerified: { type: Boolean, default: false }
});

const assignmentSchema = new mongoose.Schema({
    vendorId: {
        type: mongoose.Schema.Types.ObjectId,
        ref: 'Vendor'
    },
    shift: {
        type: String,
        // Remove required validation to make it optional
    },
    vehicleId: {
        type: mongoose.Schema.Types.ObjectId,
        ref: 'Vehicle'
    },
    serviceType: {
        type: String,
        // Remove required validation to make it optional
    },
    // Add new fields that match frontend form
    shiftPreference: {
        type: String
    },
    serviceTypes: [{
        type: String
    }]
});

const driverSchema = new mongoose.Schema({
    fullName: {
        type: String,
        required: true,
        trim: true
    },
    email: {
        type: String,
        required: true,
        unique: true,
        trim: true,
        lowercase: true,
        index: true
    },
    phone: {
        type: String,
        required: true,
        trim: true
    },
    password: {
        type: String,
        required: true,
        minlength: 6,
        select: false
    },
    dob: {
        type: Date
    },
    registeredAddress: {
        type: String,
        trim: true
    },
    profileImageUrl: {
        type: String
    },
    role: {
        type: String,
        default: 'driver'
    },
    zone: {
        type: mongoose.Schema.Types.ObjectId,
        ref: 'Zone',
        required: [true, 'Zone is required']
    },
    // Direct vendor and vehicle fields (as they exist in database)
    vendor: {
        type: mongoose.Schema.Types.ObjectId,
        ref: 'Vendor'
    },
    vehicle: {
        type: mongoose.Schema.Types.ObjectId,
        ref: 'Vehicle'
    },
    gender: {
        type: String,
        enum: ['male', 'female', 'other'],
        trim: true
    },
    emergencyContact: {
        name: { type: String, trim: true },
        phone: { type: String, trim: true }
    },
    experienceYears: {
        type: Number,
        default: 0
    },
    // License Information
    licenseNumber: {
        type: String,
        trim: true
    },
    licenseExpiry: {
        type: Date
    },
    // Background Check
    backgroundCheck: {
        status: {
            type: String,
            enum: ['pending', 'passed', 'failed', 'not required'],
            default: 'pending'
        },
        checkDate: {
            type: Date
        },
        agency: {
            type: String
        }
    },
    training: [{
        courseName: { type: String },
        completedAt: { type: Date }
    }],
    // Wallet
    walletBalance: {
        type: Number,
        default: 0
    },
    // Cash collected by driver (physical cash in hand from offline payments)
    cashCollected: {
        type: Number,
        default: 0
    },
    documents: [DocumentSchema],
    accountDetails: accountDetailsSchema,
    assignmentDetails: assignmentSchema,
    status: {
        type: String,
        enum: ['active', 'assigned', 'inactive', 'ontrip', 'suspended', 'pendingvarification'],
        default: 'pendingvarification',
        index: true
    },

    // Store previous status before vendor deactivation (for restoration)
    previousStatus: {
        type: String,
        enum: ['active', 'assigned', 'inactive', 'ontrip', 'suspended', 'pendingvarification', null],
        default: null
    },

    rating: {
        type: Number,
        default: 0
    },
    driverId: {
        type: String,
        unique: true,
        sparse: true
    },
    totalTrips: {
        type: Number,
        default: 0
    },
    isOnline: {
        type: Boolean,
        default: false,
        index: true
    },
    currentLocation: {
        type: {
            type: String,
            enum: ['Point'],
            default: 'Point'
        },
        coordinates: {
            type: [Number], // [longitude, latitude]
            default: [0, 0]
        }
    },
    lastActiveAt: {
        type: Date,
        default: Date.now
    }
}, { timestamps: true });

driverSchema.index({ currentLocation: '2dsphere' });


driverSchema.pre("save", async function (next) {
    if (!this.isModified("password")) {
        return next();
    }
    let salt = await bcrypt.genSaltSync(10);
    this.password = bcrypt.hashSync(this.password, salt);
    next();
});

driverSchema.pre("save", async function (next) {
    if (!this.isNew && this.driverId) {
        return next();
    }
    try {
        const { getEnv } = require("../utils/envLoader");
        const prefix = getEnv("DRIVER_ID_PREFIX") || process.env.DRIVER_ID_PREFIX || 'DL';

        // Find the last vendor with a vendorId
        const lastVendor = await this.constructor.findOne({ driverId: { $exists: true } })
            .sort({ createdAt: -1 });

        let nextSequence = 1;

        if (lastVendor && lastVendor.driverId) {
            // Extract the numeric part
            const vendorCount = parseInt(lastVendor.driverId.slice(7));

            nextSequence = vendorCount + 1;
        }

        const vendor = await Vendor.findById(this.vendor);
        const vendorName = vendor?.vendorName?.slice(0, 3).toUpperCase() || 'XXX';
        // Pad sequence with zeros to 4 digits (e.g., 0001, 0002)
        const paddedSequence = String(nextSequence).padStart(4, '0');
        this.driverId = `${prefix}${vendorName}${paddedSequence}`;
        next();
    } catch (error) {
        next(error);
    }
});

driverSchema.methods.comparepassword = function (password) {
    return bcrypt.compareSync(password, this.password);
};

driverSchema.methods.generateAccessToken = function () {
    const { getEnv } = require("../utils/envLoader");
    const token = jwt.sign({
        _id: this._id,
        email: this.email,
        role: this.role,
        fullName: this.fullName,
        plan: this.plan
    }, getEnv("JWT_SECRET") || process.env.JWT_SECRET,
        { expiresIn: getEnv("JWT_EXPIRES_IN") || process.env.JWT_EXPIRES_IN });
    return token;
}

driverSchema.methods.generateRefreshToken = function () {
    const { getEnv } = require("../utils/envLoader");
    const refreshToken = jwt.sign(
        { _id: this._id, role: this.role },
        getEnv("REFRESHTOKEN_SECRET") || process.env.REFRESHTOKEN_SECRET,
        { expiresIn: getEnv("REFRESH_TOKEN_EXPIRES_IN") || process.env.REFRESH_TOKEN_EXPIRES_IN }
    );
    return refreshToken;
}

module.exports = mongoose.model('Driver', driverSchema);
