<?php

namespace App\Http\Controllers\Tenant;

use App\Http\Controllers\Controller;
use App\Models\Application;
use App\Models\AttendanceRecord;
use App\Models\Employee;
use App\Models\EmployeeDocument;
use App\Models\EmployeeGratuity;
use App\Models\EmployeeLoan;
use App\Models\Invoice;
use App\Models\LeaveRequest;
use App\Models\Payment;
use App\Models\PayrollRun;
use App\Models\RenewalOpportunity;
use Illuminate\Http\Request;

class ReportCenterController extends Controller
{
    public function index(Request $request)
    {
        $validated = $request->validate([
            'from' => ['nullable', 'date'],
            'to' => ['nullable', 'date', 'after_or_equal:from'],
        ]);
        $from = isset($validated['from']) ? now()->parse($validated['from'])->startOfDay() : today()->subDays(29);
        $to = isset($validated['to']) ? now()->parse($validated['to'])->endOfDay() : now()->endOfDay();
        if ($from->diffInDays($to) > 366) {
            $from = $to->copy()->subDays(366);
        }

        $applications = Application::with(['service', 'assignedUser'])
            ->whereBetween('created_at', [$from, $to])->get();
        $payments = Payment::whereBetween('created_at', [$from, $to])
            ->whereIn('status', ['completed', 'partially_refunded'])->get();
        $invoices = Invoice::whereBetween('created_at', [$from, $to])->get();
        $renewals = RenewalOpportunity::withoutGlobalScopes()
            ->where('tenant_id', auth()->user()->tenant_id)
            ->whereBetween('created_at', [$from, $to])->get();

        $summary = [
            'applications' => $applications->count(),
            'completed' => $applications->whereIn('status', ['completed', 'delivered'])->count(),
            'returned' => $applications->where('status', 'returned')->count(),
            'rejected' => $applications->where('status', 'rejected')->count(),
            'collection' => (float) $payments->sum('amount'),
            'government_fees' => (float) $applications->sum('gov_fee_total'),
            'service_revenue' => (float) ($applications->sum('typing_fee_total') + $applications->sum('service_charge_total')),
            'vat' => (float) $applications->sum('vat_total'),
            'outstanding' => (float) $invoices->sum('balance_due'),
            'renewals' => $renewals->count(),
            'renewal_converted' => $renewals->whereIn('status', ['application_created', 'under_processing', 'completed'])->count(),
        ];
        $summary['completion_rate'] = $summary['applications'] ? round(($summary['completed'] / $summary['applications']) * 100, 1) : 0;
        $summary['renewal_conversion'] = $summary['renewals'] ? round(($summary['renewal_converted'] / $summary['renewals']) * 100, 1) : 0;

        $servicePerformance = $applications->groupBy('service_id')->map(function ($rows) {
            $service = $rows->first()->service;

            return [
                'name' => $service?->name_en ?? 'Unassigned',
                'applications' => $rows->count(),
                'completed' => $rows->whereIn('status', ['completed', 'delivered'])->count(),
                'revenue' => (float) ($rows->sum('typing_fee_total') + $rows->sum('service_charge_total')),
                'government' => (float) $rows->sum('gov_fee_total'),
            ];
        })->sortByDesc('applications')->take(10)->values();

        $staffPerformance = $applications->whereNotNull('assigned_user_id')->groupBy('assigned_user_id')->map(function ($rows) {
            $user = $rows->first()->assignedUser;

            return [
                'name' => $user?->name ?? 'Unassigned',
                'assigned' => $rows->count(),
                'completed' => $rows->whereIn('status', ['completed', 'delivered'])->count(),
                'returned' => $rows->where('status', 'returned')->count(),
                'sla_risk' => $rows->whereIn('sla_status', ['at_risk', 'overdue'])->count(),
            ];
        })->sortByDesc('completed')->take(10)->values();

        $daily = collect();
        $cursor = $from->copy()->startOfDay();
        while ($cursor->lte($to) && $daily->count() < 367) {
            $date = $cursor->copy();
            $daily->push([
                'label' => $date->format('d M'),
                'applications' => $applications->filter(fn ($row) => $row->created_at->isSameDay($date))->count(),
                'collection' => (float) $payments->filter(fn ($row) => $row->created_at->isSameDay($date))->sum('amount'),
            ]);
            $cursor->addDay();
        }

        $attendance = AttendanceRecord::whereBetween('attendance_date', [$from->toDateString(), $to->toDateString()])->get();
        $hrSummary = [
            'active_employees' => Employee::where('status', 'active')->count(),
            'present' => $attendance->whereIn('status', ['present', 'late', 'early_leave', 'half_day', 'work_from_home', 'business_visit'])->count(),
            'absent' => $attendance->where('status', 'absent')->count(),
            'late' => $attendance->where('late_minutes', '>', 0)->count(),
            'overtime_minutes' => (int) $attendance->sum('overtime_minutes'),
            'approved_leave_days' => (float) LeaveRequest::where('status', 'approved')->whereDate('from_date', '<=', $to)->whereDate('to_date', '>=', $from)->sum('total_days'),
            'documents_due' => EmployeeDocument::where('is_current', true)->whereNotNull('expiry_date')->where('expiry_date', '<=', today()->addDays(90))->count(),
            'loan_balance' => null,
            'gratuity_approved' => null,
            'payroll_gross' => null,
            'payroll_deductions' => null,
            'payroll_net' => null,
        ];
        if ($request->user()->hasPermission('payroll.salary.view')) {
            $payroll = PayrollRun::whereIn('status', ['approved', 'paid'])->whereHas('period', fn ($query) => $query->whereDate('period_start', '<=', $to)->whereDate('period_end', '>=', $from));
            $hrSummary['loan_balance'] = (float) EmployeeLoan::where('status', 'active')->sum('remaining_amount');
            $hrSummary['gratuity_approved'] = (float) EmployeeGratuity::where('status', 'approved')->sum('approved_amount');
            $hrSummary['payroll_gross'] = (float) (clone $payroll)->sum('gross_total');
            $hrSummary['payroll_deductions'] = (float) (clone $payroll)->sum('deduction_total');
            $hrSummary['payroll_net'] = (float) (clone $payroll)->sum('net_total');
        }

        if ($request->query('export') === 'csv') {
            abort_unless($request->user()->hasPermission('reports.export'), 403);
            $rows = [
                ['Report', 'Metric', 'Value'],
                ['Applications', 'Applications', $summary['applications']],
                ['Applications', 'Completed', $summary['completed']],
                ['Applications', 'Returned', $summary['returned']],
                ['Finance', 'Collections', $summary['collection']],
                ['Finance', 'Service Revenue', $summary['service_revenue']],
                ['Finance', 'Government Fees', $summary['government_fees']],
                ['Finance', 'VAT', $summary['vat']],
                ['Finance', 'Outstanding', $summary['outstanding']],
                ['HR', 'Active Employees', $hrSummary['active_employees']],
                ['HR', 'Present Records', $hrSummary['present']],
                ['HR', 'Absent Records', $hrSummary['absent']],
                ['HR', 'Late Records', $hrSummary['late']],
                ['HR', 'Overtime Minutes', $hrSummary['overtime_minutes']],
                ['HR', 'Approved Leave Days', $hrSummary['approved_leave_days']],
            ];
            if ($hrSummary['payroll_net'] !== null) {
                $rows[] = ['Payroll', 'Gross', $hrSummary['payroll_gross']];
                $rows[] = ['Payroll', 'Deductions', $hrSummary['payroll_deductions']];
                $rows[] = ['Payroll', 'Net', $hrSummary['payroll_net']];
            }

            return response()->streamDownload(function () use ($rows) {
                $stream = fopen('php://output', 'wb');
                foreach ($rows as $row) {
                    fputcsv($stream, $row);
                }
                fclose($stream);
            }, 'brandx-erp-report-'.$from->format('Ymd').'-'.$to->format('Ymd').'.csv', ['Content-Type' => 'text/csv']);
        }

        return view('tenant.operations.reports', compact('summary', 'servicePerformance', 'staffPerformance', 'daily', 'hrSummary', 'from', 'to'));
    }
}
