<?php

namespace App\Http\Controllers\Reports;

use App\Http\Controllers\Controller;
use App\Models\Order;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;

class ProfitLossController extends Controller
{
    public function index(Request $request)
    {
        $startDate = $request->input('start_date', now()->startOfMonth()->toDateString());
        $endDate = $request->input('end_date', now()->toDateString());

        $start = Carbon::parse($startDate)->startOfDay();
        $end = Carbon::parse($endDate)->endOfDay();

        $sales = $this->getSalesSummary($start, $end);
        $purchaseCost = $this->getPurchaseCost($start, $end);
        $operationalExpense = $this->getOperationalExpense($start, $end);
        $salaryExpense = $this->getSalaryExpense($start, $end);

        $grossProfit = $sales['revenue'] - $purchaseCost;
        $totalOperatingExpense = $operationalExpense + $salaryExpense;
        $netProfit = $grossProfit - $totalOperatingExpense;

        return view('pages.reports.profit-loss', [
            'title' => 'Laporan Laba Rugi',
            'startDate' => $startDate,
            'endDate' => $endDate,

            'summary' => [
                'total_orders' => $sales['total_orders'],
                'revenue' => $sales['revenue'],
                'purchase_cost' => $purchaseCost,
                'gross_profit' => $grossProfit,
                'operational_expense' => $operationalExpense,
                'salary_expense' => $salaryExpense,
                'total_operating_expense' => $totalOperatingExpense,
                'net_profit' => $netProfit,
            ],
        ]);
    }

    private function getSalesSummary(Carbon $start, Carbon $end): array
    {
        $query = Order::query();

        if (method_exists(new Order(), 'scopePaid')) {
            $query->paid();
        } elseif (Schema::hasColumn('orders', 'payment_status')) {
            $query->where('payment_status', 'paid');
        } elseif (Schema::hasColumn('orders', 'status')) {
            $query->where('status', 'paid');
        }

        if (Schema::hasColumn('orders', 'is_cancelled')) {
            $query->where('is_cancelled', false);
        }

        $dateField = Schema::hasColumn('orders', 'paid_at')
            ? 'paid_at'
            : (Schema::hasColumn('orders', 'created_at') ? 'created_at' : null);

        if ($dateField) {
            $query->whereBetween($dateField, [$start, $end]);
        }

        $amountField = $this->pickColumn('orders', [
            'total_price',
            'grand_total',
            'total',
            'amount',
        ]) ?? 'total_price';

        return [
            'total_orders' => (clone $query)->count(),
            'revenue' => (float) (clone $query)->sum($amountField),
        ];
    }

    private function getPurchaseCost(Carbon $start, Carbon $end): float
    {
        if (!Schema::hasTable('purchases')) {
            return 0.0;
        }

        $dateField = $this->pickColumn('purchases', [
            'purchase_date',
            'date',
            'created_at',
        ]);

        $amountField = $this->pickColumn('purchases', [
            'grand_total',
            'total',
            'total_price',
            'amount',
        ]);

        if (!$dateField || !$amountField) {
            return 0.0;
        }

        $query = DB::table('purchases')->whereBetween($dateField, [$start, $end]);

        if (Schema::hasColumn('purchases', 'is_cancelled')) {
            $query->where('is_cancelled', false);
        }

        if (Schema::hasColumn('purchases', 'status')) {
            $query->whereNotIn('status', ['cancelled', 'draft']);
        }

        return (float) $query->sum($amountField);
    }

    private function getOperationalExpense(Carbon $start, Carbon $end): float
    {
        if (!Schema::hasTable('expenses')) {
            return 0.0;
        }

        $dateField = $this->pickColumn('expenses', [
            'expense_date',
            'created_at',
        ]);

        $amountField = $this->pickColumn('expenses', [
            'amount',
            'total',
        ]);

        if (!$dateField || !$amountField) {
            return 0.0;
        }

        $query = DB::table('expenses')->whereBetween($dateField, [$start, $end]);

        if (Schema::hasColumn('expenses', 'description')) {
            $query->where(function ($q) {
                $q->whereNull('description')
                    ->orWhere('description', 'not like', '%purchase_payment:%');
            });
        }

        return (float) $query->sum($amountField);
    }

    private function getSalaryExpense(Carbon $start, Carbon $end): float
    {
        if (!Schema::hasTable('salaries')) {
            return 0.0;
        }

        $dateField = $this->pickColumn('salaries', [
            'paid_at',
            'payment_date',
            'salary_date',
            'date',
            'created_at',
        ]);

        $amountField = $this->pickColumn('salaries', [
            'total',
            'net_salary',
            'total_salary',
            'take_home_pay',
            'amount',
            'salary',
        ]);

        if (!$dateField || !$amountField) {
            return 0.0;
        }

        $query = DB::table('salaries')->whereBetween($dateField, [$start, $end]);

        if (Schema::hasColumn('salaries', 'status')) {
            $query->whereIn('status', ['paid', 'completed']);
        } elseif (Schema::hasColumn('salaries', 'is_paid')) {
            $query->where('is_paid', 1);
        } else {
            return 0.0;
        }

        return (float) $query->sum($amountField);
    }

    private function pickColumn(string $table, array $candidates): ?string
    {
        foreach ($candidates as $column) {
            if (Schema::hasColumn($table, $column)) {
                return $column;
            }
        }

        return null;
    }
}