<?php

namespace MtcPharmacy\Subscriptions\Http\Controllers;

use Carbon\Carbon;
use Mtc\Core\RateLimit;
use Illuminate\Http\Request;
use Mtc\Modules\Members\Models\Member;
use MtcPharmacy\Multisite\Classes\MultisiteSite;
use MtcPharmacy\Subscriptions\Classes\Subscription;
use Illuminate\Routing\Controller as BaseController;
use MtcPharmacy\Subscriptions\Classes\SubscriptionLog;
use MtcPharmacy\Subscriptions\Classes\SubscriptionItem;
use MtcPharmacy\Subscriptions\Classes\SubscriptionPreference;


class SubscriptionsController extends BaseController
{

    public function update_subscription($subscription_id, Request $request)
    {
        // Apply rate limiting: 15 updates per minute
        $rateLimit = RateLimit::log(
            'subscription_update',
            'Too many update requests. Please wait before trying again.',
            15,
            60
        );

        if ($rateLimit && $rateLimit['limited']) {
            return response()->json([
                'error' => $rateLimit['message'],
                'retry_after' => $rateLimit['retry_after']
            ], 429);
        }

        $subscription = Subscription::findOrFail($subscription_id);
        $subscription->authoriseAccessByCurrentUser();
        $oldValues = $subscription->toArray();

        // get next_issue_date from FE in d/m/Y format
        $next_issue_date_input = $request->input('next_issue_date');

        if (empty($next_issue_date_input)) {
            return response()->json([
                'error' => 'Please enter a valid date'
            ], 422);
        }

        // Validate format d/m/Y
        if (!preg_match('/^\d{2}\/\d{2}\/\d{4}$/', $next_issue_date_input)) {
            return response()->json([
                'error' => 'Please enter a valid date in DD/MM/YYYY format'
            ], 422);
        }

        // Convert d/m/Y to Y-m-d for database storage
        try {
            $next_issue_date_set = Carbon::createFromFormat('d/m/Y', $next_issue_date_input);
        } catch (\Exception $e) {
            return response()->json([
                'error' => 'Invalid date provided'
            ], 422);
        }
        // Get current date plus buffer days
        $currentDatePlusBuffer = now()->addDays(Subscription::ORDER_CREATE_DAYS_BEFORE_DISPATCH + 1);

        // Convert the next_issue_date to a Carbon instance if it's not already
        $nextIssueDate = $next_issue_date_set->startOfDay();
        $currentDatePlusBufferDay = $currentDatePlusBuffer->copy()->startOfDay();
        // Maximum allowed reschedule days from current next issue date
        $maxRescheduleDays = config('subscription.max_reschedule_days', 45);

        // If subscription issue date is already in the past, then add max reschedule days to the current date
        if (Carbon::parse($subscription->next_issue_date) < now()) {
            $maxIssueDate = now()->addDays($maxRescheduleDays)->startOfDay();
        } else {
            $maxIssueDate = Carbon::parse($subscription->next_issue_date)->addDays($maxRescheduleDays)->startOfDay();
        }

        // Now compare just the dates
        if ($nextIssueDate->lt($currentDatePlusBufferDay) || $nextIssueDate->gt($maxIssueDate)) {
            return response()->json([
                'error' => 'Next dispatch date must be between ' . $currentDatePlusBufferDay->format('d/m/Y') . ' and ' . $maxIssueDate->format('d/m/Y')
            ], 422);
        }

        $subscription->next_issue_date = $next_issue_date_set->format('Y-m-d');
        $subscription->save();

        return response()->json([
            'success' => 'Subscription updated successfully',
            'next_issue_date' => $next_issue_date_set->format('d/m/Y'), // Return in same format
            'next_payment_date' => Carbon::parse($subscription->getNextOrderDate())->format('d/m/Y')
        ]);
    }

    public function update_subscription_item($subscription_id, Request $request)
    {
        $subscription_id = (int) $subscription_id;
        $subscription = Subscription::findOrFail($subscription_id);
        $subscription->authoriseAccessByCurrentUser();

        $shop_item_id = (int) $request->input('shop_item_id');
        $shop_item_size_id = (int) $request->input('shop_item_size_id');
        $subscription_item_id = (int) $request->input('subscription_item_id');

        $message = '';
        $errors = [];

        $subscription_item = SubscriptionItem::where('id', $subscription_item_id)
            ->where('subscription_id', $subscription_id)
            ->first();

        if (!$subscription_item) {
            $errors[] = $message = 'Invalid subscription item';
        } elseif ($subscription_item->shop_item_size_id == $shop_item_size_id) {
            $errors[] = $message = 'Same item requested. Please select another dosage.';
        } else {
            $subscription_item->update(
                ['shop_item_size_id' => $shop_item_size_id]
            );

            $message = 'This subscription item has been updated.';
            $content_below_basket = "If you'd like to make any changes to your dosage for the next issue, please log in to your account and update your preferences before your next issue date.";

            $subscription->emailSubscriptionUpdates(
                'Your subscription has been updated',
                '',
                $content_below_basket
            );
        }

        return response()->json([
            'error' => (count($errors) > 0),
            'message' => $message,
            'subscription_id' => $subscription_id,
            'shop_item_id' => $shop_item_id,
            'shop_item_size_id' => $shop_item_size_id
        ]);
    }

    public function set_paused($subscription_id, Request $request)
    {
        // Apply rate limiting: 10 attempts per minute
        $rateLimit = RateLimit::log(
            'subscription_pause',
            'Too many pause requests. Please wait before trying again.',
            10,
            60
        );

        if ($rateLimit && $rateLimit['limited']) {
            return redirect()->back()->with('error', $rateLimit['message']);
        }

        $subscription = Subscription::findOrFail($subscription_id);

        if ($subscription) {
            $subscription->authoriseAccessByCurrentUser();
        }

        if ($subscription->isActive()) {
            $subscription->setPaused();
            // Logging is now handled by SubscriptionObserver::updated()

            $subscription->emailSubscriptionUpdates(
                'Your subscription has been paused',
                'pause_subscription'
            );
        }

        return redirect()->back()->with('success', 'Subscription paused successfully');
    }


    public function set_active($subscription_id, Request $request)
    {
        // Apply rate limiting: 10 attempts per minute
        $rateLimit = RateLimit::log(
            'subscription_activate',
            'Too many activation requests. Please wait before trying again.',
            10,
            60
        );

        if ($rateLimit && $rateLimit['limited']) {
            return redirect()->back()->with('error', $rateLimit['message']);
        }

        $subscription = Subscription::findOrFail($subscription_id);

        if ($subscription) {
            $subscription->authoriseAccessByCurrentUser();
        }

        if ($subscription->isPaused()) {
            $subscription->setActive();

            $subscription->emailSubscriptionUpdates(
                'Your subscription has been activated'
            );

        }

        return redirect()->back()->with('success', 'Subscription activated successfully');
    }


    public function set_cancelled($subscription_id, Request $request)
    {
        // Apply rate limiting: 5 cancellations per 5 minutes (more restrictive)
        $rateLimit = RateLimit::log(
            'subscription_cancel',
            'Too many cancellation requests. Please wait before trying again.',
            5,
            300 // 5 minutes
        );

        if ($rateLimit && $rateLimit['limited']) {
            return redirect()->back()->with('error', $rateLimit['message']);
        }

        $subscription = Subscription::findOrFail($subscription_id);

        if ($subscription) {
            $subscription->authoriseAccessByCurrentUser();
        }

        if ($request->has('cancel_reason') && $request->get('cancel_reason') != '') {
            // Sanitize cancel reason to prevent XSS
            $cancelReason = strip_tags($request->input('cancel_reason'));
            $cancelReason = clean_page($cancelReason);

            $subscription->setCancelled(
                $cancelReason
            );

            $subscription->emailSubscriptionUpdates(
                'Your subscription has been cancelled',
                'cancel_subscription'
            );

            return redirect()->back()->with('success', 'Subscription cancelled successfully');
        } else {
            return redirect()->back()->with('error', 'A cancellation reason is required.');
        }
    }



}

