<?php

namespace App\Http\Controllers\Tenant;

use App\Http\Controllers\Controller;
use App\Models\Application;
use App\Models\ApplicationDocument;
use App\Models\ApprovalRequest;
use App\Models\AttendanceRecord;
use App\Models\Branch;
use App\Models\CorporateCompany;
use App\Models\Customer;
use App\Models\Employee;
use App\Models\EmployeeDocument;
use App\Models\Invoice;
use App\Models\InvoiceItem;
use App\Models\Payment;
use App\Models\RenewalOpportunity;
use App\Models\Service;
use App\Models\User;
use App\Services\TenantContext;
use Illuminate\Http\Request;

class DashboardController extends Controller
{
    public function index()
    {
        $tenant = auth()->user()->tenant;
        $branches = auth()->user()->accessibleBranches();
        $activeBranchId = app(TenantContext::class)->getActiveBranchId();
        $employeeBase = Employee::where('tenant_id', $tenant->id)->when($activeBranchId, fn ($query) => $query->where('branch_id', $activeBranchId));
        $employeeCount = (clone $employeeBase)->where('status', 'active')->count();
        $userCount = User::where('tenant_id', $tenant->id)->where('status', 'active')->count();
        $applications = Application::where('tenant_id', $tenant->id);
        $todayApplications = (clone $applications)->whereDate('created_at', today())->count();
        $completedToday = (clone $applications)->whereDate('completed_at', today())->count();
        $pendingApplications = (clone $applications)
            ->whereNotIn('status', ['completed', 'delivered', 'cancelled', 'rejected', 'archived'])
            ->count();
        $slaRisk = (clone $applications)
            ->whereNotIn('status', ['completed', 'delivered', 'cancelled', 'rejected', 'archived'])
            ->where(function ($query) {
                $query->where('sla_status', 'at_risk')
                    ->orWhere('sla_status', 'overdue')
                    ->orWhere('due_at', '<=', now()->addHours(4));
            })
            ->count();

        $todayRevenue = Payment::where('tenant_id', $tenant->id)
            ->whereDate('created_at', today())
            ->whereIn('status', ['completed', 'partially_refunded'])
            ->sum('amount');
        $todayInvoiceItems = InvoiceItem::whereHas('invoice', fn ($query) => $query->where('tenant_id', $tenant->id)->whereDate('invoice_date', today())->whereNotIn('status', ['cancelled', 'refunded']));
        $serviceRevenueToday = (clone $todayInvoiceItems)->where('revenue_classification', 'company_revenue')->sum('total_amount');
        $governmentFeesToday = (clone $todayInvoiceItems)->whereIn('revenue_classification', ['government_clearing', 'gov_passthrough', 'pass_through'])->sum('total_amount');
        $vatToday = (clone $todayInvoiceItems)->where('revenue_classification', 'vat_liability')->sum('total_amount');
        $outstandingReceivables = Invoice::where('tenant_id', $tenant->id)
            ->whereNotIn('status', ['cancelled', 'refunded'])
            ->sum('balance_due');
        $renewalQuery = RenewalOpportunity::withoutGlobalScopes()->where('tenant_id', $tenant->id)
            ->where('expiry_date', '<=', today()->addDays(30))
            ->whereNotIn('status', ['completed', 'lost']);
        $renewalsDue = (clone $renewalQuery)->count();
        $renewalItems = (clone $renewalQuery)
            ->with(['customer', 'company', 'corporateEmployee', 'employee'])
            ->orderBy('expiry_date')
            ->limit(5)
            ->get();

        $attendanceToday = AttendanceRecord::whereDate('attendance_date', today())->get();
        $employeesPresent = $attendanceToday->whereIn('status', ['present', 'late', 'early_leave', 'half_day', 'work_from_home', 'business_visit'])->count();
        $employeesAbsent = $attendanceToday->where('status', 'absent')->count();
        $employeesLate = $attendanceToday->where('late_minutes', '>', 0)->count();
        $employeeOvertimeMinutes = (int) $attendanceToday->sum('overtime_minutes');
        $employeeDocumentsDue = EmployeeDocument::where('is_current', true)->whereNotNull('expiry_date')->where('expiry_date', '<=', today()->addDays(90))
            ->when($activeBranchId, fn ($query) => $query->whereHas('employee', fn ($employee) => $employee->where('branch_id', $activeBranchId)))->count();
        $pendingDocuments = ApplicationDocument::where('is_mandatory', true)->whereNotIn('status', ['verified', 'approved'])
            ->whereHas('application', fn ($query) => $query->where('tenant_id', $tenant->id))->count();
        $submittedApplications = (clone $applications)->where('status', 'submitted')->count();
        $returnedApplications = (clone $applications)->where('status', 'returned')->count();
        $customersAddedToday = Customer::where('tenant_id', $tenant->id)->whereDate('created_at', today())->count();
        $pendingCorporateReceivables = Invoice::where('tenant_id', $tenant->id)->whereNotNull('company_id')->whereNotIn('status', ['cancelled', 'refunded'])->sum('balance_due');
        $pendingApprovalCount = ApprovalRequest::where('status', 'pending')->count();
        $pendingApprovals = ApprovalRequest::where('status', 'pending')->with(['requester', 'assignee'])->latest()->limit(5)->get();
        $recentPayments = Payment::with(['invoice', 'cashier'])->whereDate('created_at', '>=', today()->subDays(7))->latest()->limit(5)->get();
        $expiringEmployeeDocuments = EmployeeDocument::with('employee')->where('is_current', true)->whereNotNull('expiry_date')->where('expiry_date', '<=', today()->addDays(90))
            ->when($activeBranchId, fn ($query) => $query->whereHas('employee', fn ($employee) => $employee->where('branch_id', $activeBranchId)))->orderBy('expiry_date')->limit(5)->get();
        $corporateOutstanding = CorporateCompany::where('credit_enabled', true)->where('credit_used', '>', 0)->orderByDesc('credit_used')->limit(5)->get();

        $recentApplications = (clone $applications)
            ->with(['customer', 'service', 'currentStage', 'assignedUser'])
            ->latest()
            ->limit(6)
            ->get();

        $statusCounts = (clone $applications)
            ->selectRaw('status, COUNT(*) as total')
            ->groupBy('status')
            ->pluck('total', 'status');
        $statusTotal = max(1, (int) $statusCounts->sum());

        $topServiceCounts = (clone $applications)
            ->whereNotNull('service_id')
            ->selectRaw('service_id, COUNT(*) as total')
            ->groupBy('service_id')
            ->orderByDesc('total')
            ->limit(5)
            ->get();
        $services = Service::whereIn('id', $topServiceCounts->pluck('service_id'))->get()->keyBy('id');
        $topServices = $topServiceCounts->map(fn ($row) => [
            'name' => $services->get($row->service_id)?->name_en ?? 'Unassigned service',
            'total' => (int) $row->total,
        ]);
        $topServiceTotal = max(1, (int) $topServices->sum('total'));

        $startDate = today()->subDays(6);
        $trendApplications = (clone $applications)
            ->where('created_at', '>=', $startDate)
            ->get(['created_at', 'status', 'completed_at']);
        $trendPayments = Payment::where('tenant_id', $tenant->id)
            ->where('created_at', '>=', $startDate)
            ->whereIn('status', ['completed', 'partially_refunded'])
            ->get(['created_at', 'amount']);
        $weeklyTrend = collect(range(0, 6))->map(function (int $offset) use ($startDate, $trendApplications, $trendPayments) {
            $date = $startDate->copy()->addDays($offset);
            $created = $trendApplications->filter(fn ($application) => $application->created_at->isSameDay($date))->count();
            $completed = $trendApplications->filter(fn ($application) => $application->completed_at?->isSameDay($date))->count();
            $revenue = $trendPayments->filter(fn ($payment) => $payment->created_at->isSameDay($date))->sum('amount');

            return [
                'label' => $date->format('d M'),
                'created' => $created,
                'completed' => $completed,
                'revenue' => (float) $revenue,
            ];
        });
        $maxTrend = max(1, (int) $weeklyTrend->max(fn ($day) => max($day['created'], $day['completed'])));
        $maxRevenue = max(1, (float) $weeklyTrend->max('revenue'));

        return view('tenant.dashboard', compact(
            'tenant',
            'branches',
            'employeeCount',
            'userCount',
            'todayApplications',
            'completedToday',
            'pendingApplications',
            'slaRisk',
            'todayRevenue',
            'serviceRevenueToday',
            'governmentFeesToday',
            'vatToday',
            'outstandingReceivables',
            'renewalsDue',
            'renewalItems',
            'recentApplications',
            'statusCounts',
            'statusTotal',
            'topServices',
            'topServiceTotal',
            'weeklyTrend',
            'maxTrend',
            'maxRevenue', 'employeesPresent', 'employeesAbsent', 'employeesLate', 'employeeOvertimeMinutes', 'employeeDocumentsDue', 'pendingDocuments', 'submittedApplications', 'returnedApplications', 'customersAddedToday', 'pendingCorporateReceivables', 'pendingApprovals', 'pendingApprovalCount', 'recentPayments', 'expiringEmployeeDocuments', 'corporateOutstanding'
        ));
    }

    public function switchBranch(Request $request)
    {
        $branchId = $request->input('branch_id');
        $user = auth()->user();

        if ($branchId === 'all') {
            abort_unless($user->canViewAllBranches(), 403);
            app(TenantContext::class)->setActiveBranchId('all');

            return back()->with('status', 'Switched to view all branches.');
        }

        $branch = Branch::find($branchId);
        if ($branch) {
            // Verify branch belongs to user's tenant
            if ($branch->tenant_id === $user->tenant_id && $user->canAccessBranch($branch->id)) {
                app(TenantContext::class)->setActiveBranchId($branch->id);

                return back()->with('status', 'Active branch set to '.$branch->name);
            }
        }

        return back()->withErrors(['branch' => 'Unauthorized branch selection.']);
    }

    public function switchLanguage(Request $request, string $locale)
    {
        if (in_array($locale, ['en', 'ar'])) {
            session(['locale' => $locale]);
            if (auth()->check()) {
                auth()->user()->update(['language' => $locale]);
            }
        }

        return back();
    }
}
