import { RefillListModel } from '../../schemas/refill-list.schema.js';
import type {
  RefillListQueryInput,
  UpdateRefillListInput,
  UpdateRefillListItemInput,
} from '@meshitrack/shared';

export interface CreateRefillListData {
  householdId: string;
  name: string;
  status: string;
  preferredStoreId?: string;
  totalEstimatedCost?: number;
  createdBy: string;
  items: Array<{
    medicineId: string;
    medicineName: string;
    quantity: number;
    unit: string;
    estimatedPrice?: number;
    storeId?: string;
    notes?: string;
  }>;
}

export class RefillsRepository {
  public async create(data: CreateRefillListData) {
    const list = new RefillListModel(data);
    const saved = await list.save();
    return saved.toObject();
  }

  public async findByHousehold(householdId: string, query: RefillListQueryInput) {
    const filter: Record<string, unknown> = { householdId };

    if (query.status) filter['status'] = query.status;

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

    const limit = query.limit;
    const items = await RefillListModel.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 RefillListModel.findOne({ _id: id, householdId }).lean().exec();
  }

  public async update(id: string, householdId: string, data: UpdateRefillListInput) {
    const updateSet: Record<string, unknown> = {};
    if (data.name !== undefined) updateSet['name'] = data.name;
    if (data.status !== undefined) updateSet['status'] = data.status;
    if (data.preferredStoreId !== undefined) updateSet['preferredStoreId'] = data.preferredStoreId;

    return RefillListModel.findOneAndUpdate(
      { _id: id, householdId },
      { $set: updateSet },
      { new: true, lean: true },
    ).exec();
  }

  public async updateItem(
    listId: string,
    householdId: string,
    itemId: string,
    data: UpdateRefillListItemInput & { checkedAt?: Date },
  ) {
    const updateSet: Record<string, unknown> = {};
    if (data.checked !== undefined) updateSet['items.$.checked'] = data.checked;
    if (data.actualPrice !== undefined) updateSet['items.$.actualPrice'] = data.actualPrice;
    if (data.storeId !== undefined) updateSet['items.$.storeId'] = data.storeId;
    if (data.notes !== undefined) updateSet['items.$.notes'] = data.notes;
    if (data.checkedAt !== undefined) updateSet['items.$.checkedAt'] = data.checkedAt;

    return RefillListModel.findOneAndUpdate(
      { _id: listId, householdId, 'items._id': itemId },
      { $set: updateSet },
      { new: true, lean: true },
    ).exec();
  }

  public async markItemsAddedToCabinet(listId: string, householdId: string, itemIds: string[]) {
    return RefillListModel.findOneAndUpdate(
      { _id: listId, householdId },
      { $set: { 'items.$[elem].addedToCabinet': true } },
      {
        arrayFilters: [{ 'elem._id': { $in: itemIds } }],
        new: true,
        lean: true,
      },
    ).exec();
  }
}
