import dotenv from 'dotenv';
import { jobModel } from '../../database/schemas/production/job.schema.js';
import { subJobModel } from '../../database/schemas/production/subjob.schema.js';
import log4js from 'log4js';
import { printerModel } from '../../database/schemas/production/printer.schema.js';
import { filamentModel } from '../../database/schemas/management/filament.schema.js';
import { gcodeFileModel } from '../../database/schemas/production/gcodefile.schema.js';
import { partModel } from '../../database/schemas/management/part.schema.js';
import { productModel } from '../../database/schemas/management/product.schema.js';
import { vendorModel } from '../../database/schemas/management/vendor.schema.js';
import { filamentStockModel } from '../../database/schemas/inventory/filamentstock.schema.js';
import { stockEventModel } from '../../database/schemas/inventory/stockevent.schema.js';
import { stockAuditModel } from '../../database/schemas/inventory/stockaudit.schema.js';
import { partStockModel } from '../../database/schemas/inventory/partstock.schema.js';
import { auditLogModel } from '../../database/schemas/management/auditlog.schema.js';
import { userModel } from '../../database/schemas/management/user.schema.js';
import { noteTypeModel } from '../../database/schemas/management/notetype.schema.js';
import { noteModel } from '../../database/schemas/misc/note.schema.js';
import mongoose from 'mongoose';
dotenv.config();

const logger = log4js.getLogger('Jobs');
logger.level = process.env.LOG_LEVEL;

// Map prefixes to models and id fields
const PREFIX_MODEL_MAP = {
  PRN: { model: printerModel, idField: '_id', type: 'printer' },
  FIL: { model: filamentModel, idField: '_id', type: 'filament' },
  SPL: { model: null, idField: '_id', type: 'spool' }, // No spool model found
  GCF: { model: gcodeFileModel, idField: '_id', type: 'gcodefile' },
  JOB: { model: jobModel, idField: '_id', type: 'job' },
  PRT: { model: partModel, idField: '_id', type: 'part' },
  PRD: { model: productModel, idField: '_id', type: 'product' },
  VEN: { model: vendorModel, idField: '_id', type: 'vendor' },
  SJB: { model: subJobModel, idField: '_id', type: 'subjob' },
  FLS: { model: filamentStockModel, idField: '_id', type: 'filamentstock' },
  SEV: { model: stockEventModel, idField: '_id', type: 'stockevent' },
  SAU: { model: stockAuditModel, idField: '_id', type: 'stockaudit' },
  PTS: { model: partStockModel, idField: '_id', type: 'partstock' },
  PDS: { model: null, idField: '_id', type: 'productstock' }, // No productStockModel found
  ADL: { model: auditLogModel, idField: '_id', type: 'auditlog' },
  USR: { model: userModel, idField: '_id', type: 'user' },
  NTY: { model: noteTypeModel, idField: '_id', type: 'notetype' },
  NTE: { model: noteModel, idField: '_id', type: 'note' },
};

// Helper function to build search filter from query parameters
const buildSearchFilter = (params) => {
  const filter = {};

  for (const [key, value] of Object.entries(params)) {
    // Skip pagination and limit parameters as they're not search filters
    if (key === 'limit' || key === 'page') continue;

    // Handle different field types
    if (key === 'name') {
      filter.name = { $regex: value, $options: 'i' }; // Case-insensitive search
    } else if (key === 'id' || key === '_id') {
      if (mongoose.Types.ObjectId.isValid(value)) {
        filter._id = value;
      }
    } else if (key === 'tags') {
      filter.tags = { $in: [new RegExp(value, 'i')] };
    } else if (key === 'state') {
      filter['state.type'] = value;
    } else if (key.includes('.')) {
      // Handle nested fields like 'state.type', 'address.city', etc.
      filter[key] = { $regex: value, $options: 'i' };
    } else {
      // For all other fields, do a case-insensitive search
      filter[key] = { $regex: value, $options: 'i' };
    }
  }

  return filter;
};

const trimSpotlightObject = (object) => {
  return {
    _id: object._id,
    name: object.name || undefined,
    state: object.state && object?.state.type ? { type: object.state.type } : undefined,
    tags: object.tags || undefined,
    email: object.email || undefined,
    color: object.color || undefined,
    updatedAt: object.updatedAt || undefined,
  };
};

export const getSpotlightRouteHandler = async (req, res) => {
  try {
    const query = req.params.query;
    const queryParams = req.query;
    if (query.length < 3) {
      res.status(200).send([]);
      return;
    }
    const prefix = query.substring(0, 3);
    const delimiter = query.substring(3, 4);
    const suffix = query.substring(4);

    if (delimiter == ':') {
      const prefixEntry = PREFIX_MODEL_MAP[prefix];
      if (!prefixEntry || !prefixEntry.model) {
        res.status(400).send({ error: 'Invalid or unsupported prefix' });
        return;
      }
      const { model, idField } = prefixEntry;

      // Validate ObjectId if the idField is '_id'
      if (idField === '_id' && !mongoose.Types.ObjectId.isValid(suffix)) {
        res.status(404).send({ error: `${prefix} not found` });
        return;
      }

      // Find the object by the correct field
      const queryObj = {};
      queryObj[idField] = suffix.toLowerCase();
      let doc = await model.findOne(queryObj).lean();
      if (!doc) {
        res.status(404).send({ error: `${prefix} not found` });
        return;
      }
      // Build the response with only the required fields
      const response = trimSpotlightObject(doc);
      res.status(200).send(response);
      return;
    }

    console.log(queryParams);

    if (Object.keys(queryParams).length > 0) {
      const prefixEntry = PREFIX_MODEL_MAP[prefix];
      console.log(prefixEntry);
      if (!prefixEntry || !prefixEntry.model) {
        res.status(400).send({ error: 'Invalid or unsupported prefix' });
        return;
      }
      const { model } = prefixEntry;

      // Use req.query for search parameters

      if (Object.keys(queryParams).length === 0) {
        res.status(400).send({ error: 'No search parameters provided' });
        return;
      }

      // Build search filter
      const searchFilter = buildSearchFilter(queryParams);

      // Perform search with limit
      const limit = parseInt(req.query.limit) || 10;
      const docs = await model.find(searchFilter).limit(limit).sort({ updatedAt: -1 }).lean();

      // Format response
      const response = docs.map((doc) => trimSpotlightObject(doc));

      res.status(200).send(response);
      return;
    }
  } catch (error) {
    logger.error('Error in spotlight lookup:', error);
    res.status(500).send({ error: error });
  }
};
