<?php

namespace App\Http\Controllers\SuperAdmin;

use App\Http\Controllers\Controller;
use App\Mail\SubscriptionInvoiceMail;
use App\Models\PlatformPayment;
use App\Models\Subscription;
use App\Models\SubscriptionPlan;
use Carbon\Carbon;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Mail;
use Barryvdh\DomPDF\Facade\Pdf;

class PlatformPaymentController extends Controller
{
    public function index(Request $request): JsonResponse
    {
        $query = PlatformPayment::with([
            'organization:id,name,email',
            'subscription:id,plan,billing_cycle',
        ]);

        if ($request->filled('search')) {
            $q = $request->input('search');
            $query->where(function ($qb) use ($q) {
                $qb->where('invoice_number', 'like', "%{$q}%")
                   ->orWhere('transaction_id', 'like', "%{$q}%")
                   ->orWhereHas('organization', fn($o) => $o->where('name', 'like', "%{$q}%"));
            });
        }

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

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

        if ($request->filled('date_from')) {
            $query->whereDate('paid_at', '>=', $request->input('date_from'));
        }

        if ($request->filled('date_to')) {
            $query->whereDate('paid_at', '<=', $request->input('date_to'));
        }

        $payments = $query->orderByDesc('created_at')
            ->paginate(min((int) $request->input('per_page', 20), 100));

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

    public function store(Request $request): JsonResponse
    {
        $validated = $request->validate([
            'organization_id' => 'required|exists:organizations,id',
            'subscription_id' => 'nullable|exists:subscriptions,id',
            'amount'          => 'required|numeric|min:0',
            'plan'            => 'nullable|string|max:100',
            'payment_method'  => 'nullable|string|max:100',
            'payment_gateway' => 'nullable|string|max:100',
            'transaction_id'  => 'nullable|string|max:255',
            'status'          => 'required|in:pending,completed,failed,refunded',
            'description'     => 'nullable|string',
            'paid_at'         => 'nullable|date',
        ]);

        $validated['invoice_number'] = $this->generateInvoiceNumber();

        if (empty($validated['paid_at']) && $validated['status'] === 'completed') {
            $validated['paid_at'] = now();
        }

        $payment = PlatformPayment::create($validated);
        $payment->load('organization');

        return response()->json(['message' => 'Payment recorded.', 'data' => $payment], 201);
    }

    public function updateStatus(Request $request, PlatformPayment $payment): JsonResponse
    {
        $validated = $request->validate([
            'status' => 'required|in:pending,completed,failed,refunded',
        ]);

        if ($validated['status'] === 'completed' && !$payment->paid_at) {
            $validated['paid_at'] = now();
        }

        // Auto-activate subscription when a bank-transfer payment is confirmed completed
        if (
            $validated['status'] === 'completed' &&
            $payment->payment_method === 'bank_transfer' &&
            $payment->plan &&
            $payment->organization_id
        ) {
            $plan = SubscriptionPlan::where('name', $payment->plan)->first();

            if ($plan) {
                // Billing cycle is encoded in the description prefix ("Monthly …" / "Yearly …")
                $cycle     = str_starts_with($payment->description ?? '', 'Yearly') ? 'yearly' : 'monthly';
                $now       = now();
                $periodEnd = $cycle === 'yearly' ? $now->copy()->addYear() : $now->copy()->addMonth();

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

                $subscription = Subscription::create([
                    'organization_id'      => $payment->organization_id,
                    'plan'                 => $plan->name,
                    'status'               => 'active',
                    'amount'               => $payment->amount,
                    'billing_cycle'        => $cycle,
                    'current_period_start' => $now,
                    'current_period_end'   => $periodEnd,
                ]);

                $validated['subscription_id'] = $subscription->id;
            }
        }

        $payment->update($validated);
        return response()->json(['message' => 'Status updated.', 'data' => $payment->fresh()]);
    }

    public function downloadInvoice(PlatformPayment $payment)
    {
        $payment->load('organization', 'subscription');

        $pdf = Pdf::loadView('invoices.subscription', [
            'payment' => $payment,
            'org'     => $payment->organization,
        ])->setPaper('a4', 'portrait');

        return $pdf->download("invoice-{$payment->invoice_number}.pdf");
    }

    public function sendInvoice(PlatformPayment $payment): JsonResponse
    {
        $payment->load('organization', 'subscription');
        $org = $payment->organization;

        if (!$org?->email) {
            return response()->json(['message' => 'Organization has no email address on file.'], 422);
        }

        Mail::to($org->email)->send(new SubscriptionInvoiceMail($payment));

        return response()->json([
            'message' => "Invoice {$payment->invoice_number} sent to {$org->email}.",
        ]);
    }

    public function analytics(): JsonResponse
    {
        $now            = Carbon::now();
        $thisMonthStart = $now->copy()->startOfMonth();

        // MRR: monthly-equivalent of all active subscriptions
        $mrr = Subscription::where('status', 'active')
            ->selectRaw("SUM(CASE WHEN billing_cycle='yearly' THEN amount/12 ELSE amount END) as mrr")
            ->value('mrr') ?? 0;

        $arr         = $mrr * 12;
        $activeCount = Subscription::where('status', 'active')->count();
        $arpu        = $activeCount > 0 ? round($mrr / $activeCount, 2) : 0;

        // Churn rate: cancellations this month / (active at month start + cancellations)
        $cancelledThisMonth = Subscription::where('status', 'cancelled')
            ->whereNotNull('cancelled_at')
            ->where('cancelled_at', '>=', $thisMonthStart)
            ->count();

        $activeAtMonthStart = Subscription::where('status', 'active')
            ->where('created_at', '<', $thisMonthStart)
            ->count() + $cancelledThisMonth;

        $churnRate = $activeAtMonthStart > 0
            ? round(($cancelledThisMonth / $activeAtMonthStart) * 100, 2)
            : 0;

        // Monthly revenue from platform_payments (last 12 months)
        $monthlyRevenue = collect(range(11, 0))->map(function ($i) use ($now) {
            $date  = $now->copy()->subMonths($i)->startOfMonth();
            $total = PlatformPayment::where('status', 'completed')
                ->whereYear('paid_at', $date->year)
                ->whereMonth('paid_at', $date->month)
                ->sum('amount');
            return ['month' => $date->format('M Y'), 'revenue' => round((float) $total, 2)];
        });

        // Revenue by plan
        $revenueByPlan = PlatformPayment::where('status', 'completed')
            ->selectRaw('plan, SUM(amount) as total, COUNT(*) as count')
            ->groupBy('plan')
            ->orderByDesc('total')
            ->get();

        // Subscription status breakdown
        $statusBreakdown = Subscription::selectRaw('status, count(*) as count')
            ->groupBy('status')
            ->get()
            ->pluck('count', 'status');

        // Platform payment totals
        $paymentTotals = [
            'completed' => (float) PlatformPayment::where('status', 'completed')->sum('amount'),
            'pending'   => PlatformPayment::where('status', 'pending')->count(),
            'failed'    => PlatformPayment::where('status', 'failed')->count(),
            'refunded'  => (float) PlatformPayment::where('status', 'refunded')->sum('amount'),
        ];

        return response()->json([
            'mrr'              => round((float) $mrr, 2),
            'arr'              => round($arr, 2),
            'arpu'             => $arpu,
            'churn_rate'       => $churnRate,
            'active_count'     => $activeCount,
            'monthly_revenue'  => $monthlyRevenue,
            'revenue_by_plan'  => $revenueByPlan,
            'status_breakdown' => $statusBreakdown,
            'payment_totals'   => $paymentTotals,
        ]);
    }

    private function generateInvoiceNumber(): string
    {
        $year = now()->year;
        $last = PlatformPayment::whereYear('created_at', $year)->count();
        return sprintf('INV-%d-%05d', $year, $last + 1);
    }
}
