<?php

namespace App\Services\Sales;

use App\Services\BaseService;
use App\Repositories\QuotationRepository;
use App\Models\Quotation;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Facades\DB;
use Barryvdh\DomPDF\Facade\Pdf;

class QuotationService extends BaseService
{
    protected QuotationRepository $quotationRepository;

    public function __construct(QuotationRepository $repository)
    {
        parent::__construct($repository);
        $this->quotationRepository = $repository;
    }

    /**
     * Get all quotations with customer info
     */
    public function getAllWithCustomer(): Collection
    {
        return $this->quotationRepository->getAllWithCustomer();
    }

    /**
     * Get quotations by RFQ
     */
    public function getByRfq(int $rfqId): Collection
    {
        return $this->quotationRepository->getByRfq($rfqId);
    }

    /**
     * Get quotations by customer
     */
    public function getByCustomer(int $customerId): Collection
    {
        return $this->quotationRepository->getByCustomer($customerId);
    }

    /**
     * Get quotations by date range
     */
    public function getByDateRange(string $startDate, string $endDate): Collection
    {
        return $this->quotationRepository->getByDateRange($startDate, $endDate);
    }

    /**
     * Create quotation from RFQ
     */
    public function createFromRfq(int $rfqId, array $additionalData = []): Quotation
    {
        return DB::transaction(function () use ($rfqId, $additionalData) {
            $rfq = \App\Models\Rfq::with('customerInfo')->findOrFail($rfqId);

            $data = [
                'quotation_no' => $this->generateQuotationNumber(),
                'quotation_date' => now()->toDateString(),
                'customer_name' => $rfq->customer,
                'address' => $rfq->customerInfo?->address ?? '',
                'gst' => $rfq->customerInfo?->gstn ?? '',
                'phone' => $rfq->customerInfo?->mobile ?? '',
                'email' => $rfq->customerInfo?->email ?? '',
                'cust_ref_no' => $rfq->cus_ref_no,
                'rfq_no' => $rfq->id,
                'rfq_date' => $rfq->rfq_date,
                'part_no' => $rfq->part_no,
                'project_material_no' => $rfq->project_material_no,
                'drawing_no' => $rfq->drawing_no,
                'drawing_rev' => $rfq->drawing_rev,
                'quantity' => $rfq->quantity,
                'quantity_uom' => $rfq->uom,
                'description' => $rfq->description,
                'product_type' => $rfq->product_type,
                'note' => $rfq->note,
            ];

            // Merge additional data (raw_materials, conversion_costs, etc.)
            $data = array_merge($data, $additionalData);

            $quotation = $this->quotationRepository->create($data);

            $this->logAction('created Quotation from RFQ', [
                'quotation_id' => $quotation->id,
                'quotation_no' => $quotation->quotation_no,
                'rfq_id' => $rfqId,
            ]);

            return $quotation;
        });
    }

    /**
     * Create quotation
     */
    public function createQuotation(array $data): Quotation
    {
        return DB::transaction(function () use ($data) {
            // Generate quotation number if not provided
            if (empty($data['quotation_no'])) {
                $data['quotation_no'] = $this->generateQuotationNumber();
            }

            // Calculate totals
            $data = $this->calculateTotals($data);

            $quotation = $this->quotationRepository->create($data);

            $this->logAction('created Quotation', [
                'quotation_id' => $quotation->id,
                'quotation_no' => $quotation->quotation_no,
            ]);

            return $quotation;
        });
    }

    /**
     * Update quotation
     */
    public function updateQuotation(int $id, array $data): Quotation
    {
        return DB::transaction(function () use ($id, $data) {
            // Calculate totals
            $data = $this->calculateTotals($data);

            $quotation = $this->quotationRepository->update($id, $data);

            $this->logAction('updated Quotation', [
                'quotation_id' => $quotation->id,
                'quotation_no' => $quotation->quotation_no,
            ]);

            return $quotation;
        });
    }

    /**
     * Calculate totals for quotation
     */
    protected function calculateTotals(array $data): array
    {
        $subTotal = 0;

        // Calculate raw materials total
        if (!empty($data['raw_materials']) && is_array($data['raw_materials'])) {
            foreach ($data['raw_materials'] as $material) {
                $subTotal += floatval($material['total'] ?? 0);
            }
        }

        // Calculate conversion costs total
        if (!empty($data['conversion_costs']) && is_array($data['conversion_costs'])) {
            foreach ($data['conversion_costs'] as $cost) {
                $subTotal += floatval($cost['total'] ?? 0);
            }
        }

        // Add packing charges
        if (!empty($data['packing_charges']) && is_array($data['packing_charges'])) {
            foreach ($data['packing_charges'] as $charge) {
                $subTotal += floatval($charge['total'] ?? 0);
            }
        }

        $data['sub_total'] = $subTotal;
        $discount = floatval($data['discount'] ?? 0);
        $roundUp = floatval($data['round_up'] ?? 0);
        $data['grand_total'] = $subTotal - $discount + $roundUp;

        return $data;
    }

    /**
     * Generate next quotation number
     */
    public function generateQuotationNumber(): string
    {
        $year = date('Y');
        $prefix = "QTN/{$year}";
        return nextNumber($prefix, 'quotations', 'quotation_no', 2);
    }

    /**
     * Get for DataTable
     */
    public function getForDataTable()
    {
        return $this->quotationRepository->getForDataTableWithRelations();
    }

    /**
     * Get quotations available for sales order
     */
    public function getAvailableForSalesOrder(): Collection
    {
        return $this->quotationRepository->getAvailableForSalesOrder();
    }

    /**
     * Search quotations
     */
    public function search(string $term): Collection
    {
        return $this->quotationRepository->search($term);
    }

    /**
     * Generate PDF for quotation
     */
    public function generatePdf(int $id, string $viewPath): \Illuminate\Http\Response
    {
        $quotation = $this->quotationRepository->with(['customer'])->find($id);

        $pdf = Pdf::loadView($viewPath, compact('quotation'));
        return $pdf->download("quotation-{$quotation->quotation_no}.pdf");
    }

    /**
     * Clone quotation
     */
    public function clone(int $id): Quotation
    {
        $original = $this->quotationRepository->findOrFail($id);

        $data = $original->toArray();
        unset($data['id'], $data['created_at'], $data['updated_at']);
        $data['quotation_no'] = $this->generateQuotationNumber();
        $data['quotation_date'] = now()->toDateString();

        return $this->quotationRepository->create($data);
    }
}
