// apps/web/src/server/invoicing/icount.ts
import { z } from 'zod';
import type { VendorInvoiceProvider, InvoiceCreateArgs, InvoiceCreateResult } from './types';
import { formatAgorotPlain } from '@/lib/money';

const ICOUNT_API = 'https://api.icount.co.il/api/v3.php';
type ICountResponse = {
  status?: boolean;
  reason?: string;
  doc_id?: string | number;
  doc_number?: string | number;
  url?: string;
};
function isICountResponse(value: unknown): value is ICountResponse {
  return typeof value === 'object' && value !== null;
}

export const ICountCredentialsSchema = z.object({
  apiUser: z.string().min(1),
  apiPass: z.string().min(1),
  companyId: z.string().min(1),
});

export class ICountProvider implements VendorInvoiceProvider {
  kind = 'icount' as const;
  credentialsSchema = ICountCredentialsSchema;

  async validateCredentials(creds: unknown): Promise<{ ok: true } | { ok: false; reason: string }> {
    const parsed = ICountCredentialsSchema.safeParse(creds);
    if (!parsed.success) return { ok: false, reason: parsed.error.message };
    // Credentials in POST body; never the URL (logged by edge + intermediaries).
    const res = await fetch(ICOUNT_API, {
      method: 'POST',
      headers: { 'content-type': 'application/json' },
      body: JSON.stringify({
        action: 'get_user_info',
        cid: parsed.data.companyId,
        user: parsed.data.apiUser,
        pass: parsed.data.apiPass,
      }),
    });
    const json: unknown = await res.json();
    if (!isICountResponse(json)) return { ok: false, reason: 'invalid_response' };
    return json?.status === true
      ? { ok: true }
      : { ok: false, reason: json?.reason ?? 'auth_failed' };
  }

  async createInvoice(args: InvoiceCreateArgs): Promise<InvoiceCreateResult> {
    const creds = ICountCredentialsSchema.parse({});
    const body = {
      action: 'create_doc',
      cid: creds.companyId,
      user: creds.apiUser,
      pass: creds.apiPass,
      doc_type: 400,
      client_name: args.buyer.name,
      client_email: args.buyer.email,
      currency_code: 'ILS',
      items: args.lineItems.map((l) => ({
        description: l.description,
        unitPrice: formatAgorotPlain(l.unitAgorot),
        quantity: l.qty,
        price: formatAgorotPlain(l.unitAgorot * l.qty),
      })),
      vat: formatAgorotPlain(args.vatAgorot),
    };
    const res = await fetch(ICOUNT_API, {
      method: 'POST',
      headers: { 'content-type': 'application/json' },
      body: JSON.stringify(body),
    });
    const json: unknown = await res.json();
    if (!isICountResponse(json)) throw new Error('icount_create_failed: invalid_response');
    if (!json?.status) throw new Error(`icount_create_failed: ${json?.reason ?? 'unknown'}`);
    return {
      documentId: String(json.doc_id),
      documentNumber: String(json.doc_number ?? json.doc_id),
      documentUrl: json.url ?? '',
    };
  }
}
