import {
  pgCreateSupplier,
  pgGetCustomers,
  pgGetPurchaseOrders,
  pgGetSuppliers,
  pgSavePurchaseOrders,
  pgUpdateSupplier,
} from '@/lib/postgres/data-access';
import type { Customer, PurchaseOrder, Supplier } from '@/lib/types';
import type { CreatePurchaseOrderRecord, PurchaseOrderRepository } from '../application/purchase-order.repository';

function generatePurchaseOrderNumber(existingOrders: PurchaseOrder[], documentType?: 'shipment' | 'tax_invoice'): string {
  const currentYear = new Date().getFullYear();
  const prefix = documentType === 'shipment' ? 'PS' : 'P';
  const maxSequence = existingOrders.reduce((max, order) => {
    if (!order.orderNumber || typeof order.orderNumber !== 'string') return max;
    const parts = order.orderNumber.split('/');
    if (parts.length < 3) return max;
    if (String(parts[0] || '').trim() !== prefix) return max;
    const orderYear = Number(parts[1]);
    if (!Number.isFinite(orderYear) || orderYear !== currentYear) return max;

    const sequence = Number(parts[2]);
    if (!Number.isFinite(sequence) || sequence <= 0) return max;
    return Math.max(max, sequence);
  }, 0);

  const nextSequence = maxSequence + 1;
  return `${prefix}/${currentYear}/${String(nextSequence).padStart(4, '0')}`;
}

export class PostgresPurchaseOrderRepository implements PurchaseOrderRepository {
  async findSupplierById(id: string): Promise<Supplier | null> {
    const result = await pgGetSuppliers({ page: 1, pageSize: 5000 });
    const suppliers = (result.items || []) as Supplier[];
    return suppliers.find((entry) => entry.id === id) || null;
  }

  async findCustomerById(id: string): Promise<Customer | null> {
    const result = await pgGetCustomers({ page: 1, pageSize: 5000 });
    const customers = (result.items || []) as Customer[];
    return customers.find((entry) => entry.id === id) || null;
  }

  async createSupplierFromCustomer(customer: Customer, supplierId: string): Promise<Supplier> {
    const created = await pgCreateSupplier({
      id: supplierId,
      supplierNumber: customer.customerNumber || supplierId,
      name: customer.name,
      balance: 0,
      phone: customer.phone,
      address: customer.address,
      paymentTerms: 30,
      taxNumber: '',
      inactive: false,
    });

    return created as Supplier;
  }

  async listPurchaseOrders(): Promise<PurchaseOrder[]> {
    const result = await pgGetPurchaseOrders({ page: 1, pageSize: 5000 });
    return (result.items || []) as PurchaseOrder[];
  }

  async getPurchaseOrderById(id: string): Promise<PurchaseOrder | null> {
    const orders = await this.listPurchaseOrders();
    return orders.find((entry) => entry.id === id) || null;
  }

  async createPurchaseOrder(order: CreatePurchaseOrderRecord): Promise<PurchaseOrder> {
    const existingOrders = await this.listPurchaseOrders();
    const now = new Date().toISOString();

    const newOrder: PurchaseOrder = {
      ...order,
      id: order.id,
      orderNumber: generatePurchaseOrderNumber(existingOrders, order.documentType),
      status: 'active',
      createdAt: now,
      lockedById: undefined,
      lockedByName: undefined,
      lockedAt: undefined,
      cancelledAt: undefined,
      cancelledBy: undefined,
      cancelledReason: undefined,
    };

    await pgSavePurchaseOrders([newOrder]);
    return newOrder;
  }

  async addSupplierBalance(supplierId: string, delta: number): Promise<void> {
    if (!Number.isFinite(delta) || delta === 0) return;

    const supplier = await this.findSupplierById(supplierId);
    if (!supplier) return;

    const nextBalance = Number(supplier.balance || 0) + delta;
    await pgUpdateSupplier(supplierId, { balance: nextBalance });
  }

  async updatePurchaseOrder(id: string, patch: Partial<Pick<PurchaseOrder, 'taxInvoiceId' | 'linkedShipmentIds' | 'documentType'>>): Promise<void> {
    const orders = await this.listPurchaseOrders();
    const idx = orders.findIndex((o) => o.id === id);
    if (idx < 0) return;
    orders[idx] = { ...orders[idx], ...patch };
    await pgSavePurchaseOrders([orders[idx]]);
  }
}
