import { constructContinueTx, constructContractRef, FullCallInfo, PreparedOperation } from '@coinweb/contract-kit';

import { ExecutorMethodArgs, Task } from '../../../types';
import { context, getRawContext } from '../../context';
import { isPreparedExecOp } from '../typeGuards';

export const prepareOutThreadTxs = ({ tasks, cwebPerCall }: { tasks: Task[]; cwebPerCall: bigint }) => {
  const siblingCallResolvedOps = [...context.ops];

  const siblingTxInfo: {
    [batchId: number]: {
      calls: FullCallInfo[];
      ops: PreparedOperation[];
    };
  } = {};

  let txFee = 0n;
  let callsPrepared = 0;

  tasks.forEach((task) => {
    if (isPreparedExecOp(task.op)) {
      console.log('Sibling call info');

      const id = task.op.ExecOp.id;

      const callInfo = {
        callInfo: {
          ref: constructContractRef(context.issuer, []),
          methodInfo: {
            methodName: context.methodName,
            methodArgs: [
              context.initialArgs,
              [...siblingCallResolvedOps, { ExecOp: { id } }],
              context.user,
              true,
            ] satisfies ExecutorMethodArgs,
          },
          contractInfo: {
            providedCweb: cwebPerCall - 700n,
            authenticated: null,
          },
          contractArgs: [],
        },
      };

      if (siblingTxInfo[task.batchId]) {
        siblingTxInfo[task.batchId].calls.push(callInfo);
      } else {
        siblingTxInfo[task.batchId] = {
          calls: [callInfo],
          ops: [],
        };
      }

      callsPrepared++;
    } else {
      if (siblingTxInfo[task.batchId]) {
        siblingTxInfo[task.batchId].ops.push(task.op);
      } else {
        siblingTxInfo[task.batchId] = {
          calls: [],
          ops: [task.op],
        };
      }

      txFee += 100n;
    }

    siblingCallResolvedOps.push({ SlotOp: 0 });
  });

  const siblingTxs = Object.values(siblingTxInfo).map(({ calls, ops }) =>
    constructContinueTx(getRawContext(), ops, calls)
  );

  return { txs: siblingTxs, fee: txFee, calls: callsPrepared };
};
