<?php

namespace App\Http\Controllers\API;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use App\Models\Sale;
use App\Models\SaleItem;
use App\Models\SalePayment;
use App\Models\Product;
use App\Models\InventoryLog;
use App\Models\AuditLog;

class BillingController extends Controller
{
    public function store(Request $request)
    {
        $validated = $request->validate([
            'customer_name' => 'nullable|string',
            'customer_phone' => 'nullable|string',
            'subtotal' => 'required|numeric|min:0',
            'discount_amount' => 'nullable|numeric|min:0',
            'gst_amount' => 'nullable|numeric|min:0',
            'total_amount' => 'required|numeric|min:0',
            'status' => 'nullable|in:completed,held',
            'items' => 'required|array|min:1',
            'items.*.product_id' => 'nullable|exists:products,id',
            'items.*.barcode' => 'required|string',
            'items.*.name' => 'required|string',
            'items.*.size' => 'nullable|string',
            'items.*.color' => 'nullable|string',
            'items.*.quantity' => 'required|integer|min:1',
            'items.*.unit_price' => 'required|numeric|min:0',
            'items.*.discount' => 'nullable|numeric|min:0',
            'items.*.gst_rate' => 'nullable|numeric|min:0',
            'payments' => 'nullable|array',
            'payments.*.payment_method' => 'required|in:cash,card,upi',
            'payments.*.amount' => 'required|numeric|min:0',
            'customer_name' => 'nullable|string',
            'customer_phone' => 'nullable|string',
            'customer_address' => 'nullable|string',
            'due_date' => 'nullable|date',
            'notes' => 'nullable|string',
            'subtotal' => 'required|numeric',
            'discount_amount' => 'nullable|numeric',
            'gst_amount' => 'nullable|numeric',
            'total_amount' => 'required|numeric',
            'status' => 'nullable|string|in:completed,held,pending,partially_paid',
            'items' => 'required|array|min:1',
            'items.*.product_id' => 'nullable|exists:products,id',
            'items.*.barcode' => 'required|string',
            'items.*.name' => 'required|string',
            'items.*.size' => 'nullable|string',
            'items.*.color' => 'nullable|string',
            'items.*.quantity' => 'required|integer|min:1',
            'items.*.unit_price' => 'required|numeric',
            'items.*.discount' => 'nullable|numeric',
            'items.*.gst_rate' => 'nullable|numeric',
            'payments' => 'nullable|array',
            'payments.*.payment_method' => 'required|string',
            'payments.*.amount' => 'required|numeric',
            'payments.*.transaction_id' => 'nullable|string',
        ]);

        return DB::transaction(function () use ($request, $validated) {
            $invoiceNumber = 'TXT-' . date('YmdHis') . '-' . rand(100, 999);

            $status = $validated['status'] ?? 'completed';

            $sale = Sale::create([
                'invoice_number' => $invoiceNumber,
                'customer_name' => $validated['customer_name'] ?? 'Walk-in Customer',
                'customer_phone' => $validated['customer_phone'] ?? null,
                'customer_address' => $validated['customer_address'] ?? null,
                'subtotal' => $validated['subtotal'],
                'discount_amount' => $validated['discount_amount'] ?? 0,
                'gst_amount' => $validated['gst_amount'] ?? 0,
                'total_amount' => $validated['total_amount'],
                'status' => $status,
                'held_at' => $status === 'held' ? now() : null,
                'due_date' => $validated['due_date'] ?? null,
                'notes' => $validated['notes'] ?? null,
                'created_by' => $request->user()?->id,
            ]);

            foreach ($validated['items'] as $item) {
                $product = null;
                if (!empty($item['product_id'])) {
                    $product = Product::find($item['product_id']);
                }

                $itemTotal = ($item['unit_price'] * $item['quantity']) - ($item['discount'] ?? 0);

                SaleItem::create([
                    'sale_id' => $sale->id,
                    'product_id' => $product?->id,
                    'barcode' => $item['barcode'],
                    'name' => $item['name'],
                    'size' => $item['size'] ?? ($product?->size ?? 'M'),
                    'color' => $item['color'] ?? ($product?->color ?? 'Black'),
                    'quantity' => $item['quantity'],
                    'unit_price' => $item['unit_price'],
                    'cost_price' => $product?->cost_price ?? 0,
                    'discount' => $item['discount'] ?? 0,
                    'gst_rate' => $item['gst_rate'] ?? ($product?->gst_rate ?? 18),
                    'total' => $itemTotal,
                ]);

                // Stock Out automatically if sale completed OR credit sale (pending)
                if ($product && ($status === 'completed' || $status === 'pending' || $status === 'partially_paid')) {
                    $product->decrement('current_stock', $item['quantity']);

                    InventoryLog::create([
                        'product_id' => $product->id,
                        'type' => 'stock_out',
                        'quantity' => $item['quantity'],
                        'reason' => "Sale Invoice {$sale->invoice_number}" . ($status === 'pending' ? " (Credit Sale)" : ""),
                        'created_by' => $request->user()?->id,
                    ]);
                }
            }

            // Save Payments
            if (!empty($validated['payments'])) {
                foreach ($validated['payments'] as $payment) {
                    SalePayment::create([
                        'sale_id' => $sale->id,
                        'payment_method' => $payment['payment_method'],
                        'amount' => $payment['amount'],
                        'transaction_id' => $payment['transaction_id'] ?? null,
                    ]);
                }
            } else if ($status === 'completed') {
                SalePayment::create([
                    'sale_id' => $sale->id,
                    'payment_method' => 'cash',
                    'amount' => $validated['total_amount'],
                ]);
            } else if ($status === 'pending') {
                SalePayment::create([
                    'sale_id' => $sale->id,
                    'payment_method' => 'credit',
                    'amount' => $validated['total_amount'],
                ]);
            }

            AuditLog::create([
                'user_id' => $request->user()?->id,
                'user_name' => $request->user()?->name,
                'action' => 'BILL_CREATE',
                'module' => 'BILLING',
                'description' => "Processed sale invoice {$sale->invoice_number} (Status: {$status}) for total ₹{$sale->total_amount}",
                'ip_address' => $request->ip(),
            ]);

            return response()->json([
                'success' => true,
                'message' => 'Sale invoice created successfully',
                'data' => $sale->load(['items', 'payments', 'cashier']),
            ], 201);
        });
    }

    public function getHeldBills()
    {
        $heldSales = Sale::with(['items', 'payments'])
            ->where('status', 'held')
            ->orderBy('created_at', 'desc')
            ->get();

        return response()->json([
            'success' => true,
            'data' => $heldSales,
        ]);
    }

    public function resumeBill(Request $request, $id)
    {
        $sale = Sale::find($id);
        if (!$sale || $sale->status !== 'held') {
            return response()->json(['success' => false, 'message' => 'Held bill not found'], 404);
        }

        $sale->update([
            'status' => 'completed',
            'held_at' => null,
        ]);

        foreach ($sale->items as $item) {
            if ($item->product_id) {
                $product = Product::find($item->product_id);
                if ($product) {
                    $product->decrement('current_stock', $item->quantity);
                    InventoryLog::create([
                        'product_id' => $product->id,
                        'type' => 'stock_out',
                        'quantity' => $item->quantity,
                        'reason' => "Resumed Sale Invoice {$sale->invoice_number}",
                        'created_by' => $request->user()?->id,
                    ]);
                }
            }
        }

        return response()->json([
            'success' => true,
            'message' => 'Bill resumed and completed',
            'data' => $sale->load(['items', 'payments', 'cashier']),
        ]);
    }

    public function getCreditSales()
    {
        $creditSales = Sale::with(['items', 'payments', 'cashier'])
            ->whereIn('status', ['pending', 'partially_paid', 'completed'])
            ->where(function ($query) {
                $query->whereHas('payments', function ($q) {
                    $q->where('payment_method', 'credit');
                })->orWhereIn('status', ['pending', 'partially_paid']);
            })
            ->orderBy('created_at', 'desc')
            ->get()
            ->map(function ($sale) {
                $paidAmount = $sale->payments->where('payment_method', '!=', 'credit')->sum('amount');
                $outstandingAmount = max(0, $sale->total_amount - $paidAmount);
                $sale->paid_amount = $paidAmount;
                $sale->outstanding_amount = $outstandingAmount;
                return $sale;
            });

        return response()->json([
            'success' => true,
            'data' => $creditSales,
        ]);
    }

    public function recordCreditPayment(Request $request, $id)
    {
        $validated = $request->validate([
            'amount' => 'required|numeric|min:0.01',
            'payment_method' => 'required|string|in:cash,card,upi',
            'transaction_id' => 'nullable|string',
            'notes' => 'nullable|string',
        ]);

        $sale = Sale::with('payments')->find($id);
        if (!$sale) {
            return response()->json(['success' => false, 'message' => 'Invoice not found'], 404);
        }

        SalePayment::create([
            'sale_id' => $sale->id,
            'payment_method' => $validated['payment_method'],
            'amount' => $validated['amount'],
            'transaction_id' => $validated['transaction_id'] ?? null,
        ]);

        // Recalculate total paid
        $totalPaid = $sale->payments()->where('payment_method', '!=', 'credit')->sum('amount');
        
        $newStatus = $sale->status;
        if ($totalPaid >= $sale->total_amount) {
            $newStatus = 'completed';
        } else if ($totalPaid > 0) {
            $newStatus = 'partially_paid';
        }

        $sale->update(['status' => $newStatus]);

        AuditLog::create([
            'user_id' => $request->user()?->id,
            'user_name' => $request->user()?->name,
            'action' => 'RECORD_CREDIT_PAYMENT',
            'module' => 'BILLING',
            'description' => "Recorded payment of ₹{$validated['amount']} ({$validated['payment_method']}) for Invoice {$sale->invoice_number}. New Status: {$newStatus}",
            'ip_address' => $request->ip(),
        ]);

        return response()->json([
            'success' => true,
            'message' => 'Payment recorded successfully',
            'data' => $sale->load(['items', 'payments', 'cashier']),
        ]);
    }

    public function deleteCreditSale(Request $request, $id)
    {
        $sale = Sale::with('payments')->find($id);
        if (!$sale) {
            return response()->json(['success' => false, 'message' => 'Credit sale record not found'], 404);
        }

        $paidAmount = $sale->payments()->where('payment_method', '!=', 'credit')->sum('amount');
        $outstanding = max(0, $sale->total_amount - $paidAmount);

        if ($outstanding > 0 || $sale->status !== 'completed') {
            return response()->json([
                'success' => false,
                'message' => 'Only fully PAID credit sales can be deleted. Pending or Partially Paid credit sales cannot be deleted.',
            ], 400);
        }

        AuditLog::create([
            'user_id' => $request->user()?->id,
            'user_name' => $request->user()?->name,
            'action' => 'DELETE_CREDIT_SALE',
            'module' => 'CREDIT_SALES',
            'description' => "Deleted paid credit sale Invoice {$sale->invoice_number} for customer {$sale->customer_name}",
            'ip_address' => $request->ip(),
        ]);

        $sale->delete();

        return response()->json([
            'success' => true,
            'message' => 'Paid credit sale deleted successfully',
        ]);
    }
}
