// ================================================================
// frontend/src/api/services/procurement-service.ts
// ================================================================
/**
 * Procurement Service - Fully aligned with backend Procurement Service API
 *
 * Backend API: services/procurement/app/api/
 * - procurement_plans.py: Plan CRUD and generation
 * - analytics.py: Analytics and dashboard
 * - purchase_orders.py: PO creation from plans
 *
 * Base URL: /api/v1/tenants/{tenant_id}/procurement/*
 *
 * Last Updated: 2025-10-31
 * Status: ✅ Complete - 100% backend alignment
 */

import { apiClient } from '../client/apiClient';
import {
  // Procurement Plan types
  ProcurementPlanResponse,
  ProcurementPlanCreate,
  ProcurementPlanUpdate,
  PaginatedProcurementPlans,

  // Procurement Requirement types
  ProcurementRequirementResponse,
  ProcurementRequirementUpdate,

  // Dashboard & Analytics types
  ProcurementDashboardData,
  ProcurementTrendsData,

  // Request/Response types
  GeneratePlanRequest,
  GeneratePlanResponse,
  AutoGenerateProcurementRequest,
  AutoGenerateProcurementResponse,
  CreatePOsResult,
  LinkRequirementToPORequest,
  UpdateDeliveryStatusRequest,
  ApprovalRequest,
  RejectionRequest,

  // Query parameter types
  GetProcurementPlansParams,
  GetPlanRequirementsParams,
  UpdatePlanStatusParams,
} from '../types/procurement';

/**
 * Procurement Service
 * All methods use the standalone Procurement Service backend API
 */
export class ProcurementService {

  // ===================================================================
  // ANALYTICS & DASHBOARD
  // Backend: services/procurement/app/api/analytics.py
  // ===================================================================

  /**
   * Get procurement analytics dashboard data
   * GET /api/v1/tenants/{tenant_id}/procurement/analytics/procurement
   */
  static async getProcurementAnalytics(tenantId: string): Promise<ProcurementDashboardData> {
    return apiClient.get<ProcurementDashboardData>(`/tenants/${tenantId}/procurement/analytics/procurement`);
  }

  /**
   * Get procurement time-series trends for charts
   * GET /api/v1/tenants/{tenant_id}/procurement/analytics/procurement/trends
   */
  static async getProcurementTrends(tenantId: string, days: number = 7): Promise<ProcurementTrendsData> {
    return apiClient.get<ProcurementTrendsData>(`/tenants/${tenantId}/procurement/analytics/procurement/trends?days=${days}`);
  }

  // ===================================================================
  // PROCUREMENT PLAN GENERATION
  // Backend: services/procurement/app/api/procurement_plans.py
  // ===================================================================

  /**
   * Auto-generate procurement plan from forecast data (Orchestrator integration)
   * POST /api/v1/tenants/{tenant_id}/procurement/operations/auto-generate
   *
   * Called by Orchestrator Service to create procurement plans based on forecast data
   */
  static async autoGenerateProcurement(
    tenantId: string,
    request: AutoGenerateProcurementRequest
  ): Promise<AutoGenerateProcurementResponse> {
    return apiClient.post<AutoGenerateProcurementResponse>(
      `/tenants/${tenantId}/procurement/operations/auto-generate`,
      request
    );
  }

  /**
   * Generate a new procurement plan (manual/UI-driven)
   * POST /api/v1/tenants/{tenant_id}/procurement/plans
   */
  static async generateProcurementPlan(
    tenantId: string,
    request: GeneratePlanRequest
  ): Promise<GeneratePlanResponse> {
    return apiClient.post<GeneratePlanResponse>(
      `/tenants/${tenantId}/procurement/plans`,
      request
    );
  }

  // ===================================================================
  // PROCUREMENT PLAN CRUD
  // Backend: services/procurement/app/api/procurement_plans.py
  // ===================================================================

  /**
   * Get the current day's procurement plan
   * GET /api/v1/tenants/{tenant_id}/procurement/plans/current
   */
  static async getCurrentProcurementPlan(tenantId: string): Promise<ProcurementPlanResponse | null> {
    return apiClient.get<ProcurementPlanResponse | null>(
      `/tenants/${tenantId}/procurement/plans/current`
    );
  }

  /**
   * Get procurement plan by ID
   * GET /api/v1/tenants/{tenant_id}/procurement/plans/{plan_id}
   */
  static async getProcurementPlanById(
    tenantId: string,
    planId: string
  ): Promise<ProcurementPlanResponse | null> {
    return apiClient.get<ProcurementPlanResponse | null>(
      `/tenants/${tenantId}/procurement/plans/${planId}`
    );
  }

  /**
   * Get procurement plan for a specific date
   * GET /api/v1/tenants/{tenant_id}/procurement/plans/date/{plan_date}
   */
  static async getProcurementPlanByDate(
    tenantId: string,
    planDate: string
  ): Promise<ProcurementPlanResponse | null> {
    return apiClient.get<ProcurementPlanResponse | null>(
      `/tenants/${tenantId}/procurement/plans/date/${planDate}`
    );
  }

  /**
   * List all procurement plans for tenant with pagination and filtering
   * GET /api/v1/tenants/{tenant_id}/procurement/plans
   */
  static async getProcurementPlans(params: GetProcurementPlansParams): Promise<PaginatedProcurementPlans> {
    const { tenant_id, status, start_date, end_date, limit = 50, offset = 0 } = params;

    const queryParams = new URLSearchParams({
      limit: limit.toString(),
      offset: offset.toString(),
    });

    if (status) queryParams.append('status', status);
    if (start_date) queryParams.append('start_date', start_date);
    if (end_date) queryParams.append('end_date', end_date);

    return apiClient.get<PaginatedProcurementPlans>(
      `/tenants/${tenant_id}/procurement/plans?${queryParams.toString()}`
    );
  }

  /**
   * Update procurement plan status
   * PATCH /api/v1/tenants/{tenant_id}/procurement/plans/{plan_id}/status
   */
  static async updateProcurementPlanStatus(params: UpdatePlanStatusParams): Promise<ProcurementPlanResponse> {
    const { tenant_id, plan_id, status, notes } = params;

    const queryParams = new URLSearchParams({ status });
    if (notes) queryParams.append('notes', notes);

    return apiClient.patch<ProcurementPlanResponse>(
      `/tenants/${tenant_id}/procurement/plans/${plan_id}/status?${queryParams.toString()}`,
      {}
    );
  }

  // ===================================================================
  // PROCUREMENT REQUIREMENTS
  // Backend: services/procurement/app/api/procurement_plans.py
  // ===================================================================

  /**
   * Get all requirements for a procurement plan
   * GET /api/v1/tenants/{tenant_id}/procurement/plans/{plan_id}/requirements
   */
  static async getPlanRequirements(params: GetPlanRequirementsParams): Promise<ProcurementRequirementResponse[]> {
    const { tenant_id, plan_id, status, priority } = params;

    const queryParams = new URLSearchParams();
    if (status) queryParams.append('status', status);
    if (priority) queryParams.append('priority', priority);

    const url = `/tenants/${tenant_id}/procurement/plans/${plan_id}/requirements${
      queryParams.toString() ? `?${queryParams.toString()}` : ''
    }`;

    return apiClient.get<ProcurementRequirementResponse[]>(url);
  }

  /**
   * Get critical requirements across all plans
   * GET /api/v1/tenants/{tenant_id}/procurement/requirements/critical
   */
  static async getCriticalRequirements(tenantId: string): Promise<ProcurementRequirementResponse[]> {
    return apiClient.get<ProcurementRequirementResponse[]>(
      `/tenants/${tenantId}/procurement/requirements/critical`
    );
  }

  /**
   * Link a procurement requirement to a purchase order
   * POST /api/v1/tenants/{tenant_id}/procurement/requirements/{requirement_id}/link-purchase-order
   */
  static async linkRequirementToPurchaseOrder(
    tenantId: string,
    requirementId: string,
    request: LinkRequirementToPORequest
  ): Promise<{ success: boolean; message: string; requirement_id: string; purchase_order_id: string }> {
    return apiClient.post<{
      success: boolean;
      message: string;
      requirement_id: string;
      purchase_order_id: string;
    }>(
      `/tenants/${tenantId}/procurement/requirements/${requirementId}/link-purchase-order`,
      request
    );
  }

  /**
   * Update delivery status for a requirement
   * PUT /api/v1/tenants/{tenant_id}/procurement/requirements/{requirement_id}/delivery-status
   */
  static async updateRequirementDeliveryStatus(
    tenantId: string,
    requirementId: string,
    request: UpdateDeliveryStatusRequest
  ): Promise<{ success: boolean; message: string; requirement_id: string; delivery_status: string }> {
    return apiClient.put<{
      success: boolean;
      message: string;
      requirement_id: string;
      delivery_status: string;
    }>(
      `/tenants/${tenantId}/procurement/requirements/${requirementId}/delivery-status`,
      request
    );
  }

  // ===================================================================
  // ADVANCED PROCUREMENT OPERATIONS
  // Backend: services/procurement/app/api/procurement_plans.py
  // ===================================================================

  /**
   * Recalculate an existing procurement plan
   * POST /api/v1/tenants/{tenant_id}/procurement/plans/{plan_id}/recalculate
   */
  static async recalculateProcurementPlan(
    tenantId: string,
    planId: string
  ): Promise<GeneratePlanResponse> {
    return apiClient.post<GeneratePlanResponse>(
      `/tenants/${tenantId}/procurement/plans/${planId}/recalculate`,
      {}
    );
  }

  /**
   * Approve a procurement plan with optional notes
   * POST /api/v1/tenants/{tenant_id}/procurement/plans/{plan_id}/approve
   */
  static async approveProcurementPlan(
    tenantId: string,
    planId: string,
    request?: ApprovalRequest
  ): Promise<ProcurementPlanResponse> {
    return apiClient.post<ProcurementPlanResponse>(
      `/tenants/${tenantId}/procurement/plans/${planId}/approve`,
      request || {}
    );
  }

  /**
   * Reject a procurement plan with optional notes
   * POST /api/v1/tenants/{tenant_id}/procurement/plans/{plan_id}/reject
   */
  static async rejectProcurementPlan(
    tenantId: string,
    planId: string,
    request?: RejectionRequest
  ): Promise<ProcurementPlanResponse> {
    return apiClient.post<ProcurementPlanResponse>(
      `/tenants/${tenantId}/procurement/plans/${planId}/reject`,
      request || {}
    );
  }

  // ===================================================================
  // PURCHASE ORDERS
  // Backend: services/procurement/app/api/purchase_orders.py
  // ===================================================================

  /**
   * Create purchase orders from procurement plan requirements
   * Groups requirements by supplier and creates POs
   * POST /api/v1/tenants/{tenant_id}/procurement/plans/{plan_id}/create-purchase-orders
   */
  static async createPurchaseOrdersFromPlan(
    tenantId: string,
    planId: string,
    autoApprove: boolean = false
  ): Promise<CreatePOsResult> {
    return apiClient.post<CreatePOsResult>(
      `/tenants/${tenantId}/procurement/plans/${planId}/create-purchase-orders`,
      { auto_approve: autoApprove }
    );
  }

  /**
   * Create a new purchase order
   * POST /api/v1/tenants/{tenant_id}/procurement/purchase-orders
   */
  static async createPurchaseOrder(
    tenantId: string,
    poData: any
  ): Promise<PurchaseOrderResponse> {
    return apiClient.post<PurchaseOrderResponse>(
      `/tenants/${tenantId}/procurement/purchase-orders`,
      poData
    );
  }

  /**
   * Get purchase order by ID
   * GET /api/v1/tenants/{tenant_id}/procurement/purchase-orders/{po_id}
   */
  static async getPurchaseOrderById(
    tenantId: string,
    poId: string
  ): Promise<PurchaseOrderWithSupplierResponse> {
    return apiClient.get<PurchaseOrderWithSupplierResponse>(
      `/tenants/${tenantId}/procurement/purchase-orders/${poId}`
    );
  }

  /**
   * List purchase orders
   * GET /api/v1/tenants/{tenant_id}/procurement/purchase-orders
   */
  static async getPurchaseOrders(
    tenantId: string,
    params?: { skip?: number; limit?: number; supplier_id?: string; status?: string }
  ): Promise<PurchaseOrderResponse[]> {
    const queryParams = new URLSearchParams();
    if (params?.skip !== undefined) queryParams.append('skip', params.skip.toString());
    if (params?.limit !== undefined) queryParams.append('limit', params.limit.toString());
    if (params?.supplier_id) queryParams.append('supplier_id', params.supplier_id);
    if (params?.status) queryParams.append('status', params.status);

    const queryString = queryParams.toString();
    const url = `/tenants/${tenantId}/procurement/purchase-orders${queryString ? `?${queryString}` : ''}`;
    
    return apiClient.get<PurchaseOrderResponse[]>(url);
  }

  /**
   * Update purchase order
   * PATCH /api/v1/tenants/{tenant_id}/procurement/purchase-orders/{po_id}
   */
  static async updatePurchaseOrder(
    tenantId: string,
    poId: string,
    poData: any
  ): Promise<PurchaseOrderResponse> {
    return apiClient.patch<PurchaseOrderResponse>(
      `/tenants/${tenantId}/procurement/purchase-orders/${poId}`,
      poData
    );
  }

  /**
   * Update purchase order status
   * PATCH /api/v1/tenants/{tenant_id}/procurement/purchase-orders/{po_id}/status
   */
  static async updatePurchaseOrderStatus(
    tenantId: string,
    poId: string,
    status: string,
    notes?: string
  ): Promise<PurchaseOrderResponse> {
    const queryParams = new URLSearchParams({ status });
    if (notes) queryParams.append('notes', notes);

    return apiClient.patch<PurchaseOrderResponse>(
      `/tenants/${tenantId}/procurement/purchase-orders/${poId}/status?${queryParams.toString()}`,
      {}
    );
  }

  /**
   * Approve or reject purchase order
   * POST /api/v1/tenants/{tenant_id}/procurement/purchase-orders/{po_id}/approve
   */
  static async approvePurchaseOrder(
    tenantId: string,
    poId: string,
    approveData: any
  ): Promise<PurchaseOrderResponse> {
    return apiClient.post<PurchaseOrderResponse>(
      `/tenants/${tenantId}/procurement/purchase-orders/${poId}/approve`,
      approveData
    );
  }

  /**
   * Cancel purchase order
   * POST /api/v1/tenants/{tenant_id}/procurement/purchase-orders/{po_id}/cancel
   */
  static async cancelPurchaseOrder(
    tenantId: string,
    poId: string,
    reason: string,
    cancelledBy?: string
  ): Promise<PurchaseOrderResponse> {
    const queryParams = new URLSearchParams({ reason });
    if (cancelledBy) queryParams.append('cancelled_by', cancelledBy);

    return apiClient.post<PurchaseOrderResponse>(
      `/tenants/${tenantId}/procurement/purchase-orders/${poId}/cancel?${queryParams.toString()}`,
      {}
    );
  }

  /**
   * Get expected deliveries
   * GET /api/v1/tenants/{tenant_id}/procurement/expected-deliveries
   */
  static async getExpectedDeliveries(
    tenantId: string,
    params?: { days_ahead?: number; include_overdue?: boolean }
  ): Promise<{ deliveries: any[]; total_count: number }> {
    const queryParams = new URLSearchParams();
    if (params?.days_ahead !== undefined) queryParams.append('days_ahead', params.days_ahead.toString());
    if (params?.include_overdue !== undefined) queryParams.append('include_overdue', params.include_overdue.toString());

    const queryString = queryParams.toString();
    const url = `/tenants/${tenantId}/procurement/expected-deliveries${queryString ? `?${queryString}` : ''}`;

    return apiClient.get<{ deliveries: any[]; total_count: number }>(url);
  }
}

export default ProcurementService;
