<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\Company;
use App\Models\Department;
use App\Models\Employee;
use App\Models\IntercompanyLoan;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

class DashboardController extends Controller
{
    public function index(Request $request)
    {
        $user = $request->user();

        if ($user->isSuperAdmin()) {
            return $this->superAdminDashboard();
        } else {
            return $this->companyDashboard($user->company_id);
        }
    }

    private function superAdminDashboard()
    {
        // Aggregate top-level totals across all companies (including holding company)
        $totalCompanies = Company::count();
        $activeCompanies = Company::where('status', 'active')->count();
        $totalEmployees = Employee::count();
        $totalUsers = User::count();
        $totalDepartments = Department::count();

        // Financial aggregates
        $totalRevenue = (float) Company::sum('revenue');
        $totalExpenses = (float) Company::sum('expenses_manual');
        // Include payable invoices as outgoing money
        try {
            $payableInvoices = (float) DB::table('invoices')->where('type', 'payable')->sum('total_amount');
        } catch (\Exception $e) { $payableInvoices = 0; }
        $totalExpenses += $payableInvoices;

        $netProfit = $totalRevenue - $totalExpenses;

        // Cash and bank balances
        $companyCash = (float) Company::sum('cash_balance');
        $bankBalances = 0;
        try {
            $bankBalances = (float) DB::table('bank_accounts')->sum('current_balance');
        } catch (\Exception $e) { $bankBalances = 0; }
        // include super admin bank accounts
        $superBank = (float) \App\Models\SuperAdminBankAccount::sum('current_balance');
        $totalCashAndBanks = $companyCash + $bankBalances + $superBank;

        // Loans across group
        $totalLoaned = (float) IntercompanyLoan::sum('principal_amount');
        $totalRepaid = (float) DB::table('loan_repayments')->whereIn('status', ['paid','confirmed'])->sum('total_amount');
        $totalLoanInterest = (float) DB::table('loan_repayments')->whereIn('status', ['paid','confirmed'])->sum('interest_amount');
        $outstandingLoans = max(0, $totalLoaned - $totalRepaid);

        // Assets
        $totalAssetsCount = (int) \App\Models\CompanyAsset::count();
        $totalAssetsValue = (float) \App\Models\CompanyAsset::sum('current_value');

        $stats = [
            'total_companies' => $totalCompanies,
            'active_companies' => $activeCompanies,
            'total_employees' => $totalEmployees,
            'total_users' => $totalUsers,
            'total_departments' => $totalDepartments,

            'financials' => [
                'total_revenue' => $totalRevenue,
                'total_expenses' => $totalExpenses,
                'net_profit' => $netProfit,
                'company_cash' => $companyCash,
                'bank_balances' => $bankBalances + $superBank,
                'total_cash_and_banks' => $totalCashAndBanks,
            ],

            'loans' => [
                'total_loaned' => $totalLoaned,
                'total_repaid' => $totalRepaid,
                'total_interest' => $totalLoanInterest,
                'outstanding' => $outstandingLoans,
            ],

            'assets' => [
                'count' => $totalAssetsCount,
                'total_value' => $totalAssetsValue,
            ],

            'companies_by_status' => Company::select('status', DB::raw('count(*) as count'))->groupBy('status')->get(),
            'recent_companies' => Company::withCount('employees')->orderBy('created_at', 'desc')->limit(8)->get()->map(fn($c)=>[
                'id'=>$c->id,'name'=>$c->name,'status'=>$c->status,'industry'=>$c->industry,'employee_count'=>$c->employees_count,'revenue'=>(float)$c->revenue,'cash_balance'=>(float)$c->cash_balance,'total_assets'=>(float)$c->total_assets
            ]),
        ];

        return response()->json($stats);
    }

    private function companyDashboard($companyId)
    {
        $company = Company::findOrFail($companyId);
        $fin     = DB::table('companies')->where('id', $companyId)->first();

        // Use monthly financial model for consistent current month data (includes staff loans in expenses)
        $mfin = \App\Models\MonthlyCompanyFinancial::recalculateMonth($company->id, now()->format('Y-m'));
        $rev    = (float) $mfin->revenue;
        $exp    = (float) $mfin->expenses;
        $profit = (float) $mfin->net_profit;

        $cash   = isset($fin->cash_balance) && $fin->cash_balance !== null ? (float)$fin->cash_balance : 0;
        $assetSum = (float) \DB::table('company_assets')
            ->where('company_id', $company->id)
            ->where('status', 'active')
            ->sum('current_value');
        $storedAssets = isset($fin->total_assets) && $fin->total_assets !== null ? (float)$fin->total_assets : 0;
        $assets = $assetSum > 0 ? $assetSum : $storedAssets;
        $liab   = isset($fin->total_liabilities) && $fin->total_liabilities !== null ? (float)$fin->total_liabilities : 0;
        $margin = $rev > 0 ? round(($profit / $rev) * 100, 1) : 0;
        $runway = $fin->runway_days ?? 0;
        $health = $fin->health_status ?? 'good';

        // Build revenue trend for chart (6 months) from real invoice + expense data
        $months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
        $revenueTrend = [];
        $invTotalAll  = 0;
        for ($i = 5; $i >= 0; $i--) {
            $m     = \Carbon\Carbon::now()->subMonths($i);
            $mStart = $m->copy()->startOfMonth();
            $mEnd   = $m->copy()->endOfMonth();
            $rv = 0;
            try {
                $rv = (float) \DB::table('invoices')
                    ->where('company_id', $company->id)
                    ->where('type', 'receivable')
                    ->whereBetween('invoice_date', [$mStart, $mEnd])
                    ->whereIn('status', ['sent', 'viewed', 'partial', 'paid'])
                    ->sum('total_amount');
            } catch (\Exception $e) {}
            $invTotalAll += $rv;
            $ex = (float) \App\Models\Expense::where('company_id', $company->id)
                ->whereBetween('expense_date', [$mStart, $mEnd])
                ->whereNotIn('status', ['rejected', 'cancelled'])
                ->sum('amount');
            // Include payable invoices in expenses (money going out)
            $payableInv = (float) \DB::table('invoices')
                ->where('company_id', $company->id)
                ->where('type', 'payable')
                ->whereBetween('invoice_date', [$mStart, $mEnd])
                ->whereIn('status', ['sent', 'viewed', 'partial', 'paid'])
                ->sum('total_amount');
            // Include staff loan deductions in expenses for historical consistency
            $loanDed = (float) \DB::table('staff_loan_deductions')
                ->join('staff_loans', 'staff_loan_deductions.staff_loan_id', '=', 'staff_loans.id')
                ->where('staff_loans.company_id', $company->id)
                ->whereBetween('staff_loan_deductions.due_date', [$mStart, $mEnd])
                ->where('staff_loan_deductions.status', 'deducted')
                ->sum('staff_loan_deductions.deduction_amount');
            $totalExpenses = $ex + $payableInv + $loanDed;
            $revenueTrend[] = [
                'month'    => $months[$m->month - 1],
                'revenue'  => (int) $rv,
                'expenses' => (int) $totalExpenses,
                'profit'   => (int) ($rv - $totalExpenses),
            ];
        }
        // Spread stored annual revenue evenly if no invoice records
        if ($invTotalAll === 0 && $rev > 0) {
            $monthly = (int)($rev / 12);
            $revenueTrend = array_map(fn($r) => array_merge($r, ['revenue' => $monthly, 'profit' => $monthly - $r['expenses']]), $revenueTrend);
        }

        $stats = [
            'companyName'      => $company->name,
            'totalRevenue'     => $rev,
            'totalExpenses'    => $exp,
            'netProfit'        => $profit,
            'cashBalance'      => $cash,
            'totalAssets'      => $assets,
            'totalLiabilities' => $liab,
            'profitMargin'     => $margin,
            'liquidityRatio'   => $liab > 0 ? round($assets / $liab, 2) : 1.5,
            'debtToEquity'     => ($assets - $liab) > 0 ? round($liab / ($assets - $liab), 2) : 0.45,
            'runwayDays'       => $runway,
            'healthStatus'     => $health,
            'activeEmployees'  => $company->employees()->where('status', 'active')->count(),
            'totalEmployees'   => $company->employees()->count(),
            'totalDepartments' => $company->departments()->count(),
            'totalUsers'       => $company->users()->count(),
            'revenueChange'    => 0,
            'profitChange'     => 0,
            'expensesChange'   => 0,
            'cashChange'       => 0,
            'employeesChange'  => 0,
        ];

        $empCount   = $company->employees()->count();
        $activeEmp  = $company->employees()->where('status','active')->count();
        $deptCount  = $company->departments()->count();
        $usersCount = $company->users()->count();
        $hireTrend  = $company->employees()
            ->select('hire_date')
            ->where('hire_date', '>=', now()->subMonths(6))
            ->get()
            ->groupBy(fn($e) => $e->hire_date->format('Y-m'))
            ->map(fn($g, $ym) => ['month' => (new \DateTime($ym.'-01'))->format('M'), 'year_month' => $ym, 'count' => $g->count()])
            ->sortKeys()->values();

        return response()->json([
            'stats'             => $stats,
            'total_employees'   => $empCount,
            'active_employees'  => $activeEmp,
            'total_departments' => $deptCount,
            'total_users'       => $usersCount,
            'monthly_hire_trend'=> $hireTrend,
            'revenueData'       => $revenueTrend,
            'expenseData' => array_map(fn($r) => ['month'=>$r['month'],'amount'=>$r['expenses']], $revenueTrend),
            'assetData'   => array_map(fn($r) => ['month'=>$r['month'],'amount'=>$r['revenue']*0.85], $revenueTrend),
            'deptData'    => $company->departments()->withCount('employees')->get()->map(fn($d)=>['name'=>$d->name,'value'=>$d->employees_count]),
            'payrollData' => array_map(fn($r) => ['month'=>$r['month'],'amount'=>$r['expenses']*0.42], $revenueTrend),
            'company'     => array_merge($company->toArray(), ['employee_count' => $company->employees()->count()]),
            'employees_by_department' => $company->departments()
                ->withCount('employees')
                ->get()
                ->map(fn($dept) => ['department' => $dept->name, 'count' => $dept->employees_count]),
            'employees_by_type' => $company->employees()
                ->select('employment_type', DB::raw('count(*) as count'))
                ->groupBy('employment_type')
                ->get(),
            'employees_by_status' => $company->employees()
                ->select('status', DB::raw('count(*) as count'))
                ->groupBy('status')
                ->get(),
            'recent_hires' => $company->employees()
                ->with('department')
                ->orderBy('hire_date', 'desc')
                ->limit(10)
                ->get()
                ->map(fn($e) => array_merge($e->toArray(), ['full_name' => $e->first_name . ' ' . $e->last_name])),
            'monthly_hire_trend' => $company->employees()
                ->select('hire_date')
                ->where('hire_date', '>=', now()->subMonths(6))
                ->get()
                ->groupBy(fn($e) => $e->hire_date->format('Y-m'))
                ->map(fn($group, $yearMonth) => [
                    'month' => (new \DateTime($yearMonth . '-01'))->format('M'),
                    'year_month' => $yearMonth,
                    'count' => $group->count(),
                ])
                ->sortKeys()
                ->values(),
            'departments_list' => $company->departments()
                ->with('manager')
                ->withCount('employees')
                ->get(),
        ]);
    }

    public function analytics(Request $request)
    {
        $user = $request->user();
        $companyId = $request->get('company_id', $user->company_id);

        if (!$user->canAccessCompany($companyId)) {
            return response()->json(['message' => 'Unauthorized'], 403);
        }

        $company = Company::findOrFail($companyId);

        $analytics = [
            'employee_demographics' => [
                'by_employment_type' => $company->employees()
                    ->select('employment_type', DB::raw('count(*) as count'))
                    ->groupBy('employment_type')
                    ->get(),
                'by_status' => $company->employees()
                    ->select('status', DB::raw('count(*) as count'))
                    ->groupBy('status')
                    ->get(),
            ],
            
            'department_analytics' => $company->departments()
                ->withCount('employees')
                ->with('manager')
                ->get(),
            
            'hiring_trends' => [
                'last_12_months' => $company->employees()
                    ->select('hire_date')
                    ->where('hire_date', '>=', now()->subMonths(12))
                    ->get()
                    ->groupBy(fn($e) => $e->hire_date->format('Y-m'))
                    ->map(fn($group, $month) => [
                        'month' => $month,
                        'count' => $group->count(),
                    ])
                    ->sortKeys()
                    ->values(),
                'current_month' => $company->employees()
                    ->whereMonth('hire_date', now()->month)
                    ->whereYear('hire_date', now()->year)
                    ->count(),
                'previous_month' => $company->employees()
                    ->whereMonth('hire_date', now()->subMonth()->month)
                    ->whereYear('hire_date', now()->subMonth()->year)
                    ->count(),
            ],
            
            'turnover' => [
                'terminated_this_year' => $company->employees()
                    ->where('status', 'terminated')
                    ->whereYear('updated_at', now()->year)
                    ->count(),
                'resigned_this_year' => $company->employees()
                    ->where('status', 'resigned')
                    ->whereYear('updated_at', now()->year)
                    ->count(),
            ],
        ];

        return response()->json($analytics);
    }
}
