/**
 * WHMCS Billing Provider - Raw Types
 *
 * Type definitions for the WHMCS billing API contract:
 * - Request parameter types (API inputs)
 * - Response types (API outputs)
 *
 * These represent the exact structure used by WHMCS APIs.
 */

import { z } from "zod";
import {
  whmcsString as s,
  whmcsRequiredNumber,
  whmcsOptionalNumber,
} from "../../../common/providers/whmcs-utils/index.js";

// ============================================================================
// Request Parameter Types
// ============================================================================

/**
 * Parameters for WHMCS GetInvoices API
 */
export interface WhmcsGetInvoicesParams {
  userid?: number | undefined; // WHMCS API uses 'userid' not 'clientid'
  status?: "Paid" | "Unpaid" | "Cancelled" | "Overdue" | "Collections" | undefined;
  limitstart?: number | undefined;
  limitnum?: number | undefined;
  orderby?: "id" | "invoicenum" | "date" | "duedate" | "total" | "status" | undefined;
  order?: "ASC" | "DESC" | undefined;
  [key: string]: unknown;
}

/**
 * Parameters for WHMCS CreateInvoice API
 */
export interface WhmcsCreateInvoiceParams {
  userid: number;
  status?:
    | "Draft"
    | "Paid"
    | "Unpaid"
    | "Cancelled"
    | "Refunded"
    | "Collections"
    | "Overdue"
    | "Payment Pending"
    | undefined;
  sendnotification?: boolean | undefined;
  paymentmethod?: string | undefined;
  taxrate?: number | undefined;
  taxrate2?: number | undefined;
  date?: string | undefined; // YYYY-MM-DD format
  duedate?: string | undefined; // YYYY-MM-DD format
  notes?: string | undefined;
  itemdescription1?: string | undefined;
  itemamount1?: number | undefined;
  itemtaxed1?: boolean | undefined;
  itemdescription2?: string | undefined;
  itemamount2?: number | undefined;
  itemtaxed2?: boolean | undefined;
  // Can have up to 24 line items (itemdescription1-24, itemamount1-24, itemtaxed1-24)
  [key: string]: unknown;
}

/**
 * Parameters for WHMCS UpdateInvoice API
 */
export interface WhmcsUpdateInvoiceParams {
  invoiceid: number;
  status?:
    | "Draft"
    | "Paid"
    | "Unpaid"
    | "Cancelled"
    | "Refunded"
    | "Collections"
    | "Overdue"
    | undefined;
  duedate?: string | undefined; // YYYY-MM-DD format
  notes?: string | undefined;
  [key: string]: unknown;
}

/**
 * Parameters for WHMCS CapturePayment API
 */
export interface WhmcsCapturePaymentParams {
  invoiceid: number;
  cvv?: string;
  cardnum?: string;
  cccvv?: string;
  cardtype?: string;
  cardexp?: string;
  // For existing payment methods
  paymentmethodid?: number;
  // Manual payment capture
  transid?: string;
  gateway?: string;
  [key: string]: unknown;
}

// ============================================================================
// Response Types
// ============================================================================

// Raw WHMCS Invoice Item
export const whmcsInvoiceItemRawSchema = z.object({
  id: whmcsRequiredNumber,
  type: s,
  relid: whmcsRequiredNumber,
  description: s,
  amount: s,
  taxed: s.optional(),
});

export type WhmcsInvoiceItemRaw = z.infer<typeof whmcsInvoiceItemRawSchema>;

// Raw WHMCS Invoice Items (can be single or array)
export const whmcsInvoiceItemsRawSchema = z.object({
  item: z.union([whmcsInvoiceItemRawSchema, z.array(whmcsInvoiceItemRawSchema)]),
});

export type WhmcsInvoiceItemsRaw = z.infer<typeof whmcsInvoiceItemsRawSchema>;

const whmcsInvoiceCommonSchema = z
  .object({
    invoicenum: s.optional(),
    userid: whmcsRequiredNumber,
    date: s,
    duedate: s,
    subtotal: s,
    credit: s,
    tax: s,
    tax2: s,
    total: s,
    balance: s.optional(),
    status: s,
    paymentmethod: s,
    notes: s.optional(),
    ccgateway: z.boolean().optional(),
    items: whmcsInvoiceItemsRawSchema.optional(),
    transactions: z.unknown().optional(),
    clientid: whmcsOptionalNumber,
    datecreated: s.optional(),
    paymentmethodname: s.optional(),
    currencyprefix: s.optional(),
    currencysuffix: s.optional(),
    lastcaptureattempt: s.optional(),
    last_capture_attempt: s.optional(),
    datepaid: s.optional(),
    date_refunded: s.optional(),
    date_cancelled: s.optional(),
    created_at: s.optional(),
    updated_at: s.optional(),
    taxrate: s.optional(),
    taxrate2: s.optional(),
    firstname: s.optional(),
    lastname: s.optional(),
    companyname: s.optional(),
    currencycode: s.optional(),
  })
  .strip();

export const whmcsInvoiceListItemSchema = whmcsInvoiceCommonSchema.extend({
  id: whmcsRequiredNumber,
  invoiceid: whmcsOptionalNumber,
});

// Raw WHMCS Invoice (detailed GetInvoice response)
export const whmcsInvoiceRawSchema = whmcsInvoiceCommonSchema.extend({
  invoiceid: whmcsRequiredNumber,
  id: whmcsOptionalNumber,
  balance: s.optional(),
});

export type WhmcsInvoiceRaw = z.infer<typeof whmcsInvoiceRawSchema>;
export type WhmcsInvoiceListItem = z.infer<typeof whmcsInvoiceListItemSchema>;

// ============================================================================
// WHMCS Invoice List Response (GetInvoices API)
// ============================================================================

/**
 * WHMCS GetInvoices API response schema
 */
export const whmcsInvoiceListResponseSchema = z.object({
  invoices: z.object({
    invoice: z.array(whmcsInvoiceListItemSchema),
  }),
  totalresults: whmcsRequiredNumber,
  numreturned: whmcsRequiredNumber,
  startnumber: whmcsRequiredNumber,
});

export type WhmcsInvoiceListResponse = z.infer<typeof whmcsInvoiceListResponseSchema>;

// ============================================================================
// WHMCS Single Invoice Response (GetInvoice API)
// ============================================================================

/**
 * WHMCS GetInvoice API response schema
 */
export const whmcsInvoiceResponseSchema = whmcsInvoiceRawSchema.extend({
  result: z.enum(["success", "error"]),
  transactions: z.unknown().optional(),
});

export type WhmcsInvoiceResponse = z.infer<typeof whmcsInvoiceResponseSchema>;

// ============================================================================
// WHMCS Invoice Creation Response
// ============================================================================

/**
 * WHMCS CreateInvoice API response schema
 */
export const whmcsCreateInvoiceResponseSchema = z.object({
  result: z.enum(["success", "error"]),
  invoiceid: whmcsRequiredNumber,
  status: s,
  message: s.optional(),
});

export type WhmcsCreateInvoiceResponse = z.infer<typeof whmcsCreateInvoiceResponseSchema>;

// ============================================================================
// WHMCS Invoice Update Response
// ============================================================================

/**
 * WHMCS UpdateInvoice API response schema
 */
export const whmcsUpdateInvoiceResponseSchema = z.object({
  result: z.enum(["success", "error"]),
  invoiceid: whmcsRequiredNumber,
  status: s,
  message: s.optional(),
});

export type WhmcsUpdateInvoiceResponse = z.infer<typeof whmcsUpdateInvoiceResponseSchema>;

// ============================================================================
// WHMCS Payment Capture Response
// ============================================================================

/**
 * WHMCS CapturePayment API response schema
 */
export const whmcsCapturePaymentResponseSchema = z.object({
  result: z.enum(["success", "error"]),
  invoiceid: whmcsRequiredNumber,
  status: s,
  transactionid: s.optional(),
  amount: s.optional(),
  fees: s.optional(),
  message: s.optional(),
  error: s.optional(),
});

export type WhmcsCapturePaymentResponse = z.infer<typeof whmcsCapturePaymentResponseSchema>;

// ============================================================================
// WHMCS Currency Types
// ============================================================================

/**
 * WHMCS Currency schema
 */
export const whmcsCurrencySchema = z.object({
  id: whmcsRequiredNumber,
  code: s,
  prefix: s,
  suffix: s,
  format: s,
  rate: s,
});

export type WhmcsCurrency = z.infer<typeof whmcsCurrencySchema>;

/**
 * WHMCS GetCurrencies API response schema
 *
 * WHMCS can return currencies in different formats:
 * 1. Nested format: { currencies: { currency: [...] } }
 * 2. Flat format: currencies[currency][0][id], currencies[currency][0][code], etc.
 * 3. Missing result field in some cases
 */
export const whmcsCurrenciesResponseSchema = z
  .object({
    result: z.enum(["success", "error"]).optional(),
    message: z.string().optional(),
    errorcode: z.string().optional(),
    totalresults: whmcsOptionalNumber,
    currencies: z
      .object({
        currency: z.array(whmcsCurrencySchema).or(whmcsCurrencySchema),
      })
      .optional(),
  })
  .strip();

export type WhmcsCurrenciesResponse = z.infer<typeof whmcsCurrenciesResponseSchema>;
