<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Events\SaleCreated;
use App\Events\StockUpdated;
use App\Mail\SaleReceiptMail;
use App\Models\Sale;
use App\Services\ActivityLogger;
use App\Services\DashboardService;
use App\Services\NotificationService;
use App\Services\SaleService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Mail;
use Illuminate\Validation\Rule;
use Barryvdh\DomPDF\Facade\Pdf;

class SaleController extends Controller
{
    public function __construct(
        protected SaleService $saleService
    ) {}

    public function index(Request $request)
    {
        $query = Sale::with(['customer', 'user', 'items.product']);

        if ($request->has('status') && $request->filled('status')) {
            $query->where('status', $request->input('status'));
        }

        if ($request->has('start_date') && $request->has('end_date')) {
            $query->whereBetween('sale_date', [
                $request->input('start_date'),
                $request->input('end_date')
            ]);
        }

        if ($request->has('customer_id') && $request->filled('customer_id')) {
            $query->where('customer_id', $request->input('customer_id'));
        }

        if ($request->has('search') && $request->filled('search')) {
            $search = $request->input('search');
            $query->where('sale_number', 'like', "%{$search}%");
        }

        $sales = $query->latest()->paginate(min((int) $request->input('per_page', 15), 100));

        return response()->json($sales);
    }

    public function store(Request $request)
    {
        $this->authorize('create-sales');

        $validated = $request->validate([
            'customer_id' => ['nullable', Rule::exists('customers', 'id')->where('organization_id', app('current_organization_id'))],
            'sale_date' => 'nullable|date',
            'subtotal' => 'required|numeric|min:0',
            'tax' => 'nullable|numeric|min:0',
            'discount' => 'nullable|numeric|min:0',
            'total' => 'required|numeric|min:0',
            'amount_paid' => 'required|numeric|min:0',
            'change_amount' => 'nullable|numeric|min:0',
            'debt_serviced' => 'nullable|numeric|min:0',
            'notes' => 'nullable|string',
            'items' => 'required|array|min:1',
            'items.*.product_id' => ['required', Rule::exists('products', 'id')->where('organization_id', app('current_organization_id'))],
            'items.*.quantity' => 'required|integer|min:1',
            'items.*.unit_price' => 'required|numeric|min:0',
            'items.*.discount' => 'nullable|numeric|min:0',
            'items.*.subtotal' => 'required|numeric|min:0',
            'payments' => 'nullable|array',
            'payments.*.method'     => 'required_with:payments|in:cash,card,transfer',
            'payments.*.amount'     => 'required_with:payments|numeric|min:0',
            'payments.*.reference'  => 'nullable|string',
            'points_redeemed'       => 'nullable|integer|min:0',
            'credit_applied'        => 'nullable|numeric|min:0',
        ]);

        $validated['user_id'] = $request->user()->id;

        try {
            $sale = $this->saleService->create($validated);

            ActivityLogger::log(
                'sale_created',
                "Sale {$sale->sale_number} created for " . ($sale->customer?->name ?? 'walk-in') . " — total {$sale->total}",
                $sale
            );

            $orgId    = app('current_organization_id');
            $branchId = app()->bound('current_branch_id') ? app('current_branch_id') : null;

            DashboardService::clearCache($orgId, $branchId ?? 0);

            // Broadcast real-time events
            $productIds = collect($validated['items'])->pluck('product_id')->unique()->values()->all();
            broadcast(new SaleCreated(
                organizationId: $orgId,
                saleId:         $sale->id,
                saleNumber:     $sale->sale_number,
                total:          (float) $sale->total,
                status:         $sale->status,
                customerName:   $sale->customer?->name ?? 'Walk-in',
                branchId:       $branchId,
                createdAt:      $sale->created_at->toIso8601String(),
            ));
            broadcast(new StockUpdated(
                organizationId: $orgId,
                branchId:       $branchId,
                productIds:     $productIds,
                source:         'sale',
            ));

            // Notify admins/managers of the new sale
            $actor     = $request->user();
            $customer  = $sale->customer?->name ?? 'Walk-in';
            $formatted = number_format((float) $sale->total, 2);
            NotificationService::notifyRoles(
                $orgId,
                $branchId,
                ['super-admin', 'admin'],
                'sale_completed',
                'New Sale — ' . $sale->sale_number,
                "{$actor->name} completed a sale for {$customer}. Total: {$formatted}",
                ['sale_id' => $sale->id, 'sale_number' => $sale->sale_number, 'total' => $sale->total],
                $actor->id
            );

            return response()->json($sale, 201);
        } catch (\Exception $e) {
            return response()->json(['message' => $e->getMessage()], 422);
        }
    }

    public function show(Sale $sale)
    {
        return response()->json($sale->load(['customer', 'user', 'items.product', 'payments']));
    }

    public function addPayment(Request $request, Sale $sale)
    {
        $this->authorize('edit-sales');

        if ($sale->outstanding_balance <= 0) {
            return response()->json(['message' => 'This sale has no outstanding balance.'], 422);
        }

        $validated = $request->validate([
            'amount' => 'required|numeric|min:0.01',
            'method' => 'required|in:cash,card,transfer,mixed',
            'reference' => 'nullable|string',
            'notes' => 'nullable|string',
        ]);

        try {
            $sale = $this->saleService->addPayment($sale, $validated);

            ActivityLogger::log(
                'payment_added',
                "Payment of {$validated['amount']} added to sale {$sale->sale_number}",
                $sale
            );

            return response()->json($sale);
        } catch (\Exception $e) {
            return response()->json(['message' => $e->getMessage()], 422);
        }
    }

    public function processReturn(Request $request, Sale $sale)
    {
        $this->authorize('process-returns');

        $validated = $request->validate([
            'total_amount' => 'required|numeric|min:0',
            'reason' => 'nullable|string',
            'notes' => 'nullable|string',
            'items' => 'required|array|min:1',
            'items.*.sale_item_id' => ['required', Rule::exists('sale_items', 'id')],
            'items.*.quantity' => 'required|integer|min:1',
        ]);

        $validated['user_id'] = $request->user()->id;

        try {
            $return = $this->saleService->processReturn($sale, $validated);

            ActivityLogger::log(
                'return_initiated',
                "Return initiated for sale {$sale->sale_number}",
                $sale
            );

            return response()->json([
                'message' => 'Return created successfully',
                'return' => $return,
            ], 201);
        } catch (\Exception $e) {
            return response()->json(['message' => $e->getMessage()], 422);
        }
    }

    public function receipt(Sale $sale)
    {
        try {
            $sale->load(['customer', 'items.product', 'payments', 'user', 'branch']);
            
            $data = [
                'sale' => $sale,
                'settings' => [
                    'business_name' => \App\Models\Setting::getValue('business_name', 'INVENTINO'),
                    'business_logo' => \App\Models\Setting::getValue('business_logo', null),
                    'business_address' => \App\Models\Setting::getValue('address', ''),
                    'business_phone' => \App\Models\Setting::getValue('phone', ''),
                    'business_email' => \App\Models\Setting::getValue('email', ''),
                    'business_website' => \App\Models\Setting::getValue('website', ''),
                    'currency_symbol' => \App\Models\Setting::getValue('currency_symbol', '₦'),
                    'receipt_header'  => \App\Models\Setting::getValue('receipt_header', 'Thank you for your purchase'),
                    'receipt_footer'  => \App\Models\Setting::getValue('receipt_footer', 'Please visit us again!'),
                    'branch_name'    => $sale->branch?->name ?? '',
                    'branch_address' => $sale->branch?->address ?? '',
                ],
            ];

            $pdf = Pdf::loadView('receipts.sale', $data)
                ->setPaper([0, 0, 226.77, 841.89], 'portrait') // 80mm width
                ->setOption('isHtml5ParserEnabled', true)
                ->setOption('isRemoteEnabled', true)
                ->setOption('chroot', public_path());

            return $pdf->stream('receipt-' . $sale->sale_number . '.pdf');
        } catch (\Exception $e) {
            \Log::error('Receipt generation error: ' . $e->getMessage(), [
                'sale_id' => $sale->id,
                'trace' => $e->getTraceAsString()
            ]);
            return response()->json(['error' => $e->getMessage(), 'message' => 'Failed to generate receipt. Please check server logs.'], 500);
        }
    }

    public function emailReceipt(Request $request, Sale $sale)
    {
        $validated = $request->validate([
            'email' => 'nullable|email|max:255',
        ]);

        // Resolve recipient: explicit email → customer email → error
        $recipient = $validated['email']
            ?? $sale->customer?->email
            ?? null;

        if (!$recipient) {
            return response()->json([
                'message' => 'No email address provided and this sale has no customer email on file.',
            ], 422);
        }

        try {
            $sale->load(['customer', 'items.product', 'payments', 'user', 'branch']);

            Mail::to($recipient)->send(new SaleReceiptMail($sale));

            ActivityLogger::log(
                'receipt_emailed',
                "Receipt for sale {$sale->sale_number} emailed to {$recipient}",
                $sale
            );

            return response()->json(['message' => "Receipt sent to {$recipient}."]);
        } catch (\Exception $e) {
            \Log::error('Email receipt error: ' . $e->getMessage(), [
                'sale_id' => $sale->id,
                'trace'   => $e->getTraceAsString(),
            ]);
            return response()->json(['message' => 'Failed to send receipt. Please try again.'], 500);
        }
    }
}
