import { MedicineModel } from '../../schemas/medicine.schema.js';
import type {
  CreateMedicineInput,
  UpdateMedicineInput,
  MedicineQueryInput,
} from '@meshitrack/shared';

export class MedicinesRepository {
  public async findByHousehold(householdId: string, query: MedicineQueryInput) {
    const filter: Record<string, unknown> = { householdId, isDeleted: false };

    if (query.category) filter['category'] = query.category;
    if (query.form) filter['form'] = query.form;
    if (query.q) filter['name'] = { $regex: query.q, $options: 'i' };

    if (query.cursor) {
      const id = Buffer.from(query.cursor, 'base64').toString();
      filter['_id'] = { $gt: id };
    }

    const limit = query.limit;
    const items = await MedicineModel.find(filter)
      .sort({ _id: 1 })
      .limit(limit + 1)
      .lean()
      .exec();

    const hasMore = items.length > limit;
    const data = hasMore ? items.slice(0, limit) : items;
    const cursor =
      data.length > 0 ? Buffer.from(data[data.length - 1]._id.toString()).toString('base64') : null;

    return { data, pagination: { cursor: hasMore ? cursor : null, hasMore } };
  }

  public async findById(id: string, householdId: string) {
    return MedicineModel.findOne({ _id: id, householdId, isDeleted: false }).lean().exec();
  }

  public async findDuplicate(
    householdId: string,
    name: string,
    strength: number,
    strengthUnit: string,
    form: string,
    excludeId?: string,
  ) {
    const filter: Record<string, unknown> = {
      householdId,
      name,
      strength,
      strengthUnit,
      form,
      isDeleted: false,
    };
    if (excludeId) filter['_id'] = { $ne: excludeId };
    return MedicineModel.findOne(filter).lean().exec();
  }

  public async create(data: CreateMedicineInput, householdId: string, createdBy: string) {
    const medicine = new MedicineModel({ ...data, householdId, createdBy });
    const saved = await medicine.save();
    return saved.toObject();
  }

  public async update(id: string, householdId: string, data: UpdateMedicineInput) {
    return MedicineModel.findOneAndUpdate(
      { _id: id, householdId, isDeleted: false },
      { $set: data },
      { new: true, lean: true },
    ).exec();
  }

  public async softDelete(id: string, householdId: string) {
    return MedicineModel.findOneAndUpdate(
      { _id: id, householdId, isDeleted: false },
      { $set: { isDeleted: true } },
      { new: true, lean: true },
    ).exec();
  }
}
