/**
 * 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";

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

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

/**
 * Parameters for WHMCS CreateInvoice API
 */
export interface WhmcsCreateInvoiceParams {
  userid: number;
  status?:
    | "Draft"
    | "Paid"
    | "Unpaid"
    | "Cancelled"
    | "Refunded"
    | "Collections"
    | "Overdue"
    | "Payment Pending";
  sendnotification?: boolean;
  paymentmethod?: string;
  taxrate?: number;
  taxrate2?: number;
  date?: string; // YYYY-MM-DD format
  duedate?: string; // YYYY-MM-DD format
  notes?: string;
  itemdescription1?: string;
  itemamount1?: number;
  itemtaxed1?: boolean;
  itemdescription2?: string;
  itemamount2?: number;
  itemtaxed2?: boolean;
  // 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";
  duedate?: string; // YYYY-MM-DD format
  notes?: string;
  [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: z.number(),
  type: z.string(),
  relid: z.number(),
  description: z.string(),
  amount: z.union([z.string(), z.number()]),
  taxed: z.number().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: z.string().optional(),
    userid: z.number(),
    date: z.string(),
    duedate: z.string(),
    subtotal: z.string(),
    credit: z.string(),
    tax: z.string(),
    tax2: z.string(),
    total: z.string(),
    balance: z.string().optional(),
    status: z.string(),
    paymentmethod: z.string(),
    notes: z.string().optional(),
    ccgateway: z.boolean().optional(),
    items: whmcsInvoiceItemsRawSchema.optional(),
    transactions: z.unknown().optional(),
    clientid: z.number().optional(),
    datecreated: z.string().optional(),
    paymentmethodname: z.string().optional(),
    currencyprefix: z.string().optional(),
    currencysuffix: z.string().optional(),
    lastcaptureattempt: z.string().optional(),
    last_capture_attempt: z.string().optional(),
    datepaid: z.string().optional(),
    date_refunded: z.string().optional(),
    date_cancelled: z.string().optional(),
    created_at: z.string().optional(),
    updated_at: z.string().optional(),
    taxrate: z.string().optional(),
    taxrate2: z.string().optional(),
    firstname: z.string().optional(),
    lastname: z.string().optional(),
    companyname: z.string().optional(),
    currencycode: z.string().optional(),
  })
  .passthrough();

export const whmcsInvoiceListItemSchema = whmcsInvoiceCommonSchema.extend({
  id: z.number(),
  invoiceid: z.number().optional(),
});

// Raw WHMCS Invoice (detailed GetInvoice response)
export const whmcsInvoiceRawSchema = whmcsInvoiceCommonSchema.extend({
  invoiceid: z.number(),
  id: z.number().optional(),
  balance: z.string().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: z.number(),
  numreturned: z.number(),
  startnumber: z.number(),
});

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: z.number(),
  status: z.string(),
  message: z.string().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: z.number(),
  status: z.string(),
  message: z.string().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: z.number(),
  status: z.string(),
  transactionid: z.string().optional(),
  amount: z.number().optional(),
  fees: z.number().optional(),
  message: z.string().optional(),
  error: z.string().optional(),
});

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

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

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

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(),
  totalresults: z.string().transform(val => parseInt(val, 10)).or(z.number()).optional(),
  currencies: z.object({
    currency: z.array(whmcsCurrencySchema).or(whmcsCurrencySchema),
  }).optional(),
  // Allow any additional flat currency keys for flat format
}).catchall(z.string().or(z.number()));

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