<?php

namespace App\Http\Controllers\Web;

use App\Http\Controllers\Controller;
use App\Models\Company;
use App\Models\SubscriptionPlan;
use App\Models\SubscriptionRequest;
use App\Services\PlanPricingService;
use App\Services\RazorpaySubscriptionPaymentService;
use Illuminate\Http\Request;
use Illuminate\Validation\ValidationException;

class SubscriptionRequestController extends Controller
{
    public function create(PlanPricingService $pricingService, RazorpaySubscriptionPaymentService $razorpay)
    {
        $user = request()->user();
        if ($user->is_superadmin ?? false) {
            abort(404);
        }
        if (empty($user->company_id)) {
            abort(403, 'No company associated with your account.');
        }

        $company = Company::with('subscriptionPlan')->findOrFail($user->company_id);
        $plans = SubscriptionPlan::query()
            ->where('active', true)
            ->orderBy('position')
            ->orderBy('employee_limit')
            ->get();

        $seatUsed = $company->activeEmployeeCount();
        $seatLimit = $company->employeeSeatLimit();
        $quotes = [];

        foreach ($plans as $plan) {
            if ($plan->is_custom || $plan->isFreeDefault()) {
                continue;
            }

            if ($company->isLicenceExpired() || $company->status === 'suspended' || ! $company->licence_expire_on) {
                $mode = 'renew';
            } elseif ($pricingService->canUpgradeTo($company, $plan)) {
                $mode = 'upgrade';
            } elseif ((int) $company->subscription_plan_id === (int) $plan->id) {
                $mode = 'renew';
            } else {
                $currentLimit = $company->subscriptionPlan?->employee_limit;
                if ($currentLimit !== null && $plan->employee_limit !== null && (int) $plan->employee_limit <= (int) $currentLimit) {
                    // Mid-cycle downgrade / same tier not offered as upgrade cards
                    continue;
                }
                $mode = 'purchase';
            }

            try {
                $quotes[$plan->id] = $pricingService->quoteForCheckout($company, $plan, $mode);
                $quotes[$plan->id]['checkout_mode'] = $mode;
            } catch (\Throwable $e) {
                $quotes[$plan->id] = null;
            }
        }

        [$razorpayKeyId] = $razorpay->getKeys();

        return view('subscription.request', compact(
            'company',
            'plans',
            'seatUsed',
            'seatLimit',
            'quotes',
            'razorpayKeyId'
        ));
    }

    public function quote(Request $request, PlanPricingService $pricingService)
    {
        $user = $request->user();
        $company = Company::with('subscriptionPlan')->findOrFail($user->company_id);
        $data = $request->validate([
            'subscription_plan_id' => 'required|exists:subscription_plans,id',
            'mode' => 'required|in:purchase,upgrade,renew',
            'coupon_code' => 'nullable|string|max:64',
        ]);

        $plan = SubscriptionPlan::findOrFail($data['subscription_plan_id']);
        if ($plan->is_custom) {
            throw ValidationException::withMessages(['subscription_plan_id' => 'Custom plans require an offline request.']);
        }

        $mode = $data['mode'];
        if ($mode === 'upgrade' && ! $pricingService->canUpgradeTo($company, $plan)) {
            throw ValidationException::withMessages(['mode' => 'This plan is not available as a mid-cycle upgrade.']);
        }

        $quote = $pricingService->quoteForCheckout(
            $company,
            $plan,
            $mode,
            $data['coupon_code'] ?? null
        );

        return response()->json(collect($quote)->except('coupon')->all());
    }

    public function store(Request $request, PlanPricingService $pricingService)
    {
        $user = $request->user();
        if ($user->is_superadmin ?? false) {
            abort(404);
        }
        if (empty($user->company_id)) {
            abort(403, 'No company associated with your account.');
        }

        $company = Company::with('subscriptionPlan')->findOrFail($user->company_id);

        $data = $request->validate([
            'subscription_plan_id' => 'required|exists:subscription_plans,id',
            'mode' => 'nullable|in:purchase,upgrade,renew',
            'coupon_code' => 'nullable|string|max:64',
            'employee_count' => 'nullable|integer|min:1',
            'notes' => 'nullable|string|max:1000',
        ]);

        $plan = SubscriptionPlan::findOrFail($data['subscription_plan_id']);
        $mode = $data['mode'] ?? 'purchase';

        if ($plan->is_custom && empty($data['notes'])) {
            throw ValidationException::withMessages(['notes' => 'Please describe your requirements for a custom package.']);
        }

        if (! $plan->is_custom && $mode === 'upgrade' && ! $pricingService->canUpgradeTo($company, $plan)) {
            throw ValidationException::withMessages(['subscription_plan_id' => 'Mid-cycle upgrade is only allowed to a higher seat plan.']);
        }

        if ($plan->is_custom) {
            $quote = [
                'mode' => 'purchase',
                'billing_cycle' => 'yearly',
                'subtotal_before_discount' => 0,
                'plan_discount_amount' => 0,
                'addons_total' => 0,
                'coupon_discount_amount' => 0,
                'total' => 0,
                'coupon' => null,
                'coupon_code' => null,
                'is_upgrade' => false,
                'days_remaining' => null,
                'unused_credit' => null,
                'upgrade_gross' => null,
                'selected_addons' => [],
            ];
        } else {
            if ($company->isLicenceExpired() || $company->status === 'suspended') {
                $mode = 'renew';
            } elseif ($pricingService->canUpgradeTo($company, $plan)) {
                $mode = 'upgrade';
            } else {
                $mode = in_array($mode, ['purchase', 'renew'], true) ? $mode : 'renew';
            }
            $quote = $pricingService->quoteForCheckout($company, $plan, $mode, $data['coupon_code'] ?? null);
        }

        $employeeCount = (int) ($data['employee_count'] ?? $plan->employee_limit ?? $company->activeEmployeeCount() ?: 1);
        if (! $plan->is_custom && $plan->employee_limit && $employeeCount > $plan->employee_limit) {
            throw ValidationException::withMessages([
                'employee_count' => 'Employee count cannot exceed the plan limit of '.$plan->employee_limit.'.',
            ]);
        }

        SubscriptionRequest::create([
            'company_id' => $company->id,
            'subscription_plan_id' => $plan->id,
            'employee_count' => $employeeCount,
            'billing_cycle' => 'yearly',
            'payment_path' => 'offline',
            'coupon_id' => $quote['coupon']?->id,
            'coupon_code' => $quote['coupon_code'],
            'subtotal_before_discount' => $quote['subtotal_before_discount'] ?? 0,
            'plan_discount_amount' => $quote['plan_discount_amount'] ?? 0,
            'coupon_discount_amount' => $quote['coupon_discount_amount'] ?? 0,
            'is_upgrade' => (bool) ($quote['is_upgrade'] ?? false),
            'days_remaining' => $quote['days_remaining'] ?? null,
            'unused_credit' => $quote['unused_credit'] ?? null,
            'upgrade_gross' => $quote['upgrade_gross'] ?? null,
            'selected_addons' => $quote['selected_addons'] ?? [],
            'amount' => $quote['total'] ?? 0,
            'addons_total' => $quote['addons_total'] ?? 0,
            'calculated_total' => $quote['total'] ?? 0,
            'currency' => config('app.currency_code', 'INR'),
            'status' => 'pending',
            'requested_at' => now(),
            'notes' => $data['notes'] ?? null,
        ]);

        return redirect()->route('subscription.request')
            ->with('success', 'Your offline subscription request has been submitted. Super Admin will review it shortly.');
    }

    public function createCheckoutOrder(Request $request, PlanPricingService $pricingService, RazorpaySubscriptionPaymentService $razorpay)
    {
        $user = $request->user();
        $company = Company::with('subscriptionPlan')->findOrFail($user->company_id);

        $data = $request->validate([
            'subscription_plan_id' => 'required|exists:subscription_plans,id',
            'mode' => 'required|in:purchase,upgrade,renew',
            'coupon_code' => 'nullable|string|max:64',
        ]);

        $plan = SubscriptionPlan::findOrFail($data['subscription_plan_id']);
        if ($plan->is_custom || $plan->isFreeDefault()) {
            return response()->json(['message' => 'This plan cannot be purchased online.'], 422);
        }

        $mode = $data['mode'];
        if ($mode === 'upgrade' && ! $pricingService->canUpgradeTo($company, $plan)) {
            return response()->json(['message' => 'Upgrade not available for this plan.'], 422);
        }
        if ($company->isLicenceExpired() || $company->status === 'suspended') {
            $mode = 'renew';
        } elseif ($pricingService->canUpgradeTo($company, $plan)) {
            $mode = 'upgrade';
        }

        $quote = $pricingService->quoteForCheckout($company, $plan, $mode, $data['coupon_code'] ?? null);

        try {
            $order = $razorpay->createOrderForCompany(
                $company,
                $plan,
                $quote,
                $user->id,
                true,
                $mode !== 'upgrade'
            );
        } catch (\Throwable $e) {
            return response()->json(['message' => $e->getMessage()], 500);
        }

        return response()->json($order);
    }

    public function verifyCheckout(Request $request, RazorpaySubscriptionPaymentService $razorpay)
    {
        $data = $request->validate([
            'razorpay_order_id' => 'required|string',
            'razorpay_payment_id' => 'required|string',
            'razorpay_signature' => 'required|string',
        ]);

        $result = $razorpay->verifyAndFulfill(
            $data['razorpay_order_id'],
            $data['razorpay_payment_id'],
            $data['razorpay_signature']
        );

        if (! ($result['ok'] ?? false)) {
            return redirect()->route('subscription.request')
                ->with('error', $result['message'] ?? 'Payment verification failed.');
        }

        return redirect()->route('subscription.request')
            ->with('success', 'Payment successful. Your subscription has been updated.');
    }
}
