<?php
declare(strict_types=1);
namespace App\Services;

use App\Repositories\CustomerRepository;
use App\Repositories\InvoiceRepository;
use App\Repositories\ItemRepository;

final class InvoiceService {
    public function __construct(
        private ?CustomerRepository $customers = null,
        private ?InvoiceRepository $invoices = null,
        private ?ItemRepository $items = null,
        private ?AuditService $audit = null,
    ) {
        $this->customers ??= new CustomerRepository();
        $this->invoices ??= new InvoiceRepository();
        $this->items ??= new ItemRepository();
        $this->audit ??= new AuditService();
    }

    public function createFromRequest(array $post): int {
        $deliveryDate = trim((string)($post['delivery_date'] ?? date('Y-m-d')));
        $returnDate = trim((string)($post['return_date'] ?? $deliveryDate));
        if ($deliveryDate === '' || $returnDate === '') throw new \RuntimeException('تاريخ التسليم والإرجاع مطلوبان');
        if ($returnDate < $deliveryDate) throw new \RuntimeException('تاريخ الإرجاع يجب أن يكون بعد أو مساويًا لتاريخ التسليم');

        $existingCustomer = $this->customers->findByIdentifier((string)(trim((string)($post['customer_phone'] ?? '')) ?: trim((string)($post['customer_civil_id'] ?? ''))));
        if ($existingCustomer && (int)($existingCustomer['is_blacklisted'] ?? 0) === 1) {
            throw new \RuntimeException('هذا العميل محظور ولا يمكن إنشاء فاتورة له' . (!empty($existingCustomer['blacklist_reason']) ? ' — ' . $existingCustomer['blacklist_reason'] : ''));
        }

        $customerId = $this->customers->createOrUpdate([
            'full_name' => trim((string)($post['customer_name'] ?? 'عميل')),
            'phone' => trim((string)($post['customer_phone'] ?? '')),
            'civil_id' => trim((string)($post['customer_civil_id'] ?? '')),
        ]);

        $days = (int)max(1, ((strtotime($returnDate) - strtotime($deliveryDate)) / 86400) + 1);
        $rows = $post['lines'] ?? [];
        if (!$rows) throw new \RuntimeException('أضف عنصرًا واحدًا على الأقل إلى الفاتورة');

        $lines = [];
        $invoiceTypeSet = [];
        foreach ($rows as $line) {
            $itemId = (int)($line['item_id'] ?? 0);
            $lineType = ($line['line_type'] ?? 'rental') === 'sale' ? 'sale' : 'rental';
            $unitPrice = (float)($line['unit_price'] ?? 0);
            $quantity = max(1, (int)($line['quantity'] ?? 1));
            $item = $this->items->find($itemId);
            if (!$item) throw new \RuntimeException('أحد العناصر غير موجود');
            if ($lineType === 'rental') {
                $available = $this->items->availableForPeriod(null, $deliveryDate, $returnDate);
                $availableIds = array_map(fn($r)=>(int)$r['id'], $available);
                if (!in_array($itemId, $availableIds, true)) {
                    throw new \RuntimeException('العنصر ' . $item['item_code'] . ' غير متاح في الفترة المحددة');
                }
            }
            $finalPrice = $lineType === 'sale' ? ($unitPrice * $quantity) : ($unitPrice * $quantity * $days);
            $lines[] = [
                'item_id' => $itemId,
                'line_type' => $lineType,
                'unit_price' => $unitPrice,
                'days_count' => $lineType === 'sale' ? 1 : $days,
                'quantity' => $quantity,
                'final_price' => $finalPrice,
            ];
            $invoiceTypeSet[$lineType] = true;
        }
        $invoiceType = count($invoiceTypeSet) > 1 ? 'mixed' : array_key_first($invoiceTypeSet);
        $payments = $post['payments'] ?? [];

        $invoiceId = $this->invoices->create([
            'invoice_no' => $this->invoices->nextNumber(),
            'customer_id' => $customerId,
            'invoice_type' => $invoiceType,
            'delivery_date' => $deliveryDate,
            'return_date' => $returnDate,
            'created_by' => (int)($_SESSION['uid'] ?? 1),
            'signature_name' => trim((string)($post['signature_name'] ?? '')),
            'signature_data' => trim((string)($post['signature_data'] ?? '')),
            'notes' => trim((string)($post['notes'] ?? '')),
        ], $lines, $payments);

        $this->audit->log('invoices', 'create', $invoiceId, ['customer_id'=>$customerId, 'lines_count'=>count($lines)]);
        return $invoiceId;
    }
}
