<?php

namespace App\Http\Controllers;

use App\Enums\PackageStatus;
use App\Models\Package;
use App\Services\PackageService;
use App\Services\PricingService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;

class PricingController extends Controller
{
    public function preview(Request $request, PricingService $pricingService): JsonResponse
    {
        $this->assertPricingAccess();

        $validated = $request->validate([
            'items' => ['nullable', 'array'],
            'items.*.description' => ['nullable', 'string', 'max:500'],
            'items.*.quantity' => ['nullable', 'numeric', 'min:0'],
            'items.*.unit_price' => ['nullable', 'numeric', 'min:0'],
            'items.*.charge_basis' => ['nullable', 'string'],
            'items.*.guest_count' => ['nullable', 'integer', 'min:0'],
            'items.*.billable_days' => ['nullable', 'integer', 'min:1'],
            'items.*.billable_hours' => ['nullable', 'numeric', 'min:0'],
            'items.*.discount_amount' => ['nullable', 'numeric', 'min:0'],
            'items.*.tax_rate' => ['nullable', 'numeric', 'min:0'],
            'items.*.fixed_amount' => ['nullable', 'numeric', 'min:0'],
            'overall_discount_amount' => ['nullable', 'numeric', 'min:0'],
            'service_charge_rate' => ['nullable', 'numeric', 'min:0'],
            'service_charge_amount' => ['nullable', 'numeric', 'min:0'],
        ]);

        $items = $validated['items'] ?? [];
        $lineTotals = [];

        foreach ($items as $line) {
            $lineTotals[] = $pricingService->calculateLineAmount($line);
        }

        $document = $pricingService->calculateDocumentTotals($items, [
            'overall_discount_amount' => $validated['overall_discount_amount'] ?? 0,
            'service_charge_rate' => $validated['service_charge_rate'] ?? 0,
            'service_charge_amount' => $validated['service_charge_amount'] ?? 0,
        ]);

        return response()->json([
            'line_totals' => $lineTotals,
            'document_totals' => $document,
        ]);
    }

    public function packageLines(Request $request, PackageService $packageService): JsonResponse
    {
        $this->assertPricingAccess();

        $validated = $request->validate([
            'package_ids' => ['required', 'array', 'min:1'],
            'package_ids.*' => ['integer', 'exists:packages,id'],
            'guest_count' => ['nullable', 'integer', 'min:0'],
            'billable_days' => ['nullable', 'integer', 'min:1'],
            'billable_hours' => ['nullable', 'numeric', 'min:0'],
        ]);

        $guestCount = max(1, (int) ($validated['guest_count'] ?? 1));
        $billableDays = max(1, (int) ($validated['billable_days'] ?? 1));
        $billableHours = (float) ($validated['billable_hours'] ?? 1);

        $lines = [];

        $packages = Package::query()
            ->with('items.product')
            ->whereIn('id', $validated['package_ids'])
            ->where('status', PackageStatus::Active)
            ->get();

        foreach ($packages as $package) {
            foreach ($packageService->buildEstimateLines($package, $guestCount, $billableDays, $billableHours) as $line) {
                if (empty($line['description'])) {
                    $line['description'] = $package->name;
                }
                $line['package_id'] = $package->id;
                $lines[] = $line;
            }
        }

        return response()->json(['lines' => $lines]);
    }

    private function assertPricingAccess(): void
    {
        $user = auth()->user();

        if ($user === null) {
            abort(403);
        }

        $allowed = $user->hasPermission('quotations.view')
            || $user->hasPermission('quotations.create')
            || $user->hasPermission('invoices.view')
            || $user->hasPermission('invoices.create')
            || $user->hasPermission('packages.view')
            || $user->hasPermission('bookings.view');

        abort_unless($allowed, 403);
    }
}
