<?php

namespace App\Http\Controllers\Modules\Accounts;

use App\Http\Controllers\Controller;
use App\Http\Traits\HasRoleViews;
use App\Models\TaxInvoice;
use App\Models\PurchaseOrder;
use App\Models\SalesPayment;
use Illuminate\Http\Request;
use Carbon\Carbon;

/**
 * Unified Financial Reports Controller
 *
 * Handles financial reports (Balance Sheet, P&L, Cash Flow) for all roles.
 * Uses HasRoleViews trait to automatically resolve role-specific views.
 */
class FinancialReportsController extends Controller
{
    use HasRoleViews;

    /**
     * Get financial year date range (April to March for India)
     */
    protected function getFinancialYearRange($year = null): array
    {
        $currentYear = $year ?? (now()->month >= 4 ? now()->year : now()->year - 1);
        $start = Carbon::create($currentYear, 4, 1)->startOfDay();
        $end = Carbon::create($currentYear + 1, 3, 31)->endOfDay();

        return [
            'start' => $start,
            'end' => $end,
            'label' => "FY {$currentYear}-" . ($currentYear + 1),
            'year' => $currentYear,
        ];
    }

    /**
     * Balance Sheet Report
     */
    public function balanceSheet(Request $request)
    {
        $fy = $this->getFinancialYearRange($request->year);

        // ASSETS
        $totalInvoices = TaxInvoice::whereBetween('invoice_date', [$fy['start'], $fy['end']])
            ->sum('total_amount');
        $totalReceived = SalesPayment::whereBetween('payment_date', [$fy['start'], $fy['end']])
            ->sum('payment_amount');
        $accountsReceivable = $totalInvoices - $totalReceived;
        $cashAndBank = $totalReceived;

        // LIABILITIES
        $totalPurchases = PurchaseOrder::whereBetween('purchase_order_date', [$fy['start'], $fy['end']])
            ->sum('grand_total');
        $totalPaid = 0;
        $accountsPayable = $totalPurchases - $totalPaid;

        // Calculate totals
        $totalAssets = $accountsReceivable + $cashAndBank;
        $totalLiabilities = $accountsPayable;
        $equity = $totalAssets - $totalLiabilities;

        $data = [
            'assets' => [
                'current_assets' => [
                    ['name' => 'Cash & Bank', 'amount' => $cashAndBank],
                    ['name' => 'Accounts Receivable', 'amount' => $accountsReceivable],
                ],
                'total' => $totalAssets,
            ],
            'liabilities' => [
                'current_liabilities' => [
                    ['name' => 'Accounts Payable', 'amount' => $accountsPayable],
                ],
                'total' => $totalLiabilities,
            ],
            'equity' => [
                'items' => [
                    ['name' => 'Retained Earnings', 'amount' => $equity],
                ],
                'total' => $equity,
            ],
            'total_liabilities_equity' => $totalLiabilities + $equity,
        ];

        $years = $this->getAvailableYears();

        return $this->roleView('accounts.reports.balance-sheet', compact('data', 'fy', 'years'));
    }

    /**
     * Profit & Loss Report
     */
    public function profitLoss(Request $request)
    {
        $fy = $this->getFinancialYearRange($request->year);

        // REVENUE
        $salesRevenue = TaxInvoice::whereBetween('invoice_date', [$fy['start'], $fy['end']])
            ->sum('total_amount');
        $taxableValue = TaxInvoice::whereBetween('invoice_date', [$fy['start'], $fy['end']])
            ->sum('taxable_value');

        // COST OF GOODS SOLD
        $purchaseCost = PurchaseOrder::whereBetween('purchase_order_date', [$fy['start'], $fy['end']])
            ->sum('subtotal');

        // GROSS PROFIT
        $grossProfit = $taxableValue - $purchaseCost;

        // EXPENSES
        $sgstPaid = PurchaseOrder::whereBetween('purchase_order_date', [$fy['start'], $fy['end']])
            ->sum('sgst_amount');
        $cgstPaid = PurchaseOrder::whereBetween('purchase_order_date', [$fy['start'], $fy['end']])
            ->sum('cgst_amount');
        $igstPaid = PurchaseOrder::whereBetween('purchase_order_date', [$fy['start'], $fy['end']])
            ->sum('igst_amount');

        $totalExpenses = $purchaseCost + $sgstPaid + $cgstPaid + $igstPaid;

        // TAX COLLECTED
        $sgstCollected = TaxInvoice::whereBetween('invoice_date', [$fy['start'], $fy['end']])
            ->sum('sgst');
        $cgstCollected = TaxInvoice::whereBetween('invoice_date', [$fy['start'], $fy['end']])
            ->sum('cgst');
        $igstCollected = TaxInvoice::whereBetween('invoice_date', [$fy['start'], $fy['end']])
            ->sum('igst');

        // NET PROFIT
        $netProfit = $salesRevenue - $totalExpenses;

        // Monthly breakdown
        $monthlyData = [];
        for ($m = 4; $m <= 15; $m++) {
            $month = $m > 12 ? $m - 12 : $m;
            $year = $m > 12 ? $fy['year'] + 1 : $fy['year'];

            $monthRevenue = TaxInvoice::whereYear('invoice_date', $year)
                ->whereMonth('invoice_date', $month)
                ->sum('total_amount');

            $monthExpense = PurchaseOrder::whereYear('purchase_order_date', $year)
                ->whereMonth('purchase_order_date', $month)
                ->sum('grand_total');

            $monthlyData[] = [
                'month' => Carbon::create($year, $month, 1)->format('M Y'),
                'revenue' => $monthRevenue,
                'expense' => $monthExpense,
                'profit' => $monthRevenue - $monthExpense,
            ];
        }

        $data = [
            'revenue' => [
                ['name' => 'Sales Revenue', 'amount' => $salesRevenue],
                ['name' => 'Taxable Value', 'amount' => $taxableValue],
            ],
            'total_revenue' => $salesRevenue,
            'cost_of_goods' => [
                ['name' => 'Purchase Cost', 'amount' => $purchaseCost],
            ],
            'total_cogs' => $purchaseCost,
            'gross_profit' => $grossProfit,
            'gross_margin' => $salesRevenue > 0 ? ($grossProfit / $salesRevenue) * 100 : 0,
            'expenses' => [
                ['name' => 'SGST Paid', 'amount' => $sgstPaid],
                ['name' => 'CGST Paid', 'amount' => $cgstPaid],
                ['name' => 'IGST Paid', 'amount' => $igstPaid],
            ],
            'total_expenses' => $totalExpenses,
            'net_profit' => $netProfit,
            'net_margin' => $salesRevenue > 0 ? ($netProfit / $salesRevenue) * 100 : 0,
            'tax_summary' => [
                'collected' => $sgstCollected + $cgstCollected + $igstCollected,
                'paid' => $sgstPaid + $cgstPaid + $igstPaid,
                'net_payable' => ($sgstCollected + $cgstCollected + $igstCollected) - ($sgstPaid + $cgstPaid + $igstPaid),
            ],
            'monthly' => $monthlyData,
        ];

        $years = $this->getAvailableYears();

        return $this->roleView('accounts.reports.profit-loss', compact('data', 'fy', 'years'));
    }

    /**
     * Cash Flow Report
     */
    public function cashFlow(Request $request)
    {
        $fy = $this->getFinancialYearRange($request->year);

        // OPERATING ACTIVITIES
        $cashFromCustomers = SalesPayment::whereBetween('payment_date', [$fy['start'], $fy['end']])
            ->sum('payment_amount');
        $cashToVendors = 0;
        $netOperating = $cashFromCustomers - $cashToVendors;

        // Monthly cash flow
        $monthlyData = [];
        for ($m = 4; $m <= 15; $m++) {
            $month = $m > 12 ? $m - 12 : $m;
            $year = $m > 12 ? $fy['year'] + 1 : $fy['year'];

            $inflow = SalesPayment::whereYear('payment_date', $year)
                ->whereMonth('payment_date', $month)
                ->sum('payment_amount');

            $outflow = 0;

            $monthlyData[] = [
                'month' => Carbon::create($year, $month, 1)->format('M Y'),
                'inflow' => $inflow,
                'outflow' => $outflow,
                'net' => $inflow - $outflow,
            ];
        }

        // Recent transactions
        $recentInflows = SalesPayment::with('party')
            ->whereBetween('payment_date', [$fy['start'], $fy['end']])
            ->orderBy('payment_date', 'desc')
            ->limit(10)
            ->get();

        $data = [
            'operating' => [
                'inflows' => [
                    ['name' => 'Cash Received from Customers', 'amount' => $cashFromCustomers],
                ],
                'outflows' => [
                    ['name' => 'Cash Paid to Vendors', 'amount' => $cashToVendors],
                ],
                'net' => $netOperating,
            ],
            'investing' => [
                'inflows' => [],
                'outflows' => [],
                'net' => 0,
            ],
            'financing' => [
                'inflows' => [],
                'outflows' => [],
                'net' => 0,
            ],
            'net_cash_flow' => $netOperating,
            'monthly' => $monthlyData,
            'recent_inflows' => $recentInflows,
        ];

        $years = $this->getAvailableYears();

        return $this->roleView('accounts.reports.cash-flow', compact('data', 'fy', 'years'));
    }

    /**
     * Get available financial years
     */
    protected function getAvailableYears(): array
    {
        $years = [];
        $currentYear = now()->month >= 4 ? now()->year : now()->year - 1;

        for ($i = 0; $i < 5; $i++) {
            $year = $currentYear - $i;
            $years[] = [
                'value' => $year,
                'label' => "FY {$year}-" . ($year + 1),
            ];
        }

        return $years;
    }
}
