<?php

namespace App\Http\Controllers\SuperAdmin;

use App\Http\Controllers\Controller;
use App\Models\PlatformPayment;
use App\Models\Subscription;
use App\Models\SubscriptionPlan;
use App\Models\Organization;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Carbon\Carbon;

class SubscriptionController extends Controller
{
    public function index(Request $request): JsonResponse
    {
        $query = Subscription::with('organization');

        if ($request->filled('search')) {
            $q = $request->input('search');
            $query->whereHas('organization', fn($qb) =>
                $qb->where('name', 'like', "%{$q}%")->orWhere('email', 'like', "%{$q}%")
            );
        }

        if ($request->filled('plan')) {
            $query->where('plan', $request->input('plan'));
        }

        if ($request->filled('status')) {
            $query->where('status', $request->input('status'));
        }

        $subs = $query->orderByDesc('created_at')->paginate(15);

        return response()->json($subs);
    }

    public function store(Request $request): JsonResponse
    {
        $validated = $request->validate([
            'organization_id'      => 'required|exists:organizations,id',
            'plan'                 => 'required|string|max:50',
            'status'               => 'required|in:active,cancelled,expired,trial',
            'amount'               => 'nullable|numeric|min:0',
            'billing_cycle'        => 'required|in:monthly,yearly',
            'current_period_start' => 'nullable|date',
            'current_period_end'   => 'nullable|date',
            'trial_ends_at'        => 'nullable|date',
            'notes'                => 'nullable|string|max:1000',
        ]);

        $planModel = SubscriptionPlan::where('name', $validated['plan'])->first();

        // Auto-fill amount from plan pricing if not provided or zero
        if (empty($validated['amount']) && $planModel) {
            $validated['amount'] = $validated['billing_cycle'] === 'yearly'
                ? $planModel->yearly_price
                : $planModel->monthly_price;
        }

        // Compute period dates
        $start = isset($validated['current_period_start']) && $validated['current_period_start']
            ? Carbon::parse($validated['current_period_start'])
            : Carbon::now();

        $validated['current_period_start'] = $start->toDateString();

        if ($validated['status'] === 'trial') {
            // Trial end = plan trial_days or default 14 days
            $trialDays = $planModel?->trial_days ?? 14;
            $trialEnd  = $start->copy()->addDays($trialDays);
            $validated['trial_ends_at']      = $validated['trial_ends_at']
                ? Carbon::parse($validated['trial_ends_at'])->toDateString()
                : $trialEnd->toDateString();
            $validated['current_period_end'] = $validated['current_period_end']
                ? Carbon::parse($validated['current_period_end'])->toDateString()
                : Carbon::parse($validated['trial_ends_at'])->toDateString();
        } else {
            // Active / other: period end = +1 month or +1 year
            if (empty($validated['current_period_end'])) {
                $validated['current_period_end'] = $validated['billing_cycle'] === 'yearly'
                    ? $start->copy()->addYear()->toDateString()
                    : $start->copy()->addMonth()->toDateString();
            } else {
                $validated['current_period_end'] = Carbon::parse($validated['current_period_end'])->toDateString();
            }
        }

        // Cancel any existing active/trial subscription for this org
        Subscription::where('organization_id', $validated['organization_id'])
            ->whereIn('status', ['active', 'trial'])
            ->update(['status' => 'cancelled', 'cancelled_at' => now()]);

        $sub = Subscription::create($validated);
        $sub->load('organization');

        return response()->json(['message' => 'Subscription assigned.', 'data' => $sub], 201);
    }

    public function update(Request $request, Subscription $subscription): JsonResponse
    {
        $validated = $request->validate([
            'plan'                 => 'sometimes|string|max:50',
            'status'               => 'sometimes|in:active,cancelled,expired,trial',
            'amount'               => 'sometimes|numeric|min:0',
            'billing_cycle'        => 'sometimes|in:monthly,yearly',
            'current_period_start' => 'nullable|date',
            'current_period_end'   => 'nullable|date',
            'trial_ends_at'        => 'nullable|date',
            'notes'                => 'nullable|string|max:1000',
        ]);

        // Auto-fill amount from plan if switching plan or billing cycle and amount not provided
        if ((isset($validated['plan']) || isset($validated['billing_cycle'])) && !isset($validated['amount'])) {
            $planName  = $validated['plan'] ?? $subscription->plan;
            $cycle     = $validated['billing_cycle'] ?? $subscription->billing_cycle;
            $planModel = SubscriptionPlan::where('name', $planName)->first();
            if ($planModel) {
                $validated['amount'] = $cycle === 'yearly'
                    ? $planModel->yearly_price
                    : $planModel->monthly_price;
            }
        }

        // Set cancelled_at timestamp when cancelling
        if (isset($validated['status']) && $validated['status'] === 'cancelled' && !$subscription->cancelled_at) {
            $validated['cancelled_at'] = now();
        }

        // Clear cancelled_at when re-activating
        if (isset($validated['status']) && in_array($validated['status'], ['active', 'trial'])) {
            $validated['cancelled_at'] = null;
        }

        $subscription->update($validated);
        $subscription->load('organization');

        return response()->json(['message' => 'Subscription updated.', 'data' => $subscription]);
    }

    public function destroy(Subscription $subscription): JsonResponse
    {
        $subscription->delete();
        return response()->json(['message' => 'Subscription deleted.']);
    }

    public function monitoring(): JsonResponse
    {
        $now = Carbon::now();

        $counts = [
            'active'    => Subscription::where('status', 'active')->count(),
            'trial'     => Subscription::where('status', 'trial')->count(),
            'expired'   => Subscription::where('status', 'expired')->count(),
            'cancelled' => Subscription::where('status', 'cancelled')->count(),
        ];

        // Subscriptions expiring within the next 7 days
        $expiringSoon = Subscription::with('organization:id,name,email')
            ->where('status', 'active')
            ->whereBetween('current_period_end', [$now, $now->copy()->addDays(7)])
            ->orderBy('current_period_end')
            ->get(['id', 'organization_id', 'plan', 'current_period_end']);

        // Recent failed platform payments
        $failedPayments = PlatformPayment::with('organization:id,name')
            ->where('status', 'failed')
            ->orderByDesc('created_at')
            ->limit(10)
            ->get();

        // Trial accounts expiring soon (within 3 days)
        $trialsExpiringSoon = Subscription::with('organization:id,name,email')
            ->where('status', 'trial')
            ->whereBetween('trial_ends_at', [$now, $now->copy()->addDays(3)])
            ->orderBy('trial_ends_at')
            ->get(['id', 'organization_id', 'plan', 'trial_ends_at']);

        return response()->json([
            'counts'              => $counts,
            'expiring_soon'       => $expiringSoon,
            'failed_payments'     => $failedPayments,
            'trials_expiring'     => $trialsExpiringSoon,
        ]);
    }

    public function stats(): JsonResponse
    {
        $byPlan = Subscription::selectRaw('plan, count(*) as count, sum(amount) as revenue')
            ->groupBy('plan')
            ->get();

        $byStatus = Subscription::selectRaw('status, count(*) as count')
            ->groupBy('status')
            ->get();

        $mrr = Subscription::where('status', 'active')
            ->where('billing_cycle', 'monthly')
            ->sum('amount');

        $arr = Subscription::where('status', 'active')
            ->where('billing_cycle', 'yearly')
            ->sum('amount');

        return response()->json([
            'by_plan'   => $byPlan,
            'by_status' => $byStatus,
            'mrr'       => round($mrr, 2),
            'arr'       => round($arr / 12, 2),
        ]);
    }
}
