<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\ShopContact;
use App\Models\ShopContactAccountTransaction;
use App\Models\ShopInvoice;
use App\Models\ShopGoodsReceipt;
use App\Models\ShopInvoiceReturn;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Barryvdh\DomPDF\Facade\Pdf;

class ShopApiController extends Controller
{
    public function getContactInfo(Request $request): JsonResponse
    {
        $request->validate([
            'contact_code' => 'required|string',
            'shop_id' => 'required|string'
        ]);

        try {
            $contact = ShopContact::with('shop')
                ->where('code', $request->contact_code)
                ->where('shop_id', $request->shop_id)
                ->first();

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

            // Add formatted CNIC and shop name if CNIC exists
            $contactData = $contact->toArray();
            if ($contact->cnic) {
                $cnic = preg_replace('/[^0-9]/', '', $contact->cnic);
                if (strlen($cnic) === 13) {
                    $contactData['formatted_cnic'] = substr($cnic, 0, 5) . '-' . substr($cnic, 5, 7) . '-' . substr($cnic, 12, 1);
                }
            }

            // Add shop name
            $contactData['shop_name'] = $contact->shop ? $contact->shop->name : 'N/A';

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

        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Error retrieving contact information: ' . $e->getMessage()
            ], 500);
        }
    }

    public function getInvoiceInfo(Request $request): JsonResponse
    {
        $request->validate([
            'invoice_code' => 'required|string',
            'shop_id' => 'required|string'
        ]);

        try {
            $invoice = ShopInvoice::with(['items.product'])
                ->where('code', $request->invoice_code)
                ->where('shop_id', $request->shop_id)
                ->first();

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

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

        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Error retrieving invoice information: ' . $e->getMessage()
            ], 500);
        }
    }

    public function getGoodsReceiptInfo(Request $request): JsonResponse
    {
        $request->validate([
            'receipt_code' => 'required|string',
            'shop_id' => 'required|string'
        ]);

        try {
            $receipt = ShopGoodsReceipt::with(['items.product'])
                ->where('code', $request->receipt_code)
                ->where('shop_id', $request->shop_id)
                ->first();

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

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

        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Error retrieving goods receipt information: ' . $e->getMessage()
            ], 500);
        }
    }

    public function getInvoiceReturnInfo(Request $request): JsonResponse
    {
        $request->validate([
            'return_code' => 'required|string',
            'shop_id' => 'required|string'
        ]);

        try {
            $invoiceReturn = ShopInvoiceReturn::with(['items.product'])
                ->where('code', $request->return_code)
                ->where('shop_id', $request->shop_id)
                ->first();

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

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

        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Error retrieving invoice return information: ' . $e->getMessage()
            ], 500);
        }
    }

    public function downloadInvoicePDF($invoiceCode, $shopId)
    {
        try {
            $invoice = ShopInvoice::with(['items.product'])
                ->where('code', $invoiceCode)
                ->where('shop_id', $shopId)
                ->first();

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

            // Calculate balance
            $balance = ($invoice->total_amount ?? 0) - ($invoice->discount_amount ?? 0) - ($invoice->paid_amount ?? 0);

            $pdf = Pdf::loadView('pdf.invoice', compact('invoice', 'balance'));
            $pdf->setPaper('a4', 'portrait');

            return $pdf->download('invoice-' . $invoiceCode . '.pdf');

        } catch (\Exception $e) {
            abort(500, 'Error generating PDF: ' . $e->getMessage());
        }
    }

    public function downloadGoodsReceiptPDF($receiptCode, $shopId)
    {
        try {
            $receipt = ShopGoodsReceipt::with(['items.product'])
                ->where('code', $receiptCode)
                ->where('shop_id', $shopId)
                ->first();

            if (!$receipt) {
                abort(404, 'Goods receipt not found');
            }

            $pdf = Pdf::loadView('pdf.goods-receipt', compact('receipt'));
            $pdf->setPaper('a4', 'portrait');

            return $pdf->download('goods-receipt-' . $receiptCode . '.pdf');

        } catch (\Exception $e) {
            abort(500, 'Error generating PDF: ' . $e->getMessage());
        }
    }

    public function downloadInvoiceReturnPDF($returnCode, $shopId)
    {
        try {
            $invoiceReturn = ShopInvoiceReturn::with(['items.product'])
                ->where('code', $returnCode)
                ->where('shop_id', $shopId)
                ->first();

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

            $pdf = Pdf::loadView('pdf.invoice-return', compact('invoiceReturn'));
            $pdf->setPaper('a4', 'portrait');

            return $pdf->download('invoice-return-' . $returnCode . '.pdf');

        } catch (\Exception $e) {
            abort(500, 'Error generating PDF: ' . $e->getMessage());
        }
    }

    public function getContactTransactions(Request $request): JsonResponse
    {
        $request->validate([
            'contact_code' => 'required|string',
            'shop_id' => 'required|string'
        ]);

        try {
            $transactions = ShopContactAccountTransaction::with(['shop'])
                ->where('contact_code', $request->contact_code)
                ->where('shop_id', $request->shop_id)
                ->orderBy('local_db_created_at', 'desc')
                ->get();

            // Get contact info for the response
            $contact = ShopContact::with('shop')
                ->where('code', $request->contact_code)
                ->where('shop_id', $request->shop_id)
                ->first();

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

        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Error retrieving contact transactions: ' . $e->getMessage()
            ], 500);
        }
    }

    public function downloadContactPDF($contactCode, $shopId)
    {
        try {
            $contact = ShopContact::with(['shop', 'transactions'])
                ->where('code', $contactCode)
                ->where('shop_id', $shopId)
                ->first();

            if (!$contact) {
                abort(404, 'Contact not found');
            }

            $pdf = Pdf::loadView('pdf.contact', compact('contact'));
            $pdf->setPaper('a4', 'portrait');

            return $pdf->download('contact-' . $contactCode . '.pdf');

        } catch (\Exception $e) {
            abort(500, 'Error generating PDF: ' . $e->getMessage());
        }
    }

    public function getDashboardData(Request $request)
    {
        try {
            // Get filter parameters
            $shopId = $request->get('shop_id');
            $startDate = $request->get('start_date') ? \Carbon\Carbon::parse($request->get('start_date'))->startOfDay() : null;
            $endDate = $request->get('end_date') ? \Carbon\Carbon::parse($request->get('end_date'))->endOfDay() : null;

            // Base query for transactions
            $transactionQuery = ShopContactAccountTransaction::query();

            // Apply filters
            if ($shopId) {
                $transactionQuery->where('shop_id', $shopId);
            }

            if ($startDate && $endDate) {
                $transactionQuery->whereBetween('local_db_created_at', [$startDate, $endDate]);
            } elseif ($startDate) {
                $transactionQuery->where('local_db_created_at', '>=', $startDate);
            } elseif ($endDate) {
                $transactionQuery->where('local_db_created_at', '<=', $endDate);
            }

            // Calculate dashboard metrics

            // 1. Total number of sales (count of invoices)
            $totalSales = (clone $transactionQuery)
                ->where('reference_type', 'invoice')
                ->distinct('reference_code')
                ->count('reference_code');

            // 2. Total number of invoices (same as total sales for now)
            $totalInvoices = $totalSales;

            // 3. Total earned/collected today (receipt transactions today)
            $today = now()->toDateString();
            $totalEarnedToday = (clone $transactionQuery)
                ->where('reference_type', 'invoice')
                ->where('transaction_type', 'credit')
                ->whereDate('local_db_created_at', $today)
                ->sum('amount');

            // 4. Calculate outstanding payables
            // For Suppliers: balance = credits - debits (we owe them)
            // For Customers: balance = credits - debits (usually negative, if positive it's an overpayment/payable)
            
            $supplierOutstandings = (clone $transactionQuery)
                ->join('shop_contacts', 'shop_contact_account_transactions.contact_code', '=', 'shop_contacts.code')
                ->where('shop_contacts.contact_type', 'supplier')
                ->selectRaw('SUM(CASE WHEN transaction_type = "credit" THEN amount ELSE -amount END) as balance')
                ->value('balance') ?: 0;

            $customerOverpayments = (clone $transactionQuery)
                ->join('shop_contacts', 'shop_contact_account_transactions.contact_code', '=', 'shop_contacts.code')
                ->where('shop_contacts.contact_type', 'customer')
                ->selectRaw('SUM(CASE WHEN transaction_type = "credit" THEN amount ELSE -amount END) as balance')
                ->value('balance') ?: 0;

            // Total outstanding payable is what we owe suppliers + any customer overpayments
            $totalOutstandingPayable = max(0, $supplierOutstandings) + max(0, $customerOverpayments);

            // 5. Total number of return invoices
            $totalReturnInvoices = (clone $transactionQuery)
                ->where('reference_type', 'invoice_return')
                ->distinct('reference_code')
                ->count('reference_code');

            // 6. Total amount of return invoices
            $totalReturnAmount = (clone $transactionQuery)
                ->where('reference_type', 'invoice_return')
                ->sum('amount');

            // Additional useful metrics
            // Revenue = Actual cash collected (credits from invoices)
            $totalRevenue = (clone $transactionQuery)
                ->where('reference_type', 'invoice')
                ->where('transaction_type', 'credit')
                ->sum('amount');

            // Expenses = Actual cash paid (debits from goods receipts)
            $totalExpenses = (clone $transactionQuery)
                ->where('reference_type', 'goods_receipt')
                ->where('transaction_type', 'debit')
                ->sum('amount');

            $netProfit = $totalRevenue - $totalExpenses;

            $totalTransactions = (clone $transactionQuery)->count();

            // Get recent transactions
            $recentTransactions = (clone $transactionQuery)
                ->with(['contact', 'shop'])
                ->orderByDesc('local_db_created_at')
                ->limit(10)
                ->get(['id', 'shop_id', 'contact_code', 'reference_type', 'reference_code', 'amount', 'transaction_type', 'local_db_created_at']);

            // Format recent transactions for JSON response
            $formattedTransactions = $recentTransactions->map(function ($transaction) {
                return [
                    'date' => $transaction->local_db_created_at->format('M d, Y H:i'),
                    'shop' => $transaction->shop->name ?? 'N/A',
                    'contact' => $transaction->contact->name ?? 'N/A',
                    'reference_type' => $transaction->reference_type,
                    'reference_type_label' => $transaction->reference_type_label,
                    'reference_code' => $transaction->reference_code,
                    'amount' => number_format($transaction->amount, 2),
                    'formatted_amount' => $transaction->formatted_amount,
                    'transaction_type' => $transaction->transaction_type,
                    'transaction_type_label' => $transaction->transaction_type_label,
                ];
            });

            return response()->json([
                'success' => true,
                'data' => [
                    'metrics' => [
                        'total_sales' => $totalSales,
                        'total_invoices' => $totalInvoices,
                        'total_earned_today' => $totalEarnedToday,
                        'total_outstanding_payable' => $totalOutstandingPayable,
                        'total_return_invoices' => $totalReturnInvoices,
                        'total_return_amount' => $totalReturnAmount,
                        'total_revenue' => $totalRevenue,
                        'total_expenses' => $totalExpenses,
                        'net_profit' => $netProfit,
                        'total_transactions' => $totalTransactions,
                    ],
                    'recent_transactions' => $formattedTransactions,
                    'filters' => [
                        'shop_id' => $shopId,
                        'start_date' => $startDate?->format('Y-m-d'),
                        'end_date' => $endDate?->format('Y-m-d'),
                    ]
                ]
            ]);

        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Error loading dashboard data: ' . $e->getMessage()
            ], 500);
        }
    }
}
