/*
 This file is part of GNU Taler
 (C) 2019 GNUnet e.V.
 (C) 2025 Taler Systems S.A.

 GNU Taler is free software; you can redistribute it and/or modify it under the
 terms of the GNU General Public License as published by the Free Software
 Foundation; either version 3, or (at your option) any later version.

 GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 A PARTICULAR PURPOSE.  See the GNU General Public License for more details.

 You should have received a copy of the GNU General Public License along with
 GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
 */

/**
 * @fileoverview
 * Implementation of contacts management in wallet-core.
 * The details of contacts management are specified in DD48.
 */

import {
  EmptyObject,
  AddContactRequest,
  DeleteContactRequest,
  ContactListResponse,
  ContactEntry,
  Logger,
  NotificationType,
} from "@gnu-taler/taler-util";
import {
  ContactRecord,
  WalletDbReadOnlyTransaction
} from "./db.js"
import {
  WalletExecutionContext,
} from "./wallet.js";


const logger = new Logger("contacts.ts");

async function makeContactListItem(
  wex: WalletExecutionContext,
  tx: WalletDbReadOnlyTransaction<
    ["contacts"]
  >,
  r: ContactRecord,
  //lastError: TalerErrorDetail | undefined,
): Promise<ContactEntry> {
  //const lastUpdateErrorInfo: OperationErrorInfo | undefined = lastError
  //  ? {
  //      error: lastError,
  //    }
  //  : undefined;

  const listItem: ContactEntry = {
    alias: r.alias,
    aliasType: r.aliasType,
    mailboxBaseUri: r.mailboxBaseUri,
    mailboxAddress: r.mailboxAddress,
    source: r.source,
  };
  //switch (listItem.exchangeUpdateStatus) {
  //  case ExchangeUpdateStatus.UnavailableUpdate:
  //    if (r.unavailableReason) {
  //      listItem.unavailableReason = r.unavailableReason;
  //    }
  //    break;
  //}
  return listItem;
}


/**
 * Add contact to the database.
 */
export async function addContact(
  wex: WalletExecutionContext,
  req: AddContactRequest,
): Promise<EmptyObject> {
  await wex.db.runReadWriteTx(
    {
      storeNames: [
        "contacts",
      ],
    },
    async (tx) => {
      tx.contacts.put (req.contact);
      tx.notify({
        type: NotificationType.ContactAdded,
        contact: req.contact,
      });
    },
  );
  return { };
}

/**
 * Delete contact from the database.
 */
export async function deleteContact(
  wex: WalletExecutionContext,
  req: DeleteContactRequest,
): Promise<EmptyObject> {
  await wex.db.runReadWriteTx(
    {
      storeNames: [
        "contacts",
      ],
    },
    async (tx) => {
      tx.contacts.delete ([req.contact.alias, req.contact.aliasType]);
      tx.notify({
        type: NotificationType.ContactDeleted,
        contact: req.contact,
      });
    },
  );
  return { };
}

/**
 * Get contacts from the database.
 */
export async function listContacts(
  wex: WalletExecutionContext,
  req: EmptyObject,
): Promise<ContactListResponse> {
  const contacts: ContactEntry[] = [];
  await wex.db.runReadOnlyTx(
    {
      storeNames: [
        "contacts",
      ],
    },
    async (tx) => {
      const contactsRecords = await tx.contacts.iter().toArray();
      for (const contactRec of contactsRecords) {
        const li = await makeContactListItem(
          wex,
          tx,
          contactRec,
        );
        contacts.push(li);
      }
    },
  );
  return { contacts: contacts };
}

