<?php

namespace App\Http\Controllers\Platform;

use App\Http\Controllers\Concerns\HandlesImageUploads;
use App\Http\Controllers\Controller;
use App\Models\Hotel;
use App\Models\HotelInvoice;
use App\Models\PlatformPlan;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;

class PlatformController extends Controller
{
    use HandlesImageUploads;

    public function dashboard()
    {
        $hotels = Hotel::with('plan')->get();
        $active = $hotels->filter->isActive();

        $stats = [
            'hotels' => $hotels->count(),
            'active' => $active->count(),
            'trials' => $hotels->where('status', 'trial')->count(),
            'suspended' => $hotels->reject->isActive()->count(),
            'mrr' => (float) $active->sum(fn ($hotel) => (float) ($hotel->plan->price_monthly ?? 0)),
            'collected_month' => (float) HotelInvoice::where('status', 'paid')->whereBetween('paid_at', [now()->startOfMonth(), now()])->sum('amount'),
            'unpaid_invoices' => HotelInvoice::where('status', 'unpaid')->count(),
            'unpaid_amount' => (float) HotelInvoice::where('status', 'unpaid')->sum('amount'),
        ];

        $expiring = $hotels->filter(fn ($hotel) => $hotel->isActive()
            && ($hotel->status === 'trial' ? $hotel->trial_ends_at : $hotel->subscription_expires_at)?->lte(now()->addDays(14)))
            ->sortBy(fn ($hotel) => $hotel->status === 'trial' ? $hotel->trial_ends_at : $hotel->subscription_expires_at);

        $recentInvoices = HotelInvoice::with('hotel')->latest()->limit(8)->get();

        return view('platform.dashboard', compact('stats', 'hotels', 'expiring', 'recentInvoices'));
    }

    public function hotels(Request $request)
    {
        $hotels = Hotel::with('plan')->withCount('staff')
            ->when($request->filled('q'), fn ($q) => $q->where('name', 'like', '%' . $request->q . '%'))
            ->latest()
            ->paginate(15)->withQueryString();

        $plans = PlatformPlan::where('status', 'active')->orderBy('price_monthly')->get();

        return view('platform.hotels', compact('hotels', 'plans'));
    }

    public function storeHotel(Request $request)
    {
        $data = $request->validate([
            'name' => 'required|string|max:120',
            'slug' => 'required|alpha_dash|max:60|unique:hotels,slug',
            'email' => 'required|email|max:120',
            'phone' => 'nullable|string|max:40',
            'city' => 'nullable|string|max:80',
            'platform_plan_id' => 'required|exists:platform_plans,id',
            'trial_days' => 'required|integer|min:0|max:90',
            'admin_name' => 'required|string|max:120',
            'admin_email' => 'required|email|max:120|unique:users,email',
            'admin_password' => 'required|string|min:8',
        ]);

        $hotel = Hotel::create([
            'name' => $data['name'],
            'slug' => Str::lower($data['slug']),
            'email' => $data['email'],
            'phone' => $data['phone'] ?? null,
            'city' => $data['city'] ?? null,
            'platform_plan_id' => $data['platform_plan_id'],
            'status' => $data['trial_days'] > 0 ? 'trial' : 'active',
            'trial_ends_at' => $data['trial_days'] > 0 ? now()->addDays($data['trial_days']) : null,
            'subscription_expires_at' => $data['trial_days'] > 0 ? null : now()->addMonth(),
        ]);

        User::create([
            'name' => $data['admin_name'],
            'email' => $data['admin_email'],
            'password' => Hash::make($data['admin_password']),
            'role' => 'admin',
            'hotel_id' => $hotel->id,
            'status' => 'active',
            'department' => 'Management',
            'referral_code' => strtoupper(Str::random(8)),
        ]);

        // Starter settings so the new portal works out of the box.
        foreach ([
            'hotel_name' => $hotel->name, 'currency' => '₦', 'tax_percent' => '7.5',
            'email' => $hotel->email, 'phone' => (string) $hotel->phone,
            'checkin_time' => '14:00', 'checkout_time' => '12:00', 'referral_points' => '50',
        ] as $key => $value) {
            \App\Models\Setting::withoutGlobalScopes()->create(['hotel_id' => $hotel->id, 'key' => $key, 'value' => $value]);
        }

        return back()->with('success', "{$hotel->name} onboarded. Portal login: {$data['admin_email']} — subdomain: {$hotel->slug}.epelcon.com");
    }

    public function updateHotel(Request $request, Hotel $hotel)
    {
        $data = $request->validate([
            'name' => 'required|string|max:120',
            'email' => 'nullable|email|max:120',
            'phone' => 'nullable|string|max:40',
            'city' => 'nullable|string|max:80',
            'domain' => 'nullable|string|max:120|unique:hotels,domain,' . $hotel->id,
            'platform_plan_id' => 'required|exists:platform_plans,id',
            'subscription_expires_at' => 'nullable|date',
        ]);

        if ($logo = $this->saveImage($request, 'logo', 'vendors')) {
            $data['logo'] = $logo;
        }

        $hotel->update($data);

        return back()->with('success', 'Hotel updated.');
    }

    public function setHotelStatus(Request $request, Hotel $hotel)
    {
        $request->validate(['status' => 'required|in:trial,active,suspended']);

        $hotel->update(['status' => $request->status]);

        return back()->with('success', "{$hotel->name} is now {$request->status}.");
    }

    public function actAs(Hotel $hotel)
    {
        session(['acting_hotel_id' => $hotel->id]);

        return redirect()->route('epelcon.dashboard')->with('success', "You are now viewing {$hotel->name}'s portal as platform owner.");
    }

    public function stopActing()
    {
        session()->forget('acting_hotel_id');

        return redirect()->route('platform.dashboard');
    }

    public function storePlan(Request $request)
    {
        PlatformPlan::create($this->validatePlan($request));

        return back()->with('success', 'Platform plan created.');
    }

    public function updatePlan(Request $request, PlatformPlan $plan)
    {
        $plan->update($this->validatePlan($request) + ['status' => $request->input('status', 'active')]);

        return back()->with('success', 'Plan updated.');
    }

    public function invoices(Request $request)
    {
        $invoices = HotelInvoice::with(['hotel', 'plan'])
            ->when($request->filled('status'), fn ($q) => $q->where('status', $request->status))
            ->latest()
            ->paginate(20)->withQueryString();

        $hotels = Hotel::orderBy('name')->get(['id', 'name']);

        return view('platform.invoices', compact('invoices', 'hotels'));
    }

    public function generateInvoice(Request $request)
    {
        $request->validate(['hotel_id' => 'required|exists:hotels,id']);

        $hotel = Hotel::with('plan')->findOrFail($request->hotel_id);

        if (! $hotel->plan) {
            return back()->with('error', 'Assign a plan to this hotel first.');
        }

        $start = $hotel->subscription_expires_at?->isFuture()
            ? $hotel->subscription_expires_at->copy()
            : now();

        HotelInvoice::create([
            'code' => 'INV-' . strtoupper(Str::random(8)),
            'hotel_id' => $hotel->id,
            'platform_plan_id' => $hotel->platform_plan_id,
            'amount' => $hotel->plan->price_monthly,
            'period_start' => $start->toDateString(),
            'period_end' => $start->copy()->addMonth()->toDateString(),
        ]);

        return back()->with('success', "Invoice raised for {$hotel->name} — " . number_format($hotel->plan->price_monthly, 2));
    }

    public function markInvoicePaid(HotelInvoice $invoice)
    {
        if ($invoice->status === 'paid') {
            return back()->with('error', 'Invoice already settled.');
        }

        $invoice->update(['status' => 'paid', 'paid_via' => 'manual', 'paid_at' => now()]);
        $this->extendSubscription($invoice);

        return back()->with('success', "Invoice {$invoice->code} marked paid — subscription extended.");
    }

    public static function extendSubscription(HotelInvoice $invoice): void
    {
        $hotel = $invoice->hotel;

        $base = $hotel->subscription_expires_at?->isFuture()
            ? $hotel->subscription_expires_at
            : now();

        $hotel->update([
            'status' => 'active',
            'subscription_expires_at' => $base->copy()->addMonth(),
            'trial_ends_at' => null,
        ]);
    }

    private function validatePlan(Request $request): array
    {
        $data = $request->validate([
            'name' => 'required|string|max:80',
            'price_monthly' => 'required|numeric|min:0',
            'max_rooms' => 'required|integer|min:1|max:10000',
            'features' => 'nullable|string',
        ]);

        $data['features'] = array_values(array_filter(array_map('trim', explode("\n", $data['features'] ?? ''))));

        return $data;
    }
}
