<?php

namespace App\Http\Controllers\SuperAdmin;

use App\Http\Controllers\Controller;
use App\Models\{AuditLog, Company, CompanyGroup, CompanySession, CompanySubscription, Setting, User};
use App\Support\BrandLogoManager;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\{DB, Hash, Log, Schema};
use Illuminate\Validation\ValidationException;

class DashboardController extends Controller
{
    public function dashboard()
    {
        $stats = [
            'total_companies'  => Company::count(),
            'active_companies' => Company::where('status', 'active')->count(),
            'trial_companies'  => Company::where('status', 'trial')->count(),
            'suspended'        => Company::where('status', 'suspended')->count(),
            'online_users'     => CompanySession::where('last_activity', '>=', now()->subMinutes(30)->timestamp)->count(),
        ];

        $companies = Company::with('subscription')
            ->withCount('users')
            ->latest()
            ->paginate(15);

        $recent_logs = AuditLog::latest('created_at')->take(10)->get();
        $appLogo = app(BrandLogoManager::class)->appLogoStatus();

        return view('superadmin.dashboard', compact('stats', 'companies', 'recent_logs', 'appLogo'));
    }

    // ── Companies List ────────────────────────────────────────────────────────
    public function companies(Request $request)
    {
        $query = Company::with(['subscription', 'group'])->withCount('users');

        if ($request->filled('search')) {
            $search = $request->search;
            $query->where(function ($q) use ($search) {
                $q->where('name', 'like', "%{$search}%")
                  ->orWhere('company_code', 'like', "%{$search}%")
                  ->orWhere('email', 'like', "%{$search}%");
            });
        }

        if ($request->filled('status')) {
            $query->where('status', $request->status);
        }

        $companies = $query->latest()->paginate(20)->withQueryString();
        $groups = $this->companyGroups(withCompanies: true);

        return view('superadmin.companies.index', compact('companies', 'groups'));
    }

    // ── Create Company ────────────────────────────────────────────────────────
    public function createCompany()
    {
        $groups = $this->companyGroups();

        return view('superadmin.companies.create', compact('groups'));
    }

    public function storeCompany(Request $request)
    {
        $groupRules = Schema::hasTable('company_groups')
            ? 'nullable|integer|exists:company_groups,id'
            : 'nullable';

        $validated = $request->validate([
            'name'                    => 'required|string|max:150',
            'company_code'            => ['required','string','max:20','unique:companies,company_code','regex:/^[A-Z0-9]+$/'],
            'email'                   => 'nullable|email|max:150',
            'phone'                   => 'nullable|string|max:30',
            'address'                 => 'nullable|string|max:500',
            'country'                 => 'nullable|string|max:80',
            'admin_name'              => 'required|string|max:100',
            'admin_username'          => ['required','string','max:50','regex:/^[a-z0-9_]+$/'],
            'admin_email'             => 'nullable|email|max:150',
            'admin_password'          => 'required|string|min:8|confirmed',
            'max_concurrent_users'    => 'required|integer|min:1|max:1000',
            'session_timeout_minutes' => 'required|integer|min:15|max:1440',
            'subscription_ends_at'    => 'nullable|date',
            'trial_ends_at'           => 'nullable|date',
            'monthly_fee'             => 'nullable|numeric|min:0|max:999999',
            'notes'                   => 'nullable|string|max:1000',
            'company_group_id'        => $groupRules,
        ]);

        try {
            DB::transaction(function () use ($validated) {
            $companyAttributes = [
                'name'         => $validated['name'],
                'company_code' => strtoupper($validated['company_code']),
                'email'        => $validated['email'] ?? null,
                'phone'        => $validated['phone'] ?? null,
                'address'      => $validated['address'] ?? null,
                'country'      => $validated['country'] ?? null,
                'status'       => 'trial',
            ];

            if (Schema::hasColumn('companies', 'company_group_id')) {
                $companyAttributes['company_group_id'] = $validated['company_group_id'] ?? null;
            }

            // 1. Company
            $company = Company::create($companyAttributes);

            // 2. Subscription
            CompanySubscription::create([
                'company_id'              => $company->id,
                'max_concurrent_users'    => $validated['max_concurrent_users'],
                'session_timeout_minutes' => $validated['session_timeout_minutes'],
                'subscription_ends_at'    => $validated['subscription_ends_at'] ?? null,
                'trial_ends_at'           => $validated['trial_ends_at'] ?? now()->addDays(30),
                'monthly_fee'             => $validated['monthly_fee'] ?? 0,
                'notes'                   => $validated['notes'] ?? null,
                'modules_enabled'         => null,
            ]);

            // 3. Admin user — withoutGlobalScopes because no tenant auth
            User::withoutGlobalScopes()->create([
                'company_id'  => $company->id,
                'name'        => $validated['admin_name'],
                'username'    => strtolower($validated['admin_username']),
                'email'       => $validated['admin_email'] ?? null,
                'password'    => Hash::make($validated['admin_password']),
                'is_admin'    => true,
                'is_active'   => true,
            ]);

            // 4. Default settings
            $now = now();
            $settingsData = [];
            foreach (Setting::defaults() as $key => $value) {
                $settingsData[] = [
                    'company_id' => $company->id,
                    'key'        => $key,
                    'value'      => $value,
                    'created_at' => $now,
                    'updated_at' => $now,
                ];
            }
            Setting::insert($settingsData);

            // 5. Default fiscal year
            $startDate = \Carbon\Carbon::createFromDate(now()->year, 1, 1);
            $endDate   = $startDate->copy()->addYear()->subDay();

            \App\Models\FiscalYear::create([
                'company_id' => $company->id,
                'name'       => $startDate->format('Y') . '-' . $endDate->format('Y'),
                'start_date' => $startDate,
                'end_date'   => $endDate,
                'status'     => 'open',
                'is_current' => true,
            ]);

            // 6. Audit log AFTER all records are created
            AuditLog::record('create', 'company', (string) $company->id,
                null, ['name' => $company->name, 'code' => $company->company_code],
                "Company created: {$company->name}");
            });
        } catch (ValidationException $e) {
            throw $e;
        } catch (\Throwable $e) {
            Log::error('Company create failed: ' . $e->getMessage(), ['exception' => $e]);

            return back()
                ->withInput()
                ->with('error', 'Could not create company: ' . $e->getMessage());
        }

        return redirect()->route('sadmin.companies')
            ->with('success', 'Company created successfully.');
    }

    // ── Edit Company ──────────────────────────────────────────────────────────
    public function editCompany(Company $company)
    {
        $company->load(['subscription', 'group']);
        $groups = $this->companyGroups();
        // Load users separately with count to avoid N+1
        $users = User::withoutGlobalScopes()
            ->withTrashed()
            ->where('company_id', $company->id)
            ->select(['id','name','username','email','is_admin','is_active','last_login_at','deleted_at'])
            ->get();

        return view('superadmin.companies.edit', compact('company', 'users', 'groups'));
    }

    public function updateCompany(Request $request, Company $company)
    {
        $validated = $request->validate([
            'name'                    => 'required|string|max:150',
            'email'                   => 'nullable|email|max:150',
            'phone'                   => 'nullable|string|max:30',
            'address'                 => 'nullable|string|max:500',
            'country'                 => 'nullable|string|max:80',
            'status'                  => 'required|in:active,suspended,expired,trial',
            'max_concurrent_users'    => 'required|integer|min:1|max:1000',
            'session_timeout_minutes' => 'required|integer|min:15|max:1440',
            'subscription_ends_at'    => 'nullable|date',
            'monthly_fee'             => 'nullable|numeric|min:0|max:999999',
            'notes'                   => 'nullable|string|max:1000',
            'company_group_id'        => Schema::hasTable('company_groups')
                ? 'nullable|integer|exists:company_groups,id'
                : 'nullable',
        ]);

        DB::transaction(function () use ($validated, $company) {
            $old = $company->only(['name','email','phone','status','country','company_group_id']);

            $companyAttributes = [
                'name'    => $validated['name'],
                'email'   => $validated['email'] ?? null,
                'phone'   => $validated['phone'] ?? null,
                'address' => $validated['address'] ?? null,
                'country' => $validated['country'] ?? null,
                'status'  => $validated['status'],
            ];

            if (Schema::hasColumn('companies', 'company_group_id')) {
                $companyAttributes['company_group_id'] = $validated['company_group_id'] ?? null;
            }

            $company->update($companyAttributes);

            if ($company->subscription) {
                $company->subscription->update([
                    'max_concurrent_users'    => $validated['max_concurrent_users'],
                    'session_timeout_minutes' => $validated['session_timeout_minutes'],
                    'subscription_ends_at'    => $validated['subscription_ends_at'] ?? null,
                    'monthly_fee'             => $validated['monthly_fee'] ?? 0,
                    'notes'                   => $validated['notes'] ?? null,
                ]);
            }

            $new = $company->only(['name','email','phone','status','country','company_group_id']);
            AuditLog::record('update', 'company', (string) $company->id,
                $old, $new, "Company updated: {$company->name}");
        });

        return redirect()->route('sadmin.companies')
            ->with('success', 'Company updated successfully.');
    }

    // ── Toggle Status ─────────────────────────────────────────────────────────
    public function toggleStatus(Company $company)
    {
        $oldStatus = $company->status;
        $newStatus = $oldStatus === 'active' ? 'suspended' : 'active';

        $company->update(['status' => $newStatus]);

        AuditLog::record('status_change', 'company', (string) $company->id,
            ['status' => $oldStatus],
            ['status' => $newStatus],
            "Company status changed to {$newStatus}: {$company->name}");

        return back()->with('success', "Company {$newStatus} successfully.");
    }

    // ── Online Users ──────────────────────────────────────────────────────────
    public function onlineUsers()
    {
        $sessions = CompanySession::with(['company', 'user'])
            ->where('last_activity', '>=', now()->subMinutes(30)->timestamp)
            ->latest('last_activity')
            ->get();

        $byCompany = $sessions->groupBy('company_id');
        return view('superadmin.online-users', compact('sessions', 'byCompany'));
    }

    // ── Force Logout ──────────────────────────────────────────────────────────
    public function forceLogout(Request $request)
    {
        $request->validate(['session_id' => 'required|string']);

        if ($request->session_id === 'ALL') {
            CompanySession::whereNotNull('user_id')->delete();
            AuditLog::record('force_logout', 'auth', null, null, null, 'All sessions force-terminated by Super Admin');
            return back()->with('success', 'All user sessions terminated.');
        }

        $session = CompanySession::find($request->session_id);
        if ($session) {
            AuditLog::record('force_logout', 'auth', (string) $session->user_id,
                null, null, "Session force-terminated by Super Admin. User ID: {$session->user_id}");
            $session->delete();
        }

        return back()->with('success', 'User session terminated.');
    }

    private function companyGroups(bool $withCompanies = false)
    {
        if (!\Illuminate\Support\Facades\Schema::hasTable('company_groups')) {
            return collect();
        }

        $query = CompanyGroup::query()->orderBy('name');

        if ($withCompanies) {
            $query->with(['companies' => fn ($q) => $q->orderBy('name')])->withCount('companies');
        }

        return $query->get();
    }

    // ── Audit Logs ────────────────────────────────────────────────────────────
    public function auditLogs(Request $request)
    {
        $query = AuditLog::latest('created_at');

        if ($request->filled('company_id')) $query->where('company_id', $request->company_id);
        if ($request->filled('action'))     $query->where('action', $request->action);
        if ($request->filled('module'))     $query->where('module', $request->module);
        if ($request->filled('date_from'))  $query->whereDate('created_at', '>=', $request->date_from);
        if ($request->filled('date_to'))    $query->whereDate('created_at', '<=', $request->date_to);

        $logs      = $query->paginate(50)->withQueryString();
        $companies = Company::select('id', 'name')->orderBy('name')->get();

        return view('superadmin.audit-logs', compact('logs', 'companies'));
    }
}
