import { formatFrappeApiError } from '../utils/frappeErrorMessage';

const RESOURCE = 'Purchase%20Receipt';

export interface PurchaseReceiptItem {
  name?: string;
  item_code?: string;
  item_name?: string;
  description?: string;
  qty?: number;
  rate?: number;
  amount?: number;
  uom?: string;
  idx?: number;
  [key: string]: any;
}

export interface PurchaseTaxCharge {
  name?: string;
  charge_type?: string;
  account_head?: string;
  tax_amount?: number;
  rate?: number;
  idx?: number;
  [key: string]: any;
}

export interface PurchaseReceipt {
  name: string;
  docstatus?: number;
  status?: string;
  supplier?: string;
  supplier_name?: string;
  posting_date?: string;
  company?: string;
  currency?: string;
  grand_total?: number;
  net_total?: number;
  total_taxes_and_charges?: number;
  items?: PurchaseReceiptItem[];
  taxes?: PurchaseTaxCharge[];
  owner?: string;
  creation?: string;
  modified?: string;
  [key: string]: any;
}

class PurchaseReceiptService {
  private async getCSRFToken(): Promise<string | null> {
    if (typeof window === 'undefined') return null;
    if ((window as any).csrf_token) return (window as any).csrf_token;
    if ((window as any).frappe?.csrf_token) return (window as any).frappe.csrf_token;
    try {
      const res = await fetch('/api/method/frappe.sessions.get_csrf_token', { credentials: 'include' });
      if (res.ok) {
        const json = await res.json();
        if (json.message) {
          (window as any).csrf_token = json.message;
          return json.message;
        }
      }
    } catch { /* ignore */ }
    return null;
  }

  private async getHeaders(): Promise<Record<string, string>> {
    const h: Record<string, string> = { 'Content-Type': 'application/json', Accept: 'application/json' };
    const csrf = await this.getCSRFToken();
    if (csrf) h['X-Frappe-CSRF-Token'] = csrf;
    return h;
  }

  private async fetchJson(url: string, opts: RequestInit = {}): Promise<any> {
    const headers = await this.getHeaders();
    const r = await fetch(url, { credentials: 'include', headers, ...opts });
    const body = await r.json().catch(() => ({}));
    if (!r.ok) throw new Error(formatFrappeApiError(body) || body?.message || `HTTP ${r.status}`);
    if (body.exc) throw new Error(formatFrappeApiError(body) || 'Request failed');
    return body;
  }

  async getPurchaseReceipts(
    params: { filters?: any[]; limit_start?: number; limit_page_length?: number; order_by?: string } = {},
  ): Promise<PurchaseReceipt[]> {
    const q = new URLSearchParams();
    const fields = [
      'name', 'supplier', 'supplier_name', 'posting_date', 'status',
      'grand_total', 'currency', 'docstatus', 'company', 'creation', 'modified',
    ];
    q.set('fields', JSON.stringify(fields));
    if (params.filters?.length) q.set('filters', JSON.stringify(params.filters));
    q.set('limit_start', String(params.limit_start ?? 0));
    q.set('limit_page_length', String(params.limit_page_length ?? 20));
    q.set('order_by', params.order_by ?? 'creation desc');
    const body = await this.fetchJson(`/api/resource/${RESOURCE}?${q}`);
    return body.data || [];
  }

  async getPurchaseReceiptCount(filters: any[] = []): Promise<number> {
    const q = new URLSearchParams();
    q.set('fields', JSON.stringify(['count(name) as count']));
    if (filters.length) q.set('filters', JSON.stringify(filters));
    try {
      const body = await this.fetchJson(`/api/resource/${RESOURCE}?${q}`);
      return body.data?.[0]?.count ?? 0;
    } catch {
      return 0;
    }
  }

  async getPurchaseReceipt(name: string): Promise<PurchaseReceipt> {
    const body = await this.fetchJson(`/api/resource/${RESOURCE}/${encodeURIComponent(name)}`);
    return body.data;
  }

  async createPurchaseReceipt(data: Partial<PurchaseReceipt>): Promise<PurchaseReceipt> {
    const body = await this.fetchJson(`/api/resource/${RESOURCE}`, {
      method: 'POST',
      body: JSON.stringify(data),
    });
    return body.data;
  }

  async updatePurchaseReceipt(name: string, data: Partial<PurchaseReceipt>): Promise<PurchaseReceipt> {
    const body = await this.fetchJson(`/api/resource/${RESOURCE}/${encodeURIComponent(name)}`, {
      method: 'PUT',
      body: JSON.stringify(data),
    });
    return body.data;
  }

  async submitPurchaseReceipt(name: string): Promise<PurchaseReceipt> {
    const body = await this.fetchJson(`/api/resource/${RESOURCE}/${encodeURIComponent(name)}`, {
      method: 'PUT',
      body: JSON.stringify({ docstatus: 1 }),
    });
    return body.data;
  }
}

const purchaseReceiptService = new PurchaseReceiptService();
export default purchaseReceiptService;
