<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\Subscription;
use App\Models\Plan;
use App\Models\Delivery;
use Illuminate\Http\Request;
use Illuminate\Support\Str;
use Carbon\Carbon;

class SubscriptionController extends Controller
{
    /**
     * List authenticated user's subscriptions.
     */
    public function index(Request $request)
    {
        $subscriptions = $request->user()
            ->subscriptions()
            ->with(['plan', 'address'])
            ->latest()
            ->get();

        return response()->json(['subscriptions' => $subscriptions]);
    }

    /**
     * Get a single subscription with details.
     */
    public function show(Request $request, Subscription $subscription)
    {
        $this->authorize('view', $subscription);

        $subscription->load(['plan', 'address', 'deliveries.meals', 'payments']);

        return response()->json(['subscription' => $subscription]);
    }

    /**
     * Create a new subscription.
     */
    public function store(Request $request)
    {
        $validated = $request->validate([
            'plan_id' => 'required|exists:plans,id',
            'address_id' => 'required|exists:addresses,id',
            'dietary_preferences' => 'nullable|array',
            'dietary_preferences.*' => 'string',
            'allergies' => 'nullable|array',
            'allergies.*' => 'string',
            'special_instructions' => 'nullable|string|max:500',
            'payment_method_id' => 'required|string', // Stripe payment method
        ]);

        $plan = Plan::findOrFail($validated['plan_id']);

        // TODO: Create Stripe subscription using payment_method_id
        // $stripeSubscription = $this->createStripeSubscription($request->user(), $plan, $validated['payment_method_id']);

        $subscription = Subscription::create([
            'user_id' => $request->user()->id,
            'plan_id' => $plan->id,
            'address_id' => $validated['address_id'],
            'stripe_subscription_id' => null, // Set from Stripe response
            'status' => 'active',
            'dietary_preferences' => $validated['dietary_preferences'] ?? [],
            'allergies' => $validated['allergies'] ?? [],
            'special_instructions' => $validated['special_instructions'] ?? null,
            'starts_at' => now(),
            'current_period_start' => now(),
            'current_period_end' => now()->addMonth(),
        ]);

        // Generate initial deliveries
        $this->generateDeliveries($subscription);

        return response()->json([
            'subscription' => $subscription->load(['plan', 'address', 'deliveries']),
        ], 201);
    }

    /**
     * Pause a subscription.
     */
    public function pause(Request $request, Subscription $subscription)
    {
        $this->authorize('update', $subscription);

        if (!$subscription->isActive()) {
            return response()->json(['message' => 'Subscription is not active.'], 422);
        }

        // TODO: Pause Stripe subscription

        $subscription->pause();

        // Skip upcoming deliveries
        $subscription->deliveries()
            ->where('status', 'scheduled')
            ->where('scheduled_date', '>', now())
            ->update(['status' => 'skipped']);

        return response()->json([
            'subscription' => $subscription->fresh()->load('plan'),
            'message' => 'Subscription paused successfully.',
        ]);
    }

    /**
     * Resume a paused subscription.
     */
    public function resume(Request $request, Subscription $subscription)
    {
        $this->authorize('update', $subscription);

        if (!$subscription->isPaused()) {
            return response()->json(['message' => 'Subscription is not paused.'], 422);
        }

        // TODO: Resume Stripe subscription

        $subscription->resume();

        // Re-generate upcoming deliveries
        $this->generateDeliveries($subscription);

        return response()->json([
            'subscription' => $subscription->fresh()->load('plan'),
            'message' => 'Subscription resumed successfully.',
        ]);
    }

    /**
     * Cancel a subscription.
     */
    public function cancel(Request $request, Subscription $subscription)
    {
        $this->authorize('update', $subscription);

        if ($subscription->status === 'cancelled') {
            return response()->json(['message' => 'Subscription is already cancelled.'], 422);
        }

        // TODO: Cancel Stripe subscription

        $subscription->cancel();

        // Cancel all upcoming deliveries
        $subscription->deliveries()
            ->where('status', 'scheduled')
            ->update(['status' => 'skipped']);

        return response()->json([
            'subscription' => $subscription->fresh()->load('plan'),
            'message' => 'Subscription cancelled successfully.',
        ]);
    }

    /**
     * Generate delivery schedule for a subscription.
     */
    private function generateDeliveries(Subscription $subscription): void
    {
        $plan = $subscription->plan;
        $startDate = Carbon::parse($subscription->starts_at)->startOfDay();

        // Generate 2 weeks of deliveries
        $daysToGenerate = 14;

        for ($day = 0; $day < $daysToGenerate; $day++) {
            $date = $startDate->copy()->addDays($day);

            // For daily: deliver every day
            // For weekly: deliver on select days (Mon, Wed, Fri by default)
            if ($plan->frequency === 'weekly') {
                $deliveryDays = [Carbon::MONDAY, Carbon::WEDNESDAY, Carbon::FRIDAY];
                if (!in_array($date->dayOfWeek, $deliveryDays)) {
                    continue;
                }
            }

            if ($subscription->deliveries()->where('scheduled_date', $date->toDateString())->exists()) {
                continue;
            }

            Delivery::create([
                'subscription_id' => $subscription->id,
                'address_id' => $subscription->address_id,
                'scheduled_date' => $date->toDateString(),
                'time_slot' => 'morning',
                'status' => 'scheduled',
                'tracking_code' => strtoupper(Str::random(8)),
            ]);
        }
    }
}
