<?php

namespace App\Http\Controllers\CustomerApp;

use App\Http\Controllers\Controller;
use App\Models\Area;
use App\Models\Booking;
use App\Models\BookingStatusLog;
use App\Models\CustomerAddress;
use App\Models\PartnerProfile;
use App\Models\Rating;
use App\Models\Service;
use App\Models\ServiceCategory;
use App\Models\Setting;
use App\Models\SubscriptionVisit;
use App\Models\User;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Validation\Rule;

class CustomerAppController extends Controller
{
    public function __construct()
    {
        \Illuminate\Support\Facades\View::share('siteName', Setting::get('site_name', 'Befikreyy'));
        \Illuminate\Support\Facades\View::share('sitePhone', Setting::get('site_phone', '+91 7291061623'));
        \Illuminate\Support\Facades\View::share('siteEmail', Setting::get('site_email', 'contactus@befikreyyhomes.com'));
        \Illuminate\Support\Facades\View::share('siteAddress', Setting::get('site_address', 'Flat F701, Supertech Ecociti, Sector 137, Noida'));
        \Illuminate\Support\Facades\View::share('siteWhatsapp', Setting::get('site_whatsapp', '917291061623'));
    }

    /* ===== Splash & Auth ===== */

    public function splash()
    {
        if (Auth::check()) {
            return redirect()->route('app.home');
        }
        return view('customerapp.splash');
    }

    public function showLogin()
    {
        if (Auth::check()) {
            return redirect()->route('app.home');
        }
        return view('customerapp.login');
    }

    public function login(Request $request)
    {
        $data = $request->validate([
            'identifier' => ['required', 'string'],
            'password' => ['required', 'string', 'min:4'],
        ]);

        $identifier = $data['identifier'];
        $field = filter_var($identifier, FILTER_VALIDATE_EMAIL) ? 'email' : 'phone';

        if (!Auth::attempt([$field => $identifier, 'password' => $data['password']], true)) {
            return back()->withErrors(['identifier' => 'Invalid credentials. Please check your phone/email and password.'])->withInput();
        }
        $request->session()->regenerate();
        return redirect()->route('app.home');
    }

    public function showRegister()
    {
        if (Auth::check()) {
            return redirect()->route('app.home');
        }
        return view('customerapp.register');
    }

    public function register(Request $request)
    {
        $data = $request->validate([
            'name' => ['required', 'string', 'max:120'],
            'phone' => ['required', 'string', 'min:10', 'max:15', 'unique:users,phone'],
            'email' => ['nullable', 'email', 'unique:users,email'],
            'password' => ['required', 'string', 'min:6', 'confirmed'],
            'role' => ['required', Rule::in(['customer', 'partner'])],
            'terms' => ['accepted'],
        ]);

        $email = $data['email'] ?? $data['phone'] . '@befikreyy.app';

        $user = User::create([
            'name' => $data['name'],
            'email' => $email,
            'phone' => $data['phone'],
            'password' => Hash::make($data['password']),
            'role' => $data['role'],
            'is_partner_approved' => $data['role'] === 'partner' ? false : true,
        ]);

        if ($data['role'] === 'partner') {
            PartnerProfile::create([
                'user_id' => $user->id,
                'display_name' => $user->name,
            ]);
        }

        Auth::login($user);
        $request->session()->regenerate();
        return redirect()->route('app.home');
    }

    public function logout(Request $request)
    {
        Auth::logout();
        $request->session()->invalidate();
        $request->session()->regenerateToken();
        return redirect()->route('app.splash');
    }

    /* ===== App pages ===== */

    public function home(Request $request)
    {
        $user = Auth::user();
        $categories = ServiceCategory::active()->ordered()->withCount(['services' => fn($q) => $q->where('is_active', true)])->get();
        $popular = Service::active()->featured()->ordered()->limit(6)->get();
        $recent = Booking::with(['service'])
            ->where('customer_id', $user->id)
            ->orderByDesc('id')->limit(3)->get();
        $stats = [
            'active' => Booking::where('customer_id', $user->id)->whereIn('subscription_status', ['active', 'paused'])->count(),
            'visits' => SubscriptionVisit::whereHas('booking', fn($q) => $q->where('customer_id', $user->id))->where('status', 'completed')->count(),
            'spent' => Booking::where('customer_id', $user->id)->sum('total_paise'),
        ];
        $user->load(['addresses' => fn($q) => $q->where('is_default', true)]);
        $defaultAddress = $user->addresses->first();
        $hasLocation = !is_null($user->lat) && !is_null($user->lng);
        return view('customerapp.home', compact('user', 'categories', 'popular', 'recent', 'stats', 'defaultAddress', 'hasLocation'));
    }

    public function services(Request $request)
    {
        $categories = ServiceCategory::active()->ordered()->get();
        $q = Service::active()->ordered();
        if ($request->filled('category')) {
            $q->whereHas('category', fn($qq) => $qq->where('slug', $request->string('category')));
        }
        if ($request->filled('q')) {
            $term = '%' . $request->string('q') . '%';
            $q->where(fn($qq) => $qq->where('name', 'like', $term)->orWhere('tagline', 'like', $term));
        }
        $services = $q->paginate(20);
        $activeCategory = $request->string('category');
        return view('customerapp.services', compact('services', 'categories', 'activeCategory'));
    }

    public function service($slug)
    {
        $service = Service::active()->where('slug', $slug)->firstOrFail();
        $related = Service::active()->where('id', '!=', $service->id)
            ->where('category_id', $service->category_id)
            ->ordered()->limit(4)->get();
        return view('customerapp.service', compact('service', 'related'));
    }

    public function bookings(Request $request)
    {
        $user = Auth::user();
        $tab = (string) $request->string('tab', 'active');
        $q = Booking::with(['service', 'partner.user', 'area', 'rating', 'visits'])
            ->where('customer_id', $user->id);
        $q = match ($tab) {
            'paused' => $q->where('subscription_status', 'paused'),
            'cancelled' => $q->where('subscription_status', 'cancelled'),
            'all' => $q,
            default => $q->whereIn('subscription_status', ['active', 'paused']),
        };
        $bookings = $q->orderByDesc('id')->paginate(20);
        return view('customerapp.bookings', compact('bookings', 'tab'));
    }

    public function booking($code)
    {
        $booking = Booking::with(['service', 'partner.user', 'area', 'photos', 'rating', 'visits' => fn($q) => $q->orderBy('scheduled_date', 'desc')])
            ->where('booking_code', $code)
            ->where('customer_id', Auth::id())
            ->firstOrFail();
        return view('customerapp.booking', compact('booking'));
    }

    public function schedule(Request $request)
    {
        $user = Auth::user();

        // Per-booking schedule with FULL visit history (not limited to 1 month)
        $bookings = Booking::with([
            'service',
            'partner.user',
            'area',
            'visits' => fn($q) => $q->orderBy('scheduled_date', 'desc'),
        ])
            ->where('customer_id', $user->id)
            ->whereIn('subscription_status', ['active', 'paused'])
            ->get();

        // Per-booking stats
        $bookingStats = [];
        foreach ($bookings as $b) {
            $visits = $b->visits;
            $bookingStats[$b->id] = [
                'total' => $visits->count(),
                'completed' => $visits->where('status', 'completed')->count(),
                'scheduled' => $visits->where('status', 'scheduled')->count(),
                'skipped' => $visits->whereIn('status', ['skipped', 'cancelled'])->count(),
                'next' => $visits->where('status', 'scheduled')->sortBy('scheduled_date')->first(),
                'last' => $visits->where('status', 'completed')->sortByDesc('completed_at')->first(),
                'first' => $visits->sortBy('scheduled_date')->first(),
            ];
        }

        $overallStats = [
            'subs' => $bookings->count(),
            'total_visits' => array_sum(array_column($bookingStats, 'total')),
            'completed' => array_sum(array_column($bookingStats, 'completed')),
            'scheduled' => array_sum(array_column($bookingStats, 'scheduled')),
        ];

        return view('customerapp.schedule', compact('user', 'bookings', 'bookingStats', 'overallStats'));
    }

    public function cancelSubscription($code)
    {
        $booking = Booking::where('booking_code', $code)
            ->where('customer_id', Auth::id())
            ->whereIn('subscription_status', ['active', 'paused'])
            ->firstOrFail();
        $booking->update([
            'subscription_status' => 'cancelled',
            'auto_renew' => false,
            'cancelled_at' => now(),
        ]);
        $booking->visits()->where('status', 'scheduled')->update(['status' => 'cancelled', 'cancelled_at' => now()]);
        BookingStatusLog::create([
            'booking_id' => $booking->id,
            'status' => 'cancelled',
            'note' => 'Subscription cancelled from app',
            'changed_by' => Auth::id(),
        ]);
        return back()->with('success', 'Subscription cancelled.');
    }

    public function pauseSubscription($code)
    {
        $booking = Booking::where('booking_code', $code)
            ->where('customer_id', Auth::id())
            ->where('subscription_status', 'active')
            ->firstOrFail();
        $booking->update(['subscription_status' => 'paused']);
        BookingStatusLog::create(['booking_id' => $booking->id, 'status' => 'paused', 'note' => 'Paused from app', 'changed_by' => Auth::id()]);
        return back()->with('success', 'Subscription paused.');
    }

    public function resumeSubscription($code)
    {
        $booking = Booking::where('booking_code', $code)
            ->where('customer_id', Auth::id())
            ->where('subscription_status', 'paused')
            ->firstOrFail();
        $booking->update(['subscription_status' => 'active']);
        BookingStatusLog::create(['booking_id' => $booking->id, 'status' => 'active', 'note' => 'Resumed from app', 'changed_by' => Auth::id()]);
        return back()->with('success', 'Subscription resumed.');
    }

    public function rate(Request $request, $code)
    {
        $data = $request->validate([
            'stars' => ['required', 'integer', 'between:1,5'],
            'review' => ['nullable', 'string', 'max:500'],
        ]);
        $booking = Booking::where('booking_code', $code)
            ->where('customer_id', Auth::id())
            ->firstOrFail();
        Rating::updateOrCreate(
            ['booking_id' => $booking->id],
            ['stars' => $data['stars'], 'review' => $data['review'] ?? null]
        );
        return back()->with('success', 'Thanks for your rating!');
    }

    public function profile(Request $request)
    {
        $user = Auth::user();
        $addresses = CustomerAddress::where('user_id', $user->id)->orderByDesc('is_default')->get();
        return view('customerapp.profile', compact('user', 'addresses'));
    }

    public function profileUpdate(Request $request)
    {
        $user = Auth::user();
        $data = $request->validate([
            'name' => ['required', 'string', 'max:120'],
            'email' => ['nullable', 'email', 'unique:users,email,' . $user->id],
            'phone' => ['required', 'string', 'min:10', 'max:15', 'unique:users,phone,' . $user->id],
            'address' => ['nullable', 'string', 'max:255'],
            'city' => ['nullable', 'string', 'max:80'],
            'pincode' => ['nullable', 'string', 'max:10'],
        ]);
        $user->update($data);
        return back()->with('success', 'Profile updated.');
    }

    /**
     * Save customer's current GPS location (called from JS via geolocation).
     * Updates User row + sets as default on next booking.
     */
    public function saveLocation(Request $request)
    {
        $user = Auth::user();
        $data = $request->validate([
            'lat' => ['required', 'numeric', 'between:-90,90'],
            'lng' => ['required', 'numeric', 'between:-180,180'],
            'address' => ['nullable', 'string', 'max:255'],
            'city' => ['nullable', 'string', 'max:80'],
            'pincode' => ['nullable', 'string', 'max:10'],
            'accuracy' => ['nullable', 'numeric'],
            'set_default' => ['nullable', 'boolean'],
        ]);

        $payload = [
            'lat' => $data['lat'],
            'lng' => $data['lng'],
        ];
        if (!empty($data['address'])) $payload['address'] = $data['address'];
        if (!empty($data['city'])) $payload['city'] = $data['city'];
        if (!empty($data['pincode'])) $payload['pincode'] = $data['pincode'];

        $user->update($payload);

        // If set_default, also create/update a default CustomerAddress
        if ($request->boolean('set_default') && !empty($data['address'])) {
            $existing = $user->addresses()->where('is_default', true)->first();
            if ($existing) {
                $existing->update([
                    'address' => $data['address'],
                    'city' => $data['city'] ?? null,
                    'pincode' => $data['pincode'] ?? null,
                    'lat' => $data['lat'],
                    'lng' => $data['lng'],
                ]);
            } else {
                $user->addresses()->create([
                    'label' => 'My current location',
                    'address' => $data['address'],
                    'city' => $data['city'] ?? null,
                    'pincode' => $data['pincode'] ?? null,
                    'lat' => $data['lat'],
                    'lng' => $data['lng'],
                    'is_default' => true,
                ]);
            }
        }

        return response()->json([
            'ok' => true,
            'lat' => $data['lat'],
            'lng' => $data['lng'],
            'accuracy' => $data['accuracy'] ?? null,
        ]);
    }

    public function addressSave(Request $request)
    {
        $user = Auth::user();
        $data = $request->validate([
            'label' => ['required', 'string', 'max:40'],
            'address' => ['required', 'string', 'max:255'],
            'area_id' => ['nullable', 'integer', 'exists:areas,id'],
            'pincode' => ['nullable', 'string', 'max:10'],
            'is_default' => ['nullable', 'boolean'],
            'lat' => ['nullable', 'numeric', 'between:-90,90'],
            'lng' => ['nullable', 'numeric', 'between:-180,180'],
        ]);
        if ($data['is_default'] ?? false) {
            CustomerAddress::where('user_id', $user->id)->update(['is_default' => false]);
        }
        CustomerAddress::create([
            'user_id' => $user->id,
            'label' => $data['label'],
            'address' => $data['address'],
            'area_id' => $data['area_id'] ?? null,
            'pincode' => $data['pincode'] ?? null,
            'is_default' => $data['is_default'] ?? false,
            'lat' => $data['lat'] ?? $user->lat,
            'lng' => $data['lng'] ?? $user->lng,
        ]);
        return back()->with('success', 'Address saved.');
    }

    public function addressDestroy($id)
    {
        CustomerAddress::where('id', $id)->where('user_id', Auth::id())->delete();
        return back()->with('success', 'Address removed.');
    }

    public function help()
    {
        return view('customerapp.help');
    }

    public function contact()
    {
        return view('customerapp.contact');
    }

    public function about()
    {
        return view('customerapp.about');
    }
}