<?php

namespace MtcPharmacy\Subscriptions\Console\Commands;

use Carbon\Carbon;
use Mtc\Shop\Order;
use App\SubscriptionBundleType;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Log;
use MtcPharmacy\Subscriptions\Classes\Subscription;
use MtcPharmacy\Subscriptions\Classes\SubscriptionLog;
use MtcPharmacy\Subscriptions\Classes\SubscriptionItem;
use MtcPharmacy\Subscriptions\Classes\SubscriptionPreference;

/**
 * Examples:
 *     php artisan subscriptions:generate_orders_from_subscriptions
 */


class GenerateOrdersFromSubscriptionsCommand extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'subscriptions:generate_orders {--force} {--fail} {--subscription-id=}';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Generate orders from active subscriptions. Use --fail to mark orders as failed instead of processing payments. Use --subscription-id to process a specific subscription.';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        $this->info(__METHOD__);

        // Check if --fail option is used and confirm with user
        if ($this->option('fail')) {
            $subscriptionId = $this->option('subscription-id');
            $message = $subscriptionId
                ? "Are you sure you want to mark orders as failed for subscription ID {$subscriptionId}? This will simulate payment failures for the generated order."
                : 'Are you sure you want to mark orders as failed? This will simulate payment failures for all generated orders.';

            if (!$this->confirm($message)) {
                $this->info('Operation cancelled.');
                return;
            }
        }

        Log::info("Subscription:-> Generating orders from subscriptions");

        $query = Subscription::active()
            ->whereNotNull('next_issue_date');

        // Filter by specific subscription ID if provided
        if ($this->option('subscription-id')) {
            $subscriptionId = $this->option('subscription-id');

            // Validate that the subscription exists and is active
            $subscription = Subscription::find($subscriptionId);
            if (!$subscription) {
                $this->error("Subscription with ID {$subscriptionId} not found.");
                return;
            }

            if ($subscription->status !== Subscription::STATUS_ACTIVE) {
                $this->error("Subscription with ID {$subscriptionId} is not active (status: {$subscription->status}).");
                return;
            }

            if (!$subscription->next_issue_date) {
                $this->error("Subscription with ID {$subscriptionId} has no next issue date.");
                return;
            }

            $query->where('id', $subscriptionId);
            $this->info("Processing specific subscription ID: {$subscriptionId}");
        }

        // Only check expiry date if --force is not used
        if (!$this->option('force')) {
            $query->whereDate('next_issue_date', '<=', Carbon::now()->addDays(Subscription::ORDER_CREATE_DAYS_BEFORE_DISPATCH)->format('Y-m-d'));
        }

        $active_subscriptions = $query->get();

        if (count($active_subscriptions) === 0) {
            $this->info('Done.');
            return;
        }

        foreach ($active_subscriptions as $sub) {
            try {
                $sub->refresh();

                // Check if order already generated today
                $latest_order = $sub->orders()
                    ->whereDate('created_at', Carbon::today())
                    ->first();

                if ($latest_order) {
                    $this->info("Order already generated today for subscription {$sub->id}");
                    continue;
                }

                $this->info("Processing subscription id:{$sub->id}");
                Log::info("Order from Subscription :-> Processing subscription id:{$sub->id}");
                $this->info(" - generating order...");

                $ignore_checks = $this->option('force');
                $attempt_token_payment = !$this->option('fail');

                // generateNewOrder() handles its own DB transaction internally
                $generated_order = $sub->generateNewOrder($ignore_checks, $attempt_token_payment);

                if ($generated_order) {
                    if ($this->option('fail')) {
                        $this->info(" - marking order id:{$generated_order->id} as failed");
                        $sub->setFailedPayment();
                        \Illuminate\Support\Facades\Event::dispatch('subscriptions.paymentFailed', $sub);
                        $this->info(" - order id:{$generated_order->id} marked as failed");
                    } else {
                        if ($sub->max_number_of_issues == $sub->orders()->count()) {
                            $sub->status = Subscription::STATUS_COMPLETED;
                            $sub->next_issue_date = null;
                        } else {
                            $sub->next_issue_date = $sub->getNextIssueDate(true);
                        }

                        $sub->save();
                        $this->info(" - generated order id:{$generated_order->id}");

                        SubscriptionLog::logOrderGenerated(
                            $sub,
                            $generated_order->id,
                            SubscriptionLog::SOURCE_SYSTEM,
                            ['command' => 'generate_orders', 'automatic' => true]
                        );
                    }
                } else {
                    $this->info(" - no order was generated.");
                }
            } catch (\Exception $exception) {
                Log::error("Error processing subscription {$sub->id}: " . $exception->getMessage());
                $this->error("Error processing subscription {$sub->id}: " . $exception->getMessage());
            }
        }

    }

}
