<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\CustomerAccount;
use App\Models\Currency;
use App\Models\DocumentHeader;
use App\Models\CustomerJournal;
use App\Models\Receipt;
use App\Models\CompanySettings; // Added missing import
use PDF;

class CustomerStatementReportController extends Controller
{
    // Display initial form
    public function index()
    {
        $customers = CustomerAccount::orderBy('customer_code')->get();
        $currencies = Currency::orderBy('code')->get();
        
        return view('reports.customer-statement', compact('customers', 'currencies'));
    }

    // Generate customer statement report (supports all or single)
    public function generate(Request $request)
    {
        $request->validate([
            'customer_account' => 'required',
            'date_from' => 'required|date',
            'date_to' => 'required|date|after_or_equal:date_from',
            'currency' => 'required',
        ]);

        $customerId = $request->customer_account;
        $dateFrom = $request->date_from;
        $dateTo = $request->date_to;
        $currencyCode = $request->currency;
        $company = CompanySettings::first(); // Added company info

        $customers = CustomerAccount::orderBy('customer_code')->get();
        $currencies = Currency::orderBy('code')->get();

        // Handle "All Customers"
        if ($customerId == 'all') {
            $allStatements = [];
            $customersList = CustomerAccount::orderBy('customer_code')->get();

            foreach ($customersList as $customer) {
                $openingBalance = $this->calculateOpeningBalance($customer->id, $currencyCode, $dateFrom);
                $statementData = $this->getStatementData($customer->id, $currencyCode, $dateFrom, $dateTo);

                $allStatements[] = [
                    'customer'        => $customer,
                    'openingBalance'  => $openingBalance,
                    'statementData'   => $statementData
                ];
            }

            return view('reports.customer-statement', compact(
                'allStatements',
                'customerId',
                'dateFrom',
                'dateTo',
                'currencyCode',
                'customers',
                'currencies',
                'company' // Added company to view
            ));
        } else {
            // Single customer
            $customer = CustomerAccount::findOrFail($customerId);
            $openingBalance = $this->calculateOpeningBalance($customerId, $currencyCode, $dateFrom);
            $statementData = $this->getStatementData($customerId, $currencyCode, $dateFrom, $dateTo);

            return view('reports.customer-statement', compact(
                'statementData',
                'openingBalance',
                'customerId',
                'dateFrom',
                'dateTo',
                'currencyCode',
                'customers',
                'currencies',
                'company', // Added company to view
                'customer' // Added customer to view
            ));
        }
    }

    // Download PDF (supports all or single)
    public function downloadPdf(Request $request)
    {
        $request->validate([
            'customer_account' => 'required',
            'date_from' => 'required|date',
            'date_to' => 'required|date|after_or_equal:date_from',
            'currency' => 'required',
        ]);

        $customerId = $request->customer_account;
        $dateFrom = $request->date_from;
        $dateTo = $request->date_to;
        $currencyCode = $request->currency;
        $currency = Currency::where('code', $currencyCode)->first();
        $company = CompanySettings::first(); // Added company info

        if ($customerId == 'all') {
            $allStatements = [];
            $customersList = CustomerAccount::orderBy('customer_code')->get();

            foreach ($customersList as $customer) {
                $openingBalance = $this->calculateOpeningBalance($customer->id, $currencyCode, $dateFrom);
                $statementData = $this->getStatementData($customer->id, $currencyCode, $dateFrom, $dateTo);

                $allStatements[] = [
                    'customer'        => $customer,
                    'openingBalance'  => $openingBalance,
                    'statementData'   => $statementData
                ];
            }

            $pdf = PDF::loadView('reports.customer-statement-pdf', compact(
                'allStatements',
                'dateFrom',
                'dateTo',
                'currency',
                'company' // Added company to PDF
            ));

            return $pdf->download('customer-statements.pdf');
        } else {
            $customer = CustomerAccount::findOrFail($customerId);
            $openingBalance = $this->calculateOpeningBalance($customerId, $currencyCode, $dateFrom);
            $statementData = $this->getStatementData($customerId, $currencyCode, $dateFrom, $dateTo);

            $allStatements = [[
                'customer'        => $customer,
                'openingBalance'  => $openingBalance,
                'statementData'   => $statementData
            ]];

            $pdf = PDF::loadView('reports.customer-statement-pdf', compact(
                'allStatements',
                'dateFrom',
                'dateTo',
                'currency',
                'company' // Added company to PDF
            ));

            return $pdf->download('customer-statement-' . $customer->customer_code . '.pdf');
        }
    }

    // Retrieve statement data
    private function getStatementData($customerId, $currencyCode, $dateFrom, $dateTo)
    {
        $statementData = [];
        $balance = $this->calculateOpeningBalance($customerId, $currencyCode, $dateFrom);

        $statementData[] = [
            'date'        => $dateFrom,
            'description' => 'Opening Balance',
            'reference'   => '',
            'dr'          => 0,
            'cr'          => 0,
            'balance'     => $balance
        ];

        // Documents
        $documents = DocumentHeader::where('customer_account_id', $customerId)
            ->where('currency_code', $currencyCode)
            ->whereIn('type', ['invoice', 'credit_note', 'debit_note'])
            ->whereBetween('document_date', [$dateFrom, $dateTo])
            ->orderBy('document_date')
            ->get();

        foreach ($documents as $document) {
            $dr = 0; $cr = 0;
            if (in_array($document->type, ['invoice', 'debit_note'])) {
                $dr = $document->inclusive_total;
            } elseif ($document->type === 'credit_note') {
                $cr = $document->inclusive_total;
            }
            $rowBalance = $dr - $cr;
            $balance += $rowBalance;

            $statementData[] = [
                'date'        => $document->document_date,
                'description' => ucfirst(str_replace('_', ' ', $document->type)),
                'reference'   => $document->document_number,
                'dr'          => $dr,
                'cr'          => $cr,
                'balance'     => $balance
            ];
        }

        // Journals
        $journals = CustomerJournal::where('customer_account_id', $customerId)
            ->where('currency_id', function($query) use ($currencyCode) {
                $query->select('id')
                    ->from('currencies')
                    ->where('code', $currencyCode);
            })
            ->whereBetween('date', [$dateFrom, $dateTo])
            ->orderBy('date')
            ->get();

        foreach ($journals as $journal) {
            $dr = 0; $cr = 0;
            if ($journal->tr_code === 'DR') {
                $dr = $journal->amount;
            } elseif ($journal->tr_code === 'CR') {
                $cr = $journal->amount;
            }
            $rowBalance = $dr - $cr;
            $balance += $rowBalance;

            $statementData[] = [
                'date'        => $journal->date,
                'description' => $journal->narration,
                'reference'   => 'JNL' . str_pad($journal->id, 3, '0', STR_PAD_LEFT),
                'dr'          => $dr,
                'cr'          => $cr,
                'balance'     => $balance
            ];
        }

        // Receipts
        $receipts = Receipt::where('customer_id', $customerId)
            ->whereBetween('receipt_date', [$dateFrom, $dateTo])
            ->orderBy('receipt_date')
            ->get();

        foreach ($receipts as $receipt) {
            $dr = 0; $cr = $receipt->total_amount; // receipt reduces balance
            $rowBalance = $dr - $cr;
            $balance += $rowBalance;

            $statementData[] = [
                'date'        => $receipt->receipt_date,
                'description' => 'Receipt',
                'reference'   => $receipt->receipt_number,
                'dr'          => $dr,
                'cr'          => $cr,
                'balance'     => $balance
            ];
        }

        usort($statementData, function($a, $b) {
            return strtotime($a['date']) - strtotime($b['date']);
        });

        return $statementData;
    }

    // Calculate opening balance (before dateFrom)
    private function calculateOpeningBalance($customerId, $currencyCode, $dateFrom)
    {
        $balance = 0;

        // Documents
        $documents = DocumentHeader::where('customer_account_id', $customerId)
            ->where('currency_code', $currencyCode)
            ->whereIn('type', ['invoice', 'credit_note', 'debit_note'])
            ->where('document_date', '<', $dateFrom)
            ->get();

        foreach ($documents as $document) {
            if (in_array($document->type, ['invoice', 'debit_note'])) {
                $balance += $document->inclusive_total;
            } elseif ($document->type === 'credit_note') {
                $balance -= $document->inclusive_total;
            }
        }

        // Journals
        $journals = CustomerJournal::where('customer_account_id', $customerId)
            ->where('currency_id', function($query) use ($currencyCode) {
                $query->select('id')
                    ->from('currencies')
                    ->where('code', $currencyCode);
            })
            ->where('date', '<', $dateFrom)
            ->get();

        foreach ($journals as $journal) {
            if ($journal->tr_code === 'DR') {
                $balance += $journal->amount;
            } elseif ($journal->tr_code === 'CR') {
                $balance -= $journal->amount;
            }
        }

        // Receipts
        $receipts = Receipt::where('customer_id', $customerId)
            ->where('receipt_date', '<', $dateFrom)
            ->get();

        foreach ($receipts as $receipt) {
            $balance -= $receipt->total_amount; // receipts reduce opening balance
        }

        return $balance;
    }
}