<?php

namespace Modules\Vrc\Http\Controllers;

use App\Transaction;
use Illuminate\Http\Request;
use Modules\Vrc\Entities\VrcEstimate;
use Modules\Vrc\Entities\VrcRepairOrder;
use Modules\Vrc\Entities\VrcRepairOrderPart;

/**
 * Repair KPI reports (spec §6.14), filtered by date range. Financial figures
 * read from the linked ERP invoices; operational figures from the VRC tables.
 */
class ReportController extends VrcBaseController
{
    public function index()
    {
        $this->guard('vrc.reports.view');
        return view('vrc::reports.index');
    }

    /** Revenue by day from VRC-linked ERP invoices. */
    public function revenue(Request $request)
    {
        $this->guard('vrc.reports.view');
        [$from, $to] = $this->range($request);
        $bid = $this->businessId();

        $invoiceIds = VrcRepairOrder::where('business_id', $bid)->whereNotNull('erp_invoice_id')->pluck('erp_invoice_id');
        $rows = Transaction::whereIn('id', $invoiceIds)
            ->whereBetween('transaction_date', [$from . ' 00:00:00', $to . ' 23:59:59'])
            ->selectRaw('DATE(transaction_date) as d, COUNT(*) as invoices, SUM(final_total) as revenue')
            ->groupBy('d')->orderBy('d')->get();

        $total = (float) $rows->sum('revenue');

        return view('vrc::reports.revenue', compact('rows', 'from', 'to', 'total'));
    }

    /** Estimate conversion: sent vs approved in the range. */
    public function estimateConversion(Request $request)
    {
        $this->guard('vrc.reports.view');
        [$from, $to] = $this->range($request);
        $bid = $this->businessId();

        $base = VrcEstimate::where('business_id', $bid)->whereBetween('created_at', [$from . ' 00:00:00', $to . ' 23:59:59']);
        $sent = (clone $base)->whereIn('status', ['sent', 'approved', 'declined', 'converted', 'expired'])->count();
        $approved = (clone $base)->whereIn('status', ['approved', 'converted'])->count();
        $rate = $sent > 0 ? round($approved / $sent * 100, 1) : 0.0;

        return view('vrc::reports.estimate_conversion', compact('sent', 'approved', 'rate', 'from', 'to'));
    }

    /** Job turnaround: average hours from check-in to completion. */
    public function turnaround(Request $request)
    {
        $this->guard('vrc.reports.view');
        [$from, $to] = $this->range($request);
        $bid = $this->businessId();

        $orders = VrcRepairOrder::where('business_id', $bid)
            ->whereNotNull('checked_in_at')->whereNotNull('completed_at')
            ->whereBetween('completed_at', [$from . ' 00:00:00', $to . ' 23:59:59'])
            ->get(['checked_in_at', 'completed_at']);

        $avgHours = $orders->count()
            ? round($orders->avg(fn ($o) => $o->checked_in_at->diffInMinutes($o->completed_at) / 60), 1)
            : 0.0;

        return view('vrc::reports.turnaround', ['avg_hours' => $avgHours, 'count' => $orders->count(), 'from' => $from, 'to' => $to]);
    }

    /** Parts consumption in the range. */
    public function partsConsumption(Request $request)
    {
        $this->guard('vrc.reports.view');
        [$from, $to] = $this->range($request);
        $bid = $this->businessId();

        $rows = VrcRepairOrderPart::where('business_id', $bid)
            ->whereBetween('created_at', [$from . ' 00:00:00', $to . ' 23:59:59'])
            ->selectRaw('description, SUM(qty) as qty, SUM(line_total) as total')
            ->groupBy('description')->orderByDesc('qty')->limit(100)->get();

        return view('vrc::reports.parts_consumption', compact('rows', 'from', 'to'));
    }

    /** Profit per repair order: revenue (grand_total) minus parts cost. */
    public function profit(Request $request)
    {
        $this->guard('vrc.reports.view');
        [$from, $to] = $this->range($request);
        $bid = $this->businessId();

        $rows = VrcRepairOrder::where('vrc_repair_orders.business_id', $bid)
            ->whereBetween('vrc_repair_orders.created_at', [$from . ' 00:00:00', $to . ' 23:59:59'])
            ->leftJoin('vrc_repair_order_parts as p', 'p.repair_order_id', '=', 'vrc_repair_orders.id')
            ->groupBy('vrc_repair_orders.id', 'vrc_repair_orders.number', 'vrc_repair_orders.grand_total')
            ->selectRaw('vrc_repair_orders.id, vrc_repair_orders.number, vrc_repair_orders.grand_total as revenue, COALESCE(SUM(p.unit_cost * p.qty),0) as parts_cost')
            ->orderByDesc('vrc_repair_orders.id')->limit(200)->get()
            ->map(function ($r) {
                $r->profit = round((float) $r->revenue - (float) $r->parts_cost, 2);
                return $r;
            });

        $totals = [
            'revenue' => (float) $rows->sum('revenue'),
            'cost'    => (float) $rows->sum('parts_cost'),
            'profit'  => (float) $rows->sum('profit'),
        ];

        return view('vrc::reports.profit', compact('rows', 'totals', 'from', 'to'));
    }

    /** Revenue by service line in the range. */
    public function revenueByService(Request $request)
    {
        $this->guard('vrc.reports.view');
        [$from, $to] = $this->range($request);
        $bid = $this->businessId();

        $rows = \Modules\Vrc\Entities\VrcRepairOrderService::where('business_id', $bid)
            ->whereBetween('created_at', [$from . ' 00:00:00', $to . ' 23:59:59'])
            ->selectRaw('description, COUNT(*) as jobs, SUM(line_total) as revenue')
            ->groupBy('description')->orderByDesc('revenue')->limit(100)->get();

        return view('vrc::reports.revenue_by_service', compact('rows', 'from', 'to'));
    }

    /** Receivables aging from VRC-linked ERP invoices that are not fully paid. */
    public function receivables()
    {
        $this->guard('vrc.reports.view');
        $bid = $this->businessId();

        $invoiceIds = VrcRepairOrder::where('business_id', $bid)->whereNotNull('erp_invoice_id')->pluck('erp_invoice_id');

        $buckets = ['0-30' => 0.0, '31-60' => 0.0, '61-90' => 0.0, '90+' => 0.0];
        $transactions = \App\Transaction::whereIn('id', $invoiceIds)
            ->whereIn('payment_status', ['due', 'partial', 'overdue'])->get();

        foreach ($transactions as $t) {
            $paid = (float) \App\TransactionPayment::where('transaction_id', $t->id)->where('is_return', 0)->sum('amount');
            $due = round((float) $t->final_total - $paid, 2);
            if ($due <= 0) {
                continue;
            }
            $age = \Carbon\Carbon::parse($t->transaction_date)->diffInDays(now());
            $bucket = $age <= 30 ? '0-30' : ($age <= 60 ? '31-60' : ($age <= 90 ? '61-90' : '90+'));
            $buckets[$bucket] += $due;
        }

        return view('vrc::reports.receivables', ['buckets' => $buckets, 'total' => array_sum($buckets)]);
    }

    /**
     * Rework / comeback rate — a core workshop quality KPI. Rate = repair orders
     * flagged as rework ÷ all repair orders checked in over the range. Lists the
     * comebacks with their original order so QC can drive NCR/CAPA.
     */
    public function rework(Request $request)
    {
        $this->guard('vrc.reports.view');
        [$from, $to] = $this->range($request);
        $bid = $this->businessId();

        $window = [$from . ' 00:00:00', $to . ' 23:59:59'];
        $total = VrcRepairOrder::where('business_id', $bid)->whereBetween('created_at', $window)->count();
        $reworkCount = VrcRepairOrder::where('business_id', $bid)->where('is_rework', true)
            ->whereBetween('created_at', $window)->count();
        $rate = $total > 0 ? round($reworkCount / $total * 100, 1) : 0.0;

        $rows = VrcRepairOrder::with(['vehicle', 'reworkOf'])
            ->where('business_id', $bid)->where('is_rework', true)
            ->whereBetween('created_at', $window)
            ->orderByDesc('id')->limit(200)->get();

        return view('vrc::reports.rework', compact('rows', 'total', 'reworkCount', 'rate', 'from', 'to'));
    }

    protected function range(Request $request): array
    {
        return [
            $request->get('from', now()->startOfMonth()->toDateString()),
            $request->get('to', now()->endOfMonth()->toDateString()),
        ];
    }
}
