<?php

namespace App\Http\Controllers;

use App\Core\Repositories\InvoiceRepository;
use App\Core\Services\Payment\PaymentService;
use App\Models\Invoice;
use App\Support\InvoiceTemplateResolver;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;

class PublicInvoiceController extends Controller
{
    public function __construct(
        private InvoiceRepository $invoiceRepository,
        private PaymentService $paymentService
    ) {}

    /**
     * Display public invoice view
     */
    public function show(string $token): View|RedirectResponse
    {
        // Find invoice by public token
        $invoice = $this->invoiceRepository->getByPublicToken($token);

        if ($invoice) {
            $invoice->load(['customer', 'items', 'payments']);
        }

        if (! $invoice) {
            abort(404, 'Invoice not found');
        }

        // Mark invoice as viewed if not already
        if (! $invoice->viewed_at) {
            $invoice->update([
                'status' => 'viewed',
                'viewed_at' => now(),
            ]);
        }

        // Load company settings
        $companySettings = \App\Models\CompanySetting::getSettings();
        $currencies = \App\Models\Currency::where('is_active', true)->orderBy('is_default', 'desc')->get();
        $selectedCurrency = $currencies->where('code', $invoice->currency)->first();

        $templateKey = InvoiceTemplateResolver::resolveKeyForInvoice($invoice);
        $templateView = InvoiceTemplateResolver::webView($templateKey);

        // Calculate totals
        $subtotal = $invoice->items->sum(function ($item) {
            return $item->quantity * $item->unit_price;
        });

        $taxAmount = $invoice->items->sum(function ($item) {
            return ($item->quantity * $item->unit_price) * ($item->tax_rate / 100);
        });

        $discountType = $invoice->discount_type ?? 'fixed';
        $discountAmount = floatval($invoice->discount_amount ?? 0);
        $discount = 0;

        if ($discountType === 'percentage') {
            $discount = $subtotal * ($discountAmount / 100);
        } else {
            $discount = $discountAmount;
        }

        $total = $subtotal + $taxAmount - $discount;
        $paidAmount = floatval($invoice->paid_amount ?? 0);
        $balanceDue = max(0, $total - $paidAmount);

        // Format items for template
        $items = $invoice->items->map(function ($item) {
            return [
                'description' => $item->description,
                'notes' => $item->notes ?? '',
                'quantity' => $item->quantity,
                'unit_price' => $item->unit_price,
                'tax_rate' => $item->tax_rate,
                'total' => ($item->quantity * $item->unit_price) + (($item->quantity * $item->unit_price) * ($item->tax_rate / 100)),
            ];
        })->toArray();

        // Format data for template
        $data = [
            'invoice_number' => $invoice->invoice_number,
            'issue_date' => $invoice->issue_date->format('Y-m-d'),
            'due_date' => $invoice->due_date->format('Y-m-d'),
            'currency' => $invoice->currency,
            'notes' => $invoice->notes,
            'terms' => $invoice->terms,
            'signature_id' => $invoice->signature_id ?? null,
            'discount_type' => $invoice->discount_type,
            'discount_amount' => $invoice->discount_amount,
            'paid_amount' => $invoice->paid_amount,
        ];

        return view('invoices.public-view', [
            'invoice' => $invoice,
            'data' => $data,
            'companySettings' => $companySettings,
            'customer' => $invoice->customer,
            'currencies' => $currencies,
            'selectedCurrency' => $selectedCurrency,
            'items' => $items,
            'subtotal' => $subtotal,
            'taxAmount' => $taxAmount,
            'discount' => $discount,
            'total' => $total,
            'paidAmount' => $paidAmount,
            'balanceDue' => $balanceDue,
            'templateView' => $templateView,
        ]);
    }

    /**
     * Process payment from public invoice view
     */
    public function processPayment(Request $request, string $token): JsonResponse
    {
        // Find invoice by public token
        $invoice = $this->invoiceRepository->getByPublicToken($token);

        if (! $invoice) {
            return response()->json([
                'success' => false,
                'message' => 'Invoice not found',
            ], 404);
        }

        // Validate payment data
        $validated = $request->validate([
            'amount' => 'required|numeric|min:0.01|max:'.$invoice->balance,
            'payment_date' => 'required|date',
            'payment_method' => 'required|in:bank_transfer,account_transfer,cash,cheque,credit_card,online_payment,paypal,stripe,other',
            'transaction_id' => 'nullable|string|max:255',
            'notes' => 'nullable|string|max:1000',
        ]);

        try {
            // Record the payment
            $payment = $this->paymentService->recordPayment($invoice, [
                'amount' => $validated['amount'],
                'currency' => $invoice->currency,
                'payment_method' => $validated['payment_method'],
                'payment_date' => $validated['payment_date'],
                'transaction_id' => $validated['transaction_id'] ?? null,
                'reference' => $validated['transaction_id'] ?? null,
                'notes' => $validated['notes'] ?? null,
                'status' => 'pending', // Mark as pending for admin approval
            ]);

            return response()->json([
                'success' => true,
                'message' => 'Payment recorded successfully. It will be reviewed and confirmed shortly.',
                'payment' => [
                    'id' => $payment->id,
                    'amount' => $payment->amount,
                    'status' => $payment->status,
                ],
            ]);
        } catch (\Exception $e) {
            \Log::error('Public payment processing failed: '.$e->getMessage());

            return response()->json([
                'success' => false,
                'message' => 'Failed to record payment. Please try again or contact support.',
            ], 500);
        }
    }
}
