<?php

namespace App\Livewire\Reports;

use Livewire\Component;
use App\Models\JobCard;
use App\Models\Branch;
use App\Models\Timesheet;
use App\Models\Part;
use Illuminate\Support\Facades\DB;
use Carbon\Carbon;

class WorkflowAnalytics extends Component
{
    public $selectedBranch = '';
    public $dateRange = '30';
    public $reportData = [];

    public function mount()
    {
        $this->generateReport();
    }

    public function updatedSelectedBranch()
    {
        $this->generateReport();
    }

    public function updatedDateRange()
    {
        $this->generateReport();
    }

    public function generateReport()
    {
        $startDate = Carbon::now()->subDays($this->dateRange);
        $endDate = Carbon::now();

        $this->reportData = [
            'revenue_by_branch' => $this->getRevenueByBranch($startDate, $endDate),
            'labor_utilization' => $this->getLaborUtilization($startDate, $endDate),
            'parts_usage' => $this->getPartsUsage($startDate, $endDate),
            'customer_approval_trends' => $this->getCustomerApprovalTrends($startDate, $endDate),
            'turnaround_times' => $this->getTurnaroundTimes($startDate, $endDate),
            'workflow_bottlenecks' => $this->getWorkflowBottlenecks($startDate, $endDate),
            'quality_metrics' => $this->getQualityMetrics($startDate, $endDate),
        ];
    }

    private function getRevenueByBranch($startDate, $endDate): array
    {
        $query = JobCard::with('estimates')
            ->whereBetween('completion_datetime', [$startDate, $endDate])
            ->where('status', 'delivered');

        if ($this->selectedBranch) {
            $query->where('branch_code', $this->selectedBranch);
        }

        return $query->get()
            ->groupBy('branch_code')
            ->map(function ($jobs, $branchCode) {
                $totalRevenue = $jobs->sum(function ($job) {
                    return $job->estimates->where('status', 'approved')->sum('total_amount');
                });
                
                return [
                    'branch' => $branchCode,
                    'jobs_completed' => $jobs->count(),
                    'total_revenue' => $totalRevenue,
                    'average_job_value' => $jobs->count() > 0 ? $totalRevenue / $jobs->count() : 0,
                ];
            })
            ->values()
            ->toArray();
    }

    private function getLaborUtilization($startDate, $endDate): array
    {
        $query = Timesheet::with('technician')
            ->whereBetween('date', [$startDate, $endDate]);

        if ($this->selectedBranch) {
            $query->whereHas('technician', function ($q) {
                $q->where('branch_code', $this->selectedBranch);
            });
        }

        $timesheets = $query->get();

        return $timesheets->groupBy('technician.name')
            ->map(function ($entries, $technicianName) {
                $totalHours = $entries->sum('hours_worked');
                $billableHours = $entries->sum('billable_hours');
                
                return [
                    'technician' => $technicianName,
                    'total_hours' => $totalHours,
                    'billable_hours' => $billableHours,
                    'utilization_rate' => $totalHours > 0 ? ($billableHours / $totalHours) * 100 : 0,
                ];
            })
            ->values()
            ->toArray();
    }

    private function getPartsUsage($startDate, $endDate): array
    {
        return DB::table('estimate_line_items')
            ->join('estimates', 'estimate_line_items.estimate_id', '=', 'estimates.id')
            ->join('job_cards', 'estimates.job_card_id', '=', 'job_cards.id')
            ->join('parts', 'estimate_line_items.part_id', '=', 'parts.id')
            ->whereBetween('job_cards.completion_datetime', [$startDate, $endDate])
            ->where('estimates.status', 'approved')
            ->where('estimate_line_items.type', 'part')
            ->when($this->selectedBranch, function ($query) {
                return $query->where('job_cards.branch_code', $this->selectedBranch);
            })
            ->select(
                'parts.part_number',
                'parts.name',
                DB::raw('SUM(estimate_line_items.quantity) as total_used'),
                DB::raw('SUM(estimate_line_items.total_price) as total_value'),
                'parts.current_stock'
            )
            ->groupBy('parts.id', 'parts.part_number', 'parts.name', 'parts.current_stock')
            ->orderBy('total_used', 'desc')
            ->limit(20)
            ->get()
            ->toArray();
    }

    private function getCustomerApprovalTrends($startDate, $endDate): array
    {
        $estimates = DB::table('estimates')
            ->join('job_cards', 'estimates.job_card_id', '=', 'job_cards.id')
            ->whereBetween('estimates.created_at', [$startDate, $endDate])
            ->when($this->selectedBranch, function ($query) {
                return $query->where('job_cards.branch_code', $this->selectedBranch);
            })
            ->select('estimates.status', DB::raw('COUNT(*) as count'))
            ->groupBy('estimates.status')
            ->get();

        $total = $estimates->sum('count');

        return [
            'total_estimates' => $total,
            'approval_rate' => $total > 0 ? ($estimates->where('status', 'approved')->first()?->count ?? 0) / $total * 100 : 0,
            'rejection_rate' => $total > 0 ? ($estimates->where('status', 'rejected')->first()?->count ?? 0) / $total * 100 : 0,
            'pending_rate' => $total > 0 ? ($estimates->where('status', 'sent')->first()?->count ?? 0) / $total * 100 : 0,
        ];
    }

    private function getTurnaroundTimes($startDate, $endDate): array
    {
        $jobs = JobCard::whereBetween('completion_datetime', [$startDate, $endDate])
            ->where('status', 'delivered')
            ->when($this->selectedBranch, function ($query) {
                return $query->where('branch_code', $this->selectedBranch);
            })
            ->get();

        $turnaroundTimes = $jobs->map(function ($job) {
            return $job->completion_datetime->diffInHours($job->arrival_datetime);
        });

        return [
            'average_turnaround' => $turnaroundTimes->avg(),
            'median_turnaround' => $turnaroundTimes->median(),
            'min_turnaround' => $turnaroundTimes->min(),
            'max_turnaround' => $turnaroundTimes->max(),
            'total_jobs' => $jobs->count(),
        ];
    }

    private function getWorkflowBottlenecks($startDate, $endDate): array
    {
        $statusCounts = JobCard::whereBetween('created_at', [$startDate, $endDate])
            ->when($this->selectedBranch, function ($query) {
                return $query->where('branch_code', $this->selectedBranch);
            })
            ->select('status', DB::raw('COUNT(*) as count'))
            ->groupBy('status')
            ->get()
            ->pluck('count', 'status')
            ->toArray();

        // Calculate average time in each status
        $avgTimeInStatus = [];
        foreach (JobCard::getStatusOptions() as $status => $label) {
            $avgTimeInStatus[$status] = $this->getAverageTimeInStatus($status, $startDate, $endDate);
        }

        return [
            'status_counts' => $statusCounts,
            'average_time_in_status' => $avgTimeInStatus,
        ];
    }

    private function getAverageTimeInStatus($status, $startDate, $endDate): float
    {
        // This would require status change tracking - simplified for now
        return JobCard::where('status', $status)
            ->whereBetween('updated_at', [$startDate, $endDate])
            ->when($this->selectedBranch, function ($query) {
                return $query->where('branch_code', $this->selectedBranch);
            })
            ->avg(DB::raw('TIMESTAMPDIFF(HOUR, created_at, updated_at)')) ?? 0;
    }

    private function getQualityMetrics($startDate, $endDate): array
    {
        $inspections = DB::table('vehicle_inspections')
            ->join('job_cards', 'vehicle_inspections.job_card_id', '=', 'job_cards.id')
            ->whereBetween('vehicle_inspections.inspection_date', [$startDate, $endDate])
            ->when($this->selectedBranch, function ($query) {
                return $query->where('job_cards.branch_code', $this->selectedBranch);
            })
            ->get();

        $totalInspections = $inspections->count();
        $discrepancyCount = $inspections->where('follow_up_required', true)->count();

        return [
            'total_inspections' => $totalInspections,
            'discrepancy_rate' => $totalInspections > 0 ? ($discrepancyCount / $totalInspections) * 100 : 0,
            'quality_score' => $totalInspections > 0 ? (($totalInspections - $discrepancyCount) / $totalInspections) * 100 : 100,
        ];
    }

    public function render()
    {
        $branches = Branch::active()->get();
        
        return view('livewire.reports.workflow-analytics', [
            'branches' => $branches,
            'reportData' => $this->reportData,
        ]);
    }
}
