<?php

namespace App\Http\Controllers\Site;

use App\Http\Controllers\Controller;
use App\Models\Area;
use App\Models\Booking;
use App\Models\BookingStatusLog;
use App\Models\PartnerProfile;
use App\Models\Rating;
use App\Models\Service;
use App\Models\Setting;
use App\Models\SubscriptionVisit;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;

class BookingController extends Controller
{
    public function show(Service $service, Request $request)
    {
        $areas = Area::active()->ordered()->get();
        $selectedArea = null;
        $partners = collect();
        if ($request->filled('area_id')) {
            $selectedArea = Area::find($request->integer('area_id'));
            if ($selectedArea) {
                $partners = PartnerProfile::approved()->available()
                    ->where('suspend_new_bookings', false)
                    ->whereHas('areas', fn($q) => $q->where('areas.id', $selectedArea->id))
                    ->whereHas('services', fn($q) => $q->where('services.id', $service->id))
                    ->with('user')
                    ->orderByDesc('is_online')
                    ->orderByDesc('rating_avg')
                    ->get();
            }
        }
        return view('site.book', compact('service', 'areas', 'selectedArea', 'partners'));
    }

    public function summary(Service $service, Request $request)
    {
        $data = $request->validate([
            'area_id' => ['required', 'exists:areas,id'],
            'partner_id' => ['nullable', 'exists:partner_profiles,id'],
        ]);
        $area = Area::findOrFail($data['area_id']);
        $partner = $data['partner_id'] ? PartnerProfile::find($data['partner_id']) : null;
        $taxPct = (float) Setting::get('tax_percent', '5');
        $tax = (int) round($service->price_paise * $taxPct / 100);
        $total = $service->price_paise + $tax;
        return view('site.book-summary', [
            'service' => $service,
            'area' => $area,
            'partner' => $partner,
            'taxPct' => $taxPct,
            'taxPaise' => $tax,
            'totalPaise' => $total,
        ]);
    }

    public function store(Request $request, Service $service)
    {
        $data = $request->validate([
            'area_id' => ['required', 'exists:areas,id'],
            'partner_id' => ['nullable', 'exists:partner_profiles,id'],
            'customer_name' => ['required', 'string', 'max:120'],
            'customer_phone' => ['required', 'string', 'max:20'],
            'address' => ['required', 'string'],
            'pincode' => ['nullable', 'string', 'max:12'],
            'lat' => ['nullable', 'numeric'],
            'lng' => ['nullable', 'numeric'],
            'scheduled_date' => ['required', 'date', 'after_or_equal:today'],
            'scheduled_slot' => ['required', 'string', 'max:20'],
            'notes' => ['nullable', 'string', 'max:1000'],
            'payment_method' => ['required', 'in:cod,online'],
        ]);

        $taxPct = (float) Setting::get('tax_percent', '5');
        $tax = (int) round($service->price_paise * $taxPct / 100);
        $total = $service->price_paise + $tax;

        $booking = DB::transaction(function () use ($data, $service, $tax, $total) {
            $periodStart = now()->parse($data['scheduled_date'])->startOfDay();
            $periodEnd = $periodStart->copy()->endOfMonth();
            $nextBilling = $periodStart->copy()->addMonth();

            // Monthly subscription = 30 days of daily visits
            $visitsPerPeriod = 30;

            $booking = Booking::create([
                'booking_code' => Booking::generateCode(),
                'subscription_code' => Booking::generateSubscriptionCode(),
                'is_subscription' => true,
                'billing_period' => 'monthly',
                'visits_per_period' => $visitsPerPeriod,
                'visits_used' => 0,
                'subscription_status' => 'active',
                'auto_renew' => true,
                'current_period_start' => $periodStart->toDateString(),
                'current_period_end' => $periodEnd->toDateString(),
                'next_billing_date' => $nextBilling->toDateString(),
                'customer_id' => Auth::id(),
                'partner_id' => $data['partner_id'] ?? null,
                'service_id' => $service->id,
                'area_id' => $data['area_id'],
                'customer_name' => $data['customer_name'],
                'customer_phone' => $data['customer_phone'],
                'address' => $data['address'],
                'pincode' => $data['pincode'] ?? null,
                'lat' => $data['lat'] ?? null,
                'lng' => $data['lng'] ?? null,
                'scheduled_date' => $data['scheduled_date'],
                'scheduled_slot' => $data['scheduled_slot'],
                'notes' => $data['notes'] ?? null,
                'amount_paise' => $service->price_paise,
                'tax_paise' => $tax,
                'total_paise' => $total,
                'status' => 'pending',
                'payment_status' => $data['payment_method'] === 'cod' ? 'pending' : 'paid',
                'payment_method' => $data['payment_method'],
            ]);

            // Generate 30 daily visits starting from scheduled_date using the same slot
            // Auto-accept if a partner is assigned (no manual accept step needed)
            $initialStatus = !empty($data['partner_id']) ? 'accepted' : 'scheduled';
            $visitRows = [];
            for ($i = 0; $i < $visitsPerPeriod; $i++) {
                $day = $periodStart->copy()->addDays($i);
                $visitRows[] = [
                    'booking_id' => $booking->id,
                    'partner_id' => $data['partner_id'] ?? null,
                    'scheduled_date' => $day->toDateString(),
                    'scheduled_slot' => $data['scheduled_slot'],
                    'attendance_status' => 'pending',
                    'customer_visible' => true,
                    'photos_required' => false,
                    'status' => $initialStatus,
                    'created_at' => now(),
                    'updated_at' => now(),
                ];
            }
            SubscriptionVisit::insert($visitRows);

            BookingStatusLog::create([
                'booking_id' => $booking->id,
                'status' => 'pending',
                'note' => 'Subscription created — ' . $visitsPerPeriod . ' daily visits scheduled',
                'changed_by' => Auth::id(),
            ]);
            return $booking;
        });

        return redirect()->route('customer.booking', $booking->booking_code)->with('success', 'Subscription activated! First visit scheduled for ' . $booking->scheduled_date->format('d M Y') . '.');
    }

    public function guestTrackForm()
    {
        return view('site.track');
    }

    public function track(Request $request)
    {
        $code = strtoupper(trim((string) $request->string('booking_code')));
        $phone = trim((string) $request->string('phone'));
        $booking = Booking::where('booking_code', $code)
            ->when($phone, fn($q) => $q->where('customer_phone', $phone))
            ->first();
        if (!$booking) {
            return back()->withErrors(['booking_code' => 'Booking not found. Check the code and phone number.'])->withInput();
        }
        return redirect()->route('booking.public', $booking->booking_code);
    }

    public function publicView($code)
    {
        $booking = Booking::where('booking_code', $code)->firstOrFail();
        return view('site.booking-public', compact('booking'));
    }

    public function pause($code)
    {
        $booking = Booking::where('booking_code', $code)
            ->where('customer_id', Auth::id())
            ->where('is_subscription', true)
            ->firstOrFail();
        $booking->update(['subscription_status' => 'paused']);
        BookingStatusLog::create(['booking_id' => $booking->id, 'status' => 'paused', 'note' => 'Subscription paused by customer', 'changed_by' => Auth::id()]);
        return back()->with('success', 'Subscription paused. You can resume anytime.');
    }

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

    public function cancel($code)
    {
        $booking = Booking::where('booking_code', $code)
            ->where('customer_id', Auth::id())
            ->where('is_subscription', true)
            ->firstOrFail();
        $booking->update(['subscription_status' => 'cancelled', 'auto_renew' => false, 'cancelled_at' => now()]);
        BookingStatusLog::create(['booking_id' => $booking->id, 'status' => 'cancelled', 'note' => 'Subscription cancelled by customer', 'changed_by' => Auth::id()]);
        return back()->with('success', 'Subscription cancelled. No further renewals will be charged.');
    }
}