import { z } from "zod";
import { WALLET_ACTIVITY_CHAINS } from "../../consts";
import { EvmAddressSchema } from "../common";

const CovalentChains = z.enum(WALLET_ACTIVITY_CHAINS);

const Timestamps = z
  .object({
    minAmount: z.number(),
    maxAmount: z.number(),
  })
  .partial()
  .default({});

const methodInput = z.object({
  index: z.number().int().nonnegative(),
  value: z.string(),
  operator: z.enum([
    "equal",
    "not_equal",
    "greater",
    "greater_or_equal",
    "less",
    "less_or_equal",
    "array_last_equal",
  ]),
});

export default [
  z.object({
    type: z.enum(["COVALENT_FIRST_TX", "COVALENT_FIRST_TX_RELATIVE"]),
    chain: CovalentChains.default("ETHEREUM"),
    data: z
      .object({
        timestamps: Timestamps,
      })
      .default({}),
  }),
  z.object({
    type: z.enum([
      "COVALENT_CONTRACT_DEPLOY",
      "COVALENT_CONTRACT_DEPLOY_RELATIVE",
      "COVALENT_TX_COUNT",
      "COVALENT_TX_COUNT_RELATIVE",
    ]),
    chain: CovalentChains.default("ETHEREUM"),
    address: EvmAddressSchema.nullable().optional(),
    data: z.object({
      txCount: z.number().int().nonnegative(),
      maxAmount: z.number().optional(),
      minAmount: z.number().optional(),
      timestamps: Timestamps,
    }),
  }),
  z.object({
    type: z.enum(["COVALENT_TX_VALUE", "COVALENT_TX_VALUE_RELATIVE"]),
    chain: CovalentChains.default("ETHEREUM"),
    address: EvmAddressSchema.nullable().optional(),
    data: z.object({
      txValue: z.number(),
      maxAmount: z.number().optional(),
      minAmount: z.number().optional(),
      timestamps: Timestamps,
    }),
  }),
  z.object({
    type: z.enum([
      "COVALENT_CONTRACT_CALL_COUNT",
      "COVALENT_CONTRACT_CALL_COUNT_RELATIVE",
    ]),
    chain: CovalentChains.extract(["INK", "INK_SEPOLIA", "SONIC"]).default(
      "INK"
    ),
    address: EvmAddressSchema,
    data: z
      .object({
        method: z.string(),
        inputs: z.array(methodInput).default([]),
        txCount: z.number(),
        timestamps: Timestamps,
        maxAmount: z.number().optional(),
        minAmount: z.number().optional(),
      })
      .refine(
        ({ method, inputs }) => !method.startsWith("0x") || !inputs?.length,
        {
          message:
            "Cannot define inputs if method is defined as a raw byte signature",
        }
      ),
  }),
];
