<?php

namespace App\Modules\FINANCE\Services;

use App\Modules\FINANCE\Models\Subscription;
use App\Modules\FINANCE\Models\Invoice;
use App\Modules\FINANCE\Models\InvoiceItem;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;

class SubscriptionService
{
    public function __construct(
        private readonly InvoiceNumberService $invoiceNumberService
    ) {}

    /**
     * Process all active subscriptions that are due for renewal.
     */
    public function processRenewals(): void
    {
        $today = Carbon::today();

        $subscriptions = Subscription::where('status', 'active')
            ->where('next_renewal_date', '<=', $today)
            ->get();

        /** @var Subscription $subscription */
        foreach ($subscriptions as $subscription) {
            $this->renewSubscription($subscription);
        }
    }

    /**
     * Renew a subscription and generate an invoice.
     */
    public function renewSubscription(Subscription $subscription): void
    {
        DB::transaction(function () use ($subscription) {
            $plan = $subscription->plan;
            $invoiceDate = Carbon::today();
            $dueDate = $invoiceDate->copy()->addDays(7);

            $invoice = Invoice::create([
                'company_id'     => $subscription->company_id,
                'client_id'      => $subscription->client_id,
                'invoice_number' => $this->invoiceNumberService->generate($subscription->company_id),
                'invoice_date'   => $invoiceDate,
                'due_date'       => $dueDate,
                'sub_total'      => $plan->price,
                'tax_total'      => 0,
                'total_amount'   => $plan->price,
                'balance_amount' => $plan->price,
                'currency_id'    => $subscription->client->currency_id,
                'exchange_rate'  => 1,
                'status'         => 'sent',
                'notes'          => 'Subscription renewal: ' . $plan->name,
            ]);

            InvoiceItem::create([
                'invoice_id'   => $invoice->id,
                'description'  => 'Subscription Renewal - ' . $plan->name,
                'quantity'     => 1,
                'unit_price'   => $plan->price,
                'tax_id'       => null,
                'tax_amount'   => 0,
                'total_amount' => $plan->price,
            ]);

            $nextRenewal = $this->calculateNextRenewalDate($subscription->next_renewal_date, $plan->billing_cycle);
            $subscription->update(['next_renewal_date' => $nextRenewal]);
        });
    }

    /**
     * Calculate next renewal date.
     */
    protected function calculateNextRenewalDate(mixed $currentDate, string $billingCycle): Carbon
    {
        $date = $currentDate instanceof Carbon ? $currentDate->copy() : Carbon::parse($currentDate);

        return match ($billingCycle) {
            'weekly'  => $date->addWeek(),
            'monthly' => $date->addMonth(),
            'yearly'  => $date->addYear(),
            default   => $date->addMonth(),
        };
    }
}
