import { N as Nt$1, h as hashAttachment, a as hashKey, c as createReducer, i as isBaseAction, b as createDocument, s as saveToFile, l as loadFromFile, r as readFile, J as JSZip, d as loadFromInput, e as createZip, f as createAction, B as BaseDocument, g as applyMixins, j as BaseActions } from './object-10590676.js';

const S = (e) => e != null, b = Nt$1.any().refine((e) => S(e)), f = Nt$1.enum(["ADD_ACCOUNT"]), A = Nt$1.enum(["ADD_AUDIT_REPORT"]), _ = Nt$1.enum(["ADD_COMMENT"]), I = Nt$1.enum(["ADD_LINE_ITEM"]), j = Nt$1.enum(["ADD_VESTING"]);
function r() {
  return Nt$1.object({
    __typename: Nt$1.literal("Account").optional(),
    address: Nt$1.string(),
    lineItems: Nt$1.array(l()),
    name: Nt$1.string()
  });
}
function D() {
  return Nt$1.object({
    address: Nt$1.string(),
    lineItems: Nt$1.array(Nt$1.lazy(() => p())).nullish(),
    name: Nt$1.string().nullish()
  });
}
function E() {
  return Nt$1.object({
    address: Nt$1.string(),
    lineItems: Nt$1.array(l()).nullish(),
    name: Nt$1.string().nullish()
  });
}
function z() {
  return Nt$1.object({
    input: Nt$1.lazy(() => T()),
    type: f
  });
}
function T() {
  return Nt$1.object({
    accounts: Nt$1.array(Nt$1.lazy(() => D()))
  });
}
function L() {
  return Nt$1.object({
    input: Nt$1.lazy(() => C()),
    type: A
  });
}
function C() {
  return Nt$1.object({
    reports: Nt$1.array(P())
  });
}
function U() {
  return Nt$1.object({
    input: Nt$1.lazy(() => N()),
    type: _
  });
}
function N() {
  return Nt$1.object({
    comments: Nt$1.array(Nt$1.lazy(() => w()))
  });
}
function O() {
  return Nt$1.object({
    input: Nt$1.lazy(() => R()),
    type: I
  });
}
function R() {
  return Nt$1.object({
    account: Nt$1.string(),
    lineItems: Nt$1.array(Nt$1.lazy(() => p()))
  });
}
function v() {
  return Nt$1.object({
    input: Nt$1.lazy(() => V()),
    type: j
  });
}
function V() {
  return Nt$1.object({
    vesting: Nt$1.array(Nt$1.lazy(() => y()))
  });
}
function n() {
  return Nt$1.object({
    __typename: Nt$1.literal("AuditReport").optional(),
    report: Nt$1.string(),
    status: u,
    timestamp: Nt$1.string().datetime()
  });
}
function M() {
  return Nt$1.object({
    report: Nt$1.lazy(() => ut()),
    status: u,
    timestamp: Nt$1.string().datetime().nullish()
  });
}
const u = Nt$1.enum(["Approved", "ApprovedWithComments", "Escalated", "NeedsAction"]);
function P() {
  return Nt$1.union([n(), M()]);
}
function Nt() {
  return Nt$1.object({
    __typename: Nt$1.literal("BudgetStatement").optional(),
    created: Nt$1.string().datetime(),
    data: F(),
    documentType: Nt$1.string(),
    lastModified: Nt$1.string().datetime(),
    name: Nt$1.string(),
    operations: Nt$1.array(b),
    revision: Nt$1.number()
  });
}
function Ot() {
  return Nt$1.union([z(), L(), U(), O(), v(), Q(), Y(), $(), et(), it(), ct(), jt(), Et(), Tt(), Ct()]);
}
function F() {
  return Nt$1.object({
    __typename: Nt$1.literal("BudgetStatementData").optional(),
    accounts: Nt$1.array(r()),
    auditReports: Nt$1.array(n()),
    comments: Nt$1.array(o()),
    ftes: m().nullish(),
    month: Nt$1.string().nullish(),
    owner: d().nullish(),
    quoteCurrency: Nt$1.string().nullish(),
    vesting: Nt$1.array(g())
  });
}
function x() {
  return Nt$1.object({
    accounts: Nt$1.array(r()).nullish(),
    auditReports: Nt$1.array(n()).nullish(),
    comments: Nt$1.array(o()).nullish(),
    ftes: m().nullish(),
    month: Nt$1.string().nullish(),
    owner: d().nullish(),
    quoteCurrency: Nt$1.string().nullish(),
    vesting: Nt$1.array(g()).nullish()
  });
}
function B() {
  return Nt$1.object({
    created: Nt$1.string().datetime().nullish(),
    data: Nt$1.lazy(() => x()),
    documentType: Nt$1.string().nullish(),
    lastModified: Nt$1.string().datetime().nullish(),
    name: Nt$1.string().nullish(),
    revision: Nt$1.number().nullish()
  });
}
const a = Nt$1.enum(["Draft", "Escalated", "Final", "Review"]);
function o() {
  return Nt$1.object({
    __typename: Nt$1.literal("Comment").optional(),
    author: k(),
    comment: Nt$1.string(),
    key: Nt$1.string(),
    status: a,
    timestamp: Nt$1.string().datetime()
  });
}
function k() {
  return Nt$1.object({
    __typename: Nt$1.literal("CommentAuthor").optional(),
    id: Nt$1.string().nullish(),
    ref: Nt$1.string().nullish(),
    roleLabel: Nt$1.string().nullish(),
    username: Nt$1.string().nullish()
  });
}
function c() {
  return Nt$1.object({
    id: Nt$1.string().nullish(),
    ref: Nt$1.string().nullish(),
    roleLabel: Nt$1.string().nullish(),
    username: Nt$1.string().nullish()
  });
}
function w() {
  return Nt$1.object({
    author: Nt$1.lazy(() => c().nullish()),
    comment: Nt$1.string(),
    key: Nt$1.string(),
    status: a.nullish(),
    timestamp: Nt$1.string().datetime().nullish()
  });
}
function G() {
  return Nt$1.object({
    author: Nt$1.lazy(() => c().nullish()),
    comment: Nt$1.string().nullish(),
    key: Nt$1.string(),
    timestamp: Nt$1.string().datetime().nullish()
  });
}
const q = Nt$1.enum(["DELETE_ACCOUNT"]), W = Nt$1.enum(["DELETE_AUDIT_REPORT"]), H = Nt$1.enum(["DELETE_COMMENT"]), J = Nt$1.enum(["DELETE_LINE_ITEM"]), K = Nt$1.enum(["DELETE_VESTING"]);
function Q() {
  return Nt$1.object({
    input: Nt$1.lazy(() => X()),
    type: q
  });
}
function X() {
  return Nt$1.object({
    accounts: Nt$1.array(Nt$1.string())
  });
}
function Y() {
  return Nt$1.object({
    input: Nt$1.lazy(() => Z()),
    type: W
  });
}
function Z() {
  return Nt$1.object({
    reports: Nt$1.array(Nt$1.string())
  });
}
function $() {
  return Nt$1.object({
    input: Nt$1.lazy(() => tt()),
    type: H
  });
}
function tt() {
  return Nt$1.object({
    comments: Nt$1.array(Nt$1.string())
  });
}
function et() {
  return Nt$1.object({
    input: Nt$1.lazy(() => nt()),
    type: J
  });
}
function nt() {
  return Nt$1.object({
    account: Nt$1.string(),
    lineItems: Nt$1.array(Nt$1.lazy(() => lt()))
  });
}
function it() {
  return Nt$1.object({
    input: Nt$1.lazy(() => rt()),
    type: K
  });
}
function rt() {
  return Nt$1.object({
    vesting: Nt$1.array(Nt$1.string())
  });
}
function ut() {
  return Nt$1.object({
    data: Nt$1.string(),
    extension: Nt$1.string().nullish(),
    fileName: Nt$1.string().nullish(),
    mimeType: Nt$1.string()
  });
}
function m() {
  return Nt$1.object({
    __typename: Nt$1.literal("FTE").optional(),
    forecast: Nt$1.array(at().nullable()),
    value: Nt$1.number()
  });
}
function at() {
  return Nt$1.object({
    __typename: Nt$1.literal("FTEForecast").optional(),
    month: Nt$1.string(),
    value: Nt$1.number()
  });
}
const ot = Nt$1.enum(["INIT"]);
function ct() {
  return Nt$1.object({
    input: Nt$1.lazy(() => B()),
    type: ot
  });
}
const mt = Nt$1.enum(["LOAD_STATE"]);
function l() {
  return Nt$1.object({
    __typename: Nt$1.literal("LineItem").optional(),
    actual: Nt$1.number().nullish(),
    budgetCap: Nt$1.number().nullish(),
    category: s().nullish(),
    comment: Nt$1.string().nullish(),
    forecast: Nt$1.array(i()),
    group: h().nullish(),
    headcountExpense: Nt$1.boolean(),
    payment: Nt$1.number().nullish()
  });
}
function s() {
  return Nt$1.object({
    __typename: Nt$1.literal("LineItemCategory").optional(),
    id: Nt$1.string(),
    ref: Nt$1.string(),
    title: Nt$1.string()
  });
}
function lt() {
  return Nt$1.object({
    category: Nt$1.string().nullish(),
    group: Nt$1.string().nullish()
  });
}
function i() {
  return Nt$1.object({
    __typename: Nt$1.literal("LineItemForecast").optional(),
    budgetCap: Nt$1.number(),
    month: Nt$1.string(),
    value: Nt$1.number()
  });
}
function h() {
  return Nt$1.object({
    __typename: Nt$1.literal("LineItemGroup").optional(),
    id: Nt$1.string(),
    ref: Nt$1.string(),
    title: Nt$1.string()
  });
}
function p() {
  return Nt$1.object({
    actual: Nt$1.number().nullish(),
    budgetCap: Nt$1.number().nullish(),
    category: s().nullish(),
    comment: Nt$1.string().nullish(),
    forecast: Nt$1.array(i()).nullish(),
    group: h().nullish(),
    headcountExpense: Nt$1.boolean().nullish(),
    payment: Nt$1.number().nullish()
  });
}
function st() {
  return Nt$1.object({
    actual: Nt$1.number().nullish(),
    budgetCap: Nt$1.number().nullish(),
    category: Nt$1.string().nullish(),
    comment: Nt$1.string().nullish(),
    forecast: Nt$1.array(i()).nullish(),
    group: Nt$1.string().nullish(),
    headcountExpense: Nt$1.boolean().nullish(),
    payment: Nt$1.number().nullish()
  });
}
function Rt() {
  return Nt$1.object({
    input: Nt$1.lazy(() => ht()),
    type: mt
  });
}
function ht() {
  return Nt$1.object({
    operations: Nt$1.number(),
    state: Nt$1.lazy(() => pt())
  });
}
function pt() {
  return Nt$1.object({
    data: Nt$1.unknown().nullish(),
    name: Nt$1.string()
  });
}
function vt() {
  return Nt$1.object({
    __typename: Nt$1.literal("Operation").optional(),
    hash: Nt$1.string(),
    index: Nt$1.number(),
    timestamp: Nt$1.string().datetime(),
    type: Nt$1.string()
  });
}
function d() {
  return Nt$1.object({
    __typename: Nt$1.literal("Owner").optional(),
    id: Nt$1.string().nullish(),
    ref: Nt$1.string().nullish(),
    title: Nt$1.string().nullish()
  });
}
const dt = Nt$1.enum(["PRUNE"]);
function Vt() {
  return Nt$1.object({
    input: Nt$1.lazy(() => gt()),
    type: dt
  });
}
function gt() {
  return Nt$1.object({
    end: Nt$1.number().nullish(),
    start: Nt$1.number().nullish()
  });
}
const yt = Nt$1.enum(["REDO"]);
function Mt() {
  return Nt$1.object({
    input: Nt$1.number(),
    type: yt
  });
}
const St = Nt$1.enum(["SET_NAME"]);
function Pt() {
  return Nt$1.object({
    input: Nt$1.string(),
    type: St
  });
}
function Ft() {
  return Nt$1.object({
    __typename: Nt$1.literal("SetNameOperation").optional(),
    hash: Nt$1.string(),
    index: Nt$1.number(),
    input: Nt$1.string(),
    timestamp: Nt$1.string().datetime(),
    type: Nt$1.string()
  });
}
const bt = Nt$1.enum(["UNDO"]), ft = Nt$1.enum(["UPDATE_ACCOUNT"]), At = Nt$1.enum(["UPDATE_COMMENT"]), _t = Nt$1.enum(["UPDATE_LINE_ITEM"]), It = Nt$1.enum(["UPDATE_VESTING"]);
function xt() {
  return Nt$1.object({
    input: Nt$1.number(),
    type: bt
  });
}
function jt() {
  return Nt$1.object({
    input: Nt$1.lazy(() => Dt()),
    type: ft
  });
}
function Dt() {
  return Nt$1.object({
    accounts: Nt$1.array(Nt$1.lazy(() => E()))
  });
}
function Et() {
  return Nt$1.object({
    input: Nt$1.lazy(() => zt()),
    type: At
  });
}
function zt() {
  return Nt$1.object({
    comments: Nt$1.array(Nt$1.lazy(() => G()))
  });
}
function Tt() {
  return Nt$1.object({
    input: Nt$1.lazy(() => Lt()),
    type: _t
  });
}
function Lt() {
  return Nt$1.object({
    account: Nt$1.string(),
    lineItems: Nt$1.array(Nt$1.lazy(() => st()))
  });
}
function Ct() {
  return Nt$1.object({
    input: Nt$1.lazy(() => Ut()),
    type: It
  });
}
function Ut() {
  return Nt$1.object({
    vesting: Nt$1.array(Nt$1.lazy(() => y()))
  });
}
function g() {
  return Nt$1.object({
    __typename: Nt$1.literal("Vesting").optional(),
    amount: Nt$1.string(),
    amountOld: Nt$1.string(),
    comment: Nt$1.string(),
    currency: Nt$1.string(),
    date: Nt$1.string(),
    key: Nt$1.string(),
    vested: Nt$1.boolean()
  });
}
function y() {
  return Nt$1.object({
    amount: Nt$1.string().nullish(),
    amountOld: Nt$1.string().nullish(),
    comment: Nt$1.string().nullish(),
    currency: Nt$1.string().nullish(),
    date: Nt$1.string().nullish(),
    key: Nt$1.string(),
    vested: Nt$1.boolean().nullish()
  });
}
const Bt = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
  __proto__: null,
  AccountInputSchema: D,
  AccountSchema: r,
  AccountUpdateInputSchema: E,
  AddAccountActionSchema: z,
  AddAccountInputSchema: T,
  AddAuditReportActionSchema: L,
  AddAuditReportInputSchema: C,
  AddCommentActionSchema: U,
  AddCommentInputSchema: N,
  AddLineItemActionSchema: O,
  AddLineItemInputSchema: R,
  AddVestingActionSchema: v,
  AddVestingInputSchema: V,
  Add_AccountSchema: f,
  Add_Audit_ReportSchema: A,
  Add_CommentSchema: _,
  Add_Line_ItemSchema: I,
  Add_VestingSchema: j,
  AuditReportInputSchema: M,
  AuditReportSchema: n,
  AuditReportStatusSchema: u,
  AuditReportUnionSchema: P,
  BudgetStatementActionSchema: Ot,
  BudgetStatementDataInputSchema: x,
  BudgetStatementDataSchema: F,
  BudgetStatementInputSchema: B,
  BudgetStatementSchema: Nt,
  BudgetStatusSchema: a,
  CommentAuthorInputSchema: c,
  CommentAuthorSchema: k,
  CommentInputSchema: w,
  CommentSchema: o,
  CommentUpdateInputSchema: G,
  DeleteAccountActionSchema: Q,
  DeleteAccountInputSchema: X,
  DeleteAuditReportActionSchema: Y,
  DeleteAuditReportInputSchema: Z,
  DeleteCommentActionSchema: $,
  DeleteCommentInputSchema: tt,
  DeleteLineItemActionSchema: et,
  DeleteLineItemInputSchema: nt,
  DeleteVestingActionSchema: it,
  DeleteVestingInputSchema: rt,
  Delete_AccountSchema: q,
  Delete_Audit_ReportSchema: W,
  Delete_CommentSchema: H,
  Delete_Line_ItemSchema: J,
  Delete_VestingSchema: K,
  DocumentFileInputSchema: ut,
  FteForecastSchema: at,
  FteSchema: m,
  InitActionSchema: ct,
  InitSchema: ot,
  LineItemCategorySchema: s,
  LineItemDeleteInputSchema: lt,
  LineItemForecastSchema: i,
  LineItemGroupSchema: h,
  LineItemInputSchema: p,
  LineItemSchema: l,
  LineItemUpdateInputSchema: st,
  LoadStateActionInputSchema: ht,
  LoadStateActionSchema: Rt,
  LoadStateActionStateInputSchema: pt,
  Load_StateSchema: mt,
  OperationSchema: vt,
  OwnerSchema: d,
  PruneActionInputSchema: gt,
  PruneActionSchema: Vt,
  PruneSchema: dt,
  RedoActionSchema: Mt,
  RedoSchema: yt,
  SetNameActionSchema: Pt,
  SetNameOperationSchema: Ft,
  Set_NameSchema: St,
  UndoActionSchema: xt,
  UndoSchema: bt,
  UpdateAccountActionSchema: jt,
  UpdateAccountInputSchema: Dt,
  UpdateCommentActionSchema: Et,
  UpdateCommentInputSchema: zt,
  UpdateLineItemActionSchema: Tt,
  UpdateLineItemInputSchema: Lt,
  UpdateVestingActionSchema: Ct,
  UpdateVestingInputSchema: Ut,
  Update_AccountSchema: ft,
  Update_CommentSchema: At,
  Update_Line_ItemSchema: _t,
  Update_VestingSchema: It,
  VestingInputSchema: y,
  VestingSchema: g,
  definedNonNullAnySchema: b,
  isDefinedNonNullAny: S
}, Symbol.toStringTag, { value: "Module" }));

const ADD_ACCOUNT = "ADD_ACCOUNT";
const UPDATE_ACCOUNT = "UPDATE_ACCOUNT";
const DELETE_ACCOUNT = "DELETE_ACCOUNT";

const ADD_AUDIT_REPORT = "ADD_AUDIT_REPORT";
const DELETE_AUDIT_REPORT = "DELETE_AUDIT_REPORT";
function isAuditReport(audit) {
  return typeof audit.report === "string" && audit.report.startsWith("attachment://");
}

const ADD_COMMENT = "ADD_COMMENT";
const UPDATE_COMMENT = "UPDATE_COMMENT";
const DELETE_COMMENT = "DELETE_COMMENT";

const INIT = "INIT";

const ADD_LINE_ITEM = "ADD_LINE_ITEM";
const UPDATE_LINE_ITEM = "UPDATE_LINE_ITEM";
const DELETE_LINE_ITEM = "DELETE_LINE_ITEM";

const ADD_VESTING = "ADD_VESTING";
const UPDATE_VESTING = "UPDATE_VESTING";
const DELETE_VESTING = "DELETE_VESTING";

const addAccountOperation = (state, action) => {
  return {
    ...state,
    data: {
      ...state.data,
      accounts: [
        ...state.data.accounts ?? [],
        ...action.input.accounts.map(createAccount)
      ]
    }
  };
};
const updateAccountOperation = (state, action) => {
  return {
    ...state,
    data: {
      ...state.data,
      accounts: state.data.accounts.map((account) => {
        const accountUpdate = action.input.accounts.find(
          (a) => a.address === account.address
        );
        return {
          ...account,
          lineItems: accountUpdate?.lineItems ?? account.lineItems,
          name: accountUpdate?.name ?? account.name
        };
      })
    }
  };
};
const deleteAccountOperation = (state, action) => {
  return {
    ...state,
    data: {
      ...state.data,
      accounts: state.data.accounts.filter(
        (account) => !action.input.accounts.find(
          (address) => address === account.address
        )
      )
    }
  };
};

const addAuditReportOperation = (state, action) => {
  const operation = state.operations[state.operations.length - 1];
  action.input.reports.forEach((audit, index) => {
    if (isAuditReport(audit)) {
      state.data.auditReports.push(audit);
    } else {
      const hash = hashAttachment(audit.report.data);
      const attachmentKey = `attachment://audits/${hash}`;
      state.fileRegistry[attachmentKey] = { ...audit.report };
      state.data.auditReports.push({
        timestamp: audit.timestamp ?? (/* @__PURE__ */ new Date()).toISOString(),
        status: audit.status,
        report: attachmentKey
      });
      operation.input.reports[index].report = attachmentKey;
    }
  });
};
const deleteAuditReportOperation = (state, action) => {
  action.input.reports.forEach((report) => {
    const index = state.data.auditReports.findIndex(
      (audit) => audit.report === report
    );
    if (index > -1) {
      state.data.auditReports.splice(index, 1);
    }
  });
};

const initOperation = (state, action) => {
  return createBudgetStatement({
    ...state,
    ...action.input,
    name: action.input.name ?? state.name,
    revision: action.input.revision ?? state.revision,
    documentType: action.input.documentType ?? state.documentType,
    created: action.input.created ?? state.created,
    lastModified: action.input.lastModified ?? state.lastModified,
    data: {
      owner: {
        ref: action.input.data.owner?.ref || null,
        id: action.input.data.owner?.id || null,
        title: action.input.data.owner?.title || null
      },
      month: action.input.data.month ?? null,
      quoteCurrency: action.input.data.quoteCurrency ?? null,
      vesting: action.input.data.vesting ?? [],
      ftes: action.input.data.ftes ?? null,
      accounts: action.input.data.accounts ?? [],
      auditReports: action.input.data.auditReports ?? [],
      comments: action.input.data.comments ?? []
    }
  });
};

function isEqual(lineItemInput, lineItem) {
  return lineItemInput.category === lineItem.category?.id && lineItemInput.group === lineItem.group?.id;
}
const addLineItemOperation = (state, action) => {
  const newAccounts = state.data.accounts.slice();
  const accountIndex = newAccounts.findIndex(
    (a) => a.address === action.input.account
  );
  if (accountIndex === -1) {
    throw new Error(
      `Account with address ${action.input.account} not found`
    );
  }
  const newAccount = Object.assign({}, newAccounts[accountIndex]);
  newAccount.lineItems = [
    ...newAccount.lineItems,
    ...action.input.lineItems.map(createLineItem)
  ];
  newAccounts[accountIndex] = newAccount;
  return {
    ...state,
    data: {
      ...state.data,
      accounts: newAccounts
    }
  };
};
const updateLineItemOperation = (state, action) => {
  const newAccounts = state.data.accounts.slice();
  const accountIndex = newAccounts.findIndex(
    (a) => a.address === action.input.account
  );
  if (accountIndex === -1) {
    throw new Error(
      `Account with address ${action.input.account} not found`
    );
  }
  const newAccount = Object.assign({}, newAccounts[accountIndex]);
  newAccount.lineItems = newAccount.lineItems.map((lineItem) => {
    const input = action.input.lineItems.find((l) => isEqual(l, lineItem));
    if (!input) {
      return lineItem;
    } else {
      return {
        ...lineItem,
        ...input,
        category: lineItem.category,
        headcountExpense: input.headcountExpense ?? false,
        group: lineItem.group,
        forecast: [
          // replace old forecasts with new forecasts
          ...input.forecast ?? [],
          ...lineItem.forecast.filter(
            (oldForecast) => !input.forecast?.find(
              (newForecast) => newForecast.month === oldForecast.month
            )
          )
        ].filter((forecast) => forecast.value !== null).sort((f1, f2) => f1.month.localeCompare(f2.month))
      };
    }
  });
  newAccounts[accountIndex] = newAccount;
  return {
    ...state,
    data: {
      ...state.data,
      accounts: newAccounts
    }
  };
};
const deleteLineItemOperation = (state, action) => {
  const newAccounts = state.data.accounts.slice();
  const accountIndex = newAccounts.findIndex(
    (a) => a.address === action.input.account
  );
  if (accountIndex === -1) {
    throw new Error(
      `Account with address ${action.input.account} not found`
    );
  }
  const newAccount = Object.assign({}, newAccounts[accountIndex]);
  newAccount.lineItems = newAccount.lineItems.filter(
    (lineItem) => !action.input.lineItems.find((l) => isEqual(l, lineItem))
  );
  newAccounts[accountIndex] = newAccount;
  return {
    ...state,
    data: {
      ...state.data,
      accounts: newAccounts
    }
  };
};

const sortComment = (a, b) => a.timestamp < b.timestamp ? -1 : 1;
const addCommentOperation = (state, action) => {
  state.data.comments.push(
    ...action.input.comments.map((input) => ({
      key: input.key ?? hashKey(),
      author: {
        ref: null,
        id: null,
        username: null,
        roleLabel: null,
        ...input.author
      },
      comment: input.comment || "",
      timestamp: input.timestamp || (/* @__PURE__ */ new Date()).toISOString(),
      status: input.status ?? "Draft"
    }))
  );
  state.data.comments.sort(sortComment);
};
const updateCommentOperation = (state, action) => {
  action.input.comments.forEach((input) => {
    const index = state.data.comments.findIndex((c) => c.key === input.key);
    if (index === -1) {
      return;
    }
    const comment = state.data.comments[index];
    state.data.comments[index] = {
      ...comment,
      ...input,
      author: {
        id: input.author?.id ?? comment.author.id,
        ref: input.author?.ref ?? comment.author.ref,
        roleLabel: input.author?.roleLabel ?? comment.author.roleLabel,
        username: input.author?.username ?? comment.author.username
      },
      comment: input.comment ?? comment.comment,
      timestamp: input.timestamp ?? comment.timestamp
    };
  });
  state.data.comments.sort(sortComment);
};
const deleteCommentOperation = (state, action) => {
  state.data.comments = state.data.comments.filter(
    (comment) => !action.input.comments.includes(comment.key)
  );
};

const sortVesting = (a, b) => a.date < b.date ? -1 : 1;
const addVestingOperation = (state, action) => {
  state.data.vesting.push(
    ...action.input.vesting.map((input) => ({
      ...input,
      key: input.key ?? hashKey(),
      date: input.date ?? "",
      amount: input.amount ?? "",
      amountOld: input.amountOld ?? input.amount ?? "",
      comment: input.comment ?? "",
      currency: input.currency ?? "",
      vested: input.vested ?? false
    }))
  );
  state.data.vesting.sort(sortVesting);
};
const updateVestingOperation = (state, action) => {
  action.input.vesting.forEach((input) => {
    const index = state.data.vesting.findIndex((v) => v.key === input.key);
    if (index === -1) {
      return;
    }
    const vesting = state.data.vesting[index];
    state.data.vesting[index] = {
      ...vesting,
      ...input,
      amount: input.amount ?? vesting.amount,
      amountOld: input.amountOld ?? vesting.amountOld,
      comment: input.comment ?? vesting.comment,
      currency: input.currency ?? vesting.currency,
      date: input.date ?? vesting.date,
      vested: input.vested ?? vesting.vested
    };
  });
  state.data.vesting.sort(sortVesting);
};
const deleteVestingOperation = (state, action) => {
  state.data.vesting = state.data.vesting.filter(
    (vesting) => !action.input.vesting.includes(vesting.key)
  );
};

const reducer = createReducer(
  (state, action) => {
    if (isBaseAction(action)) {
      return state;
    }
    Bt.BudgetStatementActionSchema().parse(action);
    switch (action.type) {
      case INIT:
        return initOperation(state, action);
      case ADD_ACCOUNT:
        return addAccountOperation(state, action);
      case UPDATE_ACCOUNT:
        return updateAccountOperation(state, action);
      case DELETE_ACCOUNT:
        return deleteAccountOperation(state, action);
      case ADD_LINE_ITEM:
        return addLineItemOperation(state, action);
      case UPDATE_LINE_ITEM:
        return updateLineItemOperation(state, action);
      case DELETE_LINE_ITEM:
        return deleteLineItemOperation(state, action);
      case ADD_AUDIT_REPORT:
        return addAuditReportOperation(state, action);
      case DELETE_AUDIT_REPORT:
        return deleteAuditReportOperation(state, action);
      case ADD_VESTING:
        return addVestingOperation(state, action);
      case UPDATE_VESTING:
        return updateVestingOperation(state, action);
      case DELETE_VESTING:
        return deleteVestingOperation(state, action);
      case ADD_COMMENT:
        return addCommentOperation(state, action);
      case UPDATE_COMMENT:
        return updateCommentOperation(state, action);
      case DELETE_COMMENT:
        return deleteCommentOperation(state, action);
      default:
        return state;
    }
  }
);

const createBudgetStatement = (initialState) => createDocument({
  documentType: "powerhouse/budget-statement",
  ...initialState,
  data: {
    owner: {
      ref: null,
      id: null,
      title: null
    },
    month: null,
    quoteCurrency: null,
    vesting: [],
    ftes: null,
    accounts: [],
    auditReports: [],
    comments: [],
    ...initialState?.data
  }
});
const createAccount = (input) => ({
  ...input,
  name: input.name ?? "",
  lineItems: input.lineItems?.map(createLineItem) ?? new Array()
});
const createLineItem = (input) => ({
  budgetCap: null,
  payment: null,
  actual: null,
  comment: null,
  ...input,
  forecast: input.forecast ?? new Array(),
  headcountExpense: input.headcountExpense ?? false,
  group: input.group ?? null,
  category: input.category ?? null
});
const saveBudgetStatementToFile = (document, path, name) => {
  return saveToFile(document, path, "phbs", name);
};
const loadBudgetStatementFromFile = async (path) => {
  const state = await loadFromFile(
    path,
    reducer
  );
  const auditReports = state.data.auditReports;
  if (!auditReports.length) {
    return state;
  }
  const file = readFile();
  const zip = new JSZip();
  await zip.loadAsync(file);
  const fileRegistry = { ...state.fileRegistry };
  await Promise.all(
    auditReports.map(async (audit) => {
      const path2 = audit.report.slice("attachment://".length);
      const file2 = await zip.file(path2);
      if (!file2) {
        throw new Error(`Attachment ${audit.report} not found`);
      }
      const data = await file2.async("base64");
      const { mimeType, extension, fileName } = JSON.parse(file2.comment);
      fileRegistry[audit.report] = {
        data,
        mimeType,
        extension,
        fileName
      };
    })
  );
  return { ...state, fileRegistry };
};
const loadBudgetStatementFromInput = async (input) => {
  const state = await loadFromInput(
    input,
    reducer
  );
  const auditReports = state.data.auditReports;
  if (!auditReports.length) {
    return state;
  }
  const zip = new JSZip();
  await zip.loadAsync(input);
  const fileRegistry = { ...state.fileRegistry };
  await Promise.all(
    auditReports.map(async (audit) => {
      const path = audit.report.slice("attachment://".length);
      const file = await zip.file(path);
      if (!file) {
        throw new Error(`Attachment ${audit.report} not found`);
      }
      const data = await file.async("base64");
      const { mimeType, extension, fileName } = JSON.parse(file.comment);
      fileRegistry[audit.report] = {
        data,
        mimeType,
        extension,
        fileName
      };
    })
  );
  return { ...state, fileRegistry };
};
const saveBudgetStatementToFileHandle = async (document, input) => {
  const zip = await createZip(document);
  const blob = await zip.generateAsync({ type: "blob" });
  const writable = await input.createWritable();
  await writable.write(blob);
  await writable.close();
};

var utils = /*#__PURE__*/Object.freeze({
  __proto__: null,
  createAccount: createAccount,
  createBudgetStatement: createBudgetStatement,
  createLineItem: createLineItem,
  loadBudgetStatementFromFile: loadBudgetStatementFromFile,
  loadBudgetStatementFromInput: loadBudgetStatementFromInput,
  saveBudgetStatementToFile: saveBudgetStatementToFile,
  saveBudgetStatementToFileHandle: saveBudgetStatementToFileHandle
});

const addAccount = (accounts) => createAction(ADD_ACCOUNT, {
  accounts: accounts.map(createAccount)
});
const updateAccount = (accounts) => createAction(UPDATE_ACCOUNT, { accounts });
const deleteAccount = (accounts) => createAction(DELETE_ACCOUNT, { accounts });

const addAuditReport = (reports) => {
  const newTimestamp = /* @__PURE__ */ new Date();
  const newReports = reports.map(({ timestamp, report, status }) => ({
    report,
    timestamp: timestamp ?? newTimestamp.toISOString(),
    status
  }));
  return createAction(ADD_AUDIT_REPORT, {
    reports: newReports
  });
};
const deleteAuditReport = (reports) => createAction(DELETE_AUDIT_REPORT, { reports });

const init = (budgetStatement) => createAction(INIT, budgetStatement);

const addLineItem = (account, lineItems) => createAction(ADD_LINE_ITEM, {
  account,
  lineItems: lineItems.map(createLineItem)
});
const updateLineItem = (account, lineItems) => createAction(UPDATE_LINE_ITEM, {
  account,
  lineItems
});
const deleteLineItem = (account, lineItems) => createAction(DELETE_LINE_ITEM, {
  account,
  lineItems
});

class AccountObject extends BaseDocument {
  /**
   * Adds one or more accounts to the budget statement.
   * @param accounts An array of AccountInput objects to add.
   *
   * @group Account
   */
  addAccount(accounts) {
    return this.dispatch(addAccount(accounts));
  }
  /**
   * Updates one or more existing accounts in the budget statement.
   * @param accounts An array of AccountInput objects to update.
   *
   * @group Account
   */
  updateAccount(accounts) {
    return this.dispatch(updateAccount(accounts));
  }
  /**
   * Deletes one or more accounts from the budget statement.
   * @param addresses An array of addresses of the accounts to delete.
   *
   * @group Account
   */
  deleteAccount(accounts) {
    return this.dispatch(deleteAccount(accounts));
  }
  /**
   * Returns an array of all accounts in the budget statement.
   *
   * @group Account
   */
  get accounts() {
    return this.state.data.accounts;
  }
  /**
   * Returns the Account object with the specified address.
   * @param address The address of the Account to retrieve.
   *
   * @group Account
   */
  getAccount(address) {
    return this.accounts.find((account) => account.address === address);
  }
}

class AuditObject extends BaseDocument {
  /**
   * Adds audit reports to the budget statement.
   * @param reports - An array of audit report objects to add.
   *
   * @group Audit
   */
  addAuditReport(reports) {
    return this.dispatch(addAuditReport(reports));
  }
  /**
   * Deletes audit reports from the budget statement.
   * @param reports - An array of objects that contain the report attachment name of the audits items to be deleted.
   *
   * @group Audit
   */
  deleteAuditReport(reports) {
    return this.dispatch(deleteAuditReport(reports));
  }
  /**
   * Retrieves all audit reports from the budget statement.
   * @returns An array of audit report objects.
   *
   * @group Audit
   */
  getAuditReports() {
    return this.state.data.auditReports;
  }
  /**
   * Retrieves a specific audit report from the budget statement.
   * @param report - The name of the attachment of the report to be retrieved.
   * @returns The audit report object if it exists, or undefined if not.
   *
   * @group Audit
   */
  getAuditReport(report) {
    return this.getAuditReports().find((audit) => audit.report === report);
  }
}

const addComment = (comments) => createAction(ADD_COMMENT, { comments });
const updateComment = (comments) => createAction(UPDATE_COMMENT, { comments });
const deleteComment = (comments) => createAction(DELETE_COMMENT, { comments });

class CommentObject extends BaseDocument {
  addComment(comments) {
    return this.dispatch(addComment(comments));
  }
  updateComment(comments) {
    return this.dispatch(updateComment(comments));
  }
  deleteComment(comments) {
    return this.dispatch(deleteComment(comments));
  }
}

class InitObject extends BaseDocument {
  /**
   * Initializes the state of the budget statement with the provided partial object.
   *
   * @param budgetStatement - A partial object of the budget statement to initialize.
   */
  init(budgetStatement) {
    return this.dispatch(init(budgetStatement));
  }
}

class LineItemObject extends BaseDocument {
  /**
   * Adds a line item to the specified account.
   * @param account The address of the account to which the line item will be added.
   * @param lineItems An array of line item objects to be added to the account.
   *
   * @group Line Item
   */
  addLineItem(account, lineItems) {
    return this.dispatch(addLineItem(account, lineItems));
  }
  /**
   * Updates line items for the specified account.
   * @param account The address of the account for which line items will be updated.
   * @param lineItems An array of line item input objects to be updated.
   *
   * @group Line Item
   */
  updateLineItem(account, lineItems) {
    return this.dispatch(updateLineItem(account, lineItems));
  }
  /**
   * Deletes line items for the specified account.
   * @param account The address of the account for which line items will be deleted.
   * @param lineItems An array of objects that contain the category and group of the line items to be deleted.
   *
   * @group Line Item
   */
  deleteLineItem(account, lineItems) {
    return this.dispatch(deleteLineItem(account, lineItems));
  }
  /**
   * Retrieves line items for the specified account.
   * @param account The address of the account for which line items will be retrieved.
   * @returns An array of line item objects for the specified account, or undefined if the account does not exist.
   *
   * @group Line Item
   */
  getLineItems(account) {
    return this.state.data.accounts.find(
      ({ address }) => address === account
    )?.lineItems;
  }
  /**
   * Retrieves a specific line item for the specified account.
   * @param account The address of the account for which the line item will be retrieved.
   * @param lineItem An object that contains the category and group of the line item to be retrieved.
   * @returns The line item object that matches the specified category and group, or undefined if it does not exist.
   *
   * @group Line Item
   */
  getLineItem(account, lineItem) {
    return this.getLineItems(account)?.find(
      ({ category, group }) => category?.id === lineItem.category && group?.id === lineItem.group
    );
  }
}

const addVesting = (vesting) => createAction(ADD_VESTING, { vesting });
const updateVesting = (vesting) => createAction(UPDATE_VESTING, { vesting });
const deleteVesting = (vesting) => createAction(DELETE_VESTING, { vesting });

class VestingObject extends BaseDocument {
  addVesting(vesting) {
    return this.dispatch(addVesting(vesting));
  }
  updateVesting(vesting) {
    return this.dispatch(updateVesting(vesting));
  }
  deleteVesting(vesting) {
    return this.dispatch(deleteVesting(vesting));
  }
}

let BudgetStatement$2 = class BudgetStatement extends BaseDocument {
  /**
   * The file extension used to save budget statements.
   */
  static fileExtension = "phbs";
  /**
   *
   * Creates a new BudgetStatement instance.
   * @param initialState - An optional object representing the initial state of the BudgetStatement.
   */
  constructor(initialState) {
    super(reducer, createBudgetStatement(initialState));
  }
  /**
   * Gets the month of the budget statement.
   * @category Budget Statement
   */
  get month() {
    return this.state.data.month;
  }
  /**
   * Gets the owner of the budget statement.
   * @category Budget Statement
   */
  get owner() {
    return this.state.data.owner;
  }
  /**
   * Gets the quote currency of the budget statement.
   * @category Budget Statement
   */
  get quoteCurrency() {
    return this.state.data.quoteCurrency;
  }
  /**
   * Saves the budget statement to a file.
   *
   * @param path The path to the file to save.
   * @returns A promise that resolves when the save operation completes.
   */
  saveToFile(path, name) {
    return super.saveToFile(path, BudgetStatement.fileExtension, name);
  }
  /**
   * Loads the budget statement from a file.
   *
   * @param path The path to the file to load.
   * @returns A promise that resolves with the loaded `BudgetStatement` instance.
   */
  loadFromFile(path) {
    return super.loadFromFile(path);
  }
  /**
   * Creates a new `BudgetStatement` instance from a file.
   *
   * @param path The path to the file to load.
   * @returns A promise that resolves with the loaded `BudgetStatement` instance.
   */
  static async fromFile(path) {
    const budgetStatement = new this();
    await budgetStatement.loadFromFile(path);
    return budgetStatement;
  }
};
applyMixins(BudgetStatement$2, [
  AccountObject,
  AuditObject,
  CommentObject,
  InitObject,
  LineItemObject,
  VestingObject
]);

var gen = /*#__PURE__*/Object.freeze({
  __proto__: null,
  BudgetStatement: BudgetStatement$2,
  addAccount: addAccount,
  addAuditReport: addAuditReport,
  addLineItem: addLineItem,
  deleteAccount: deleteAccount,
  deleteAuditReport: deleteAuditReport,
  deleteLineItem: deleteLineItem,
  init: init,
  updateAccount: updateAccount,
  updateLineItem: updateLineItem
});

const { BudgetStatement, ...BudgetActions } = gen;
const actions = { ...BaseActions, ...BudgetActions };

var BudgetStatement$1 = /*#__PURE__*/Object.freeze({
  __proto__: null,
  BudgetStatement: BudgetStatement,
  actions: actions,
  reducer: reducer,
  utils: utils
});

export { BudgetStatement$1 as B, BudgetStatement as a, actions as b, reducer as r, utils as u };
//# sourceMappingURL=index-e529dc49.js.map
