<?php

declare(strict_types=1);

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use Carbon\CarbonImmutable;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\DB;

/**
 * SaaS-admin billing-overview для AdminBillingView. Aggregates пополнения и
 * списания за текущий календарный месяц по `balance_transactions`.
 *
 * На MVP без auth-middleware (saas-admin SSO ⏸ Б-1).
 */
class AdminBillingController extends Controller
{
    /** GET /api/admin/billing?search= */
    public function index(Request $request): JsonResponse
    {
        $search = trim((string) $request->query('search', ''));
        $monthStart = now()->startOfMonth();

        $query = DB::table('tenants')
            ->leftJoin('tariff_plans', 'tariff_plans.id', '=', 'tenants.current_tariff_id')
            ->whereNull('tenants.deleted_at');

        if ($search !== '') {
            $like = '%'.$search.'%';
            $query->where(function ($q) use ($like) {
                $q->where('tenants.organization_name', 'ilike', $like)
                    ->orWhere('tenants.subdomain', 'ilike', $like);
            });
        }

        $tenants = $query->select([
            'tenants.id',
            'tenants.subdomain',
            'tenants.organization_name',
            'tenants.contact_email',
            'tenants.status',
            'tenants.balance_rub',
            'tenants.is_trial',
            'tenants.chargeback_unrecovered_rub',
            'tariff_plans.id as tariff_id',
            'tariff_plans.name as tariff_name',
            'tariff_plans.price_monthly as tariff_price_monthly',
        ])->get();

        $tenantIds = $tenants->pluck('id')->all();

        // Aggregate balance_transactions за текущий месяц по типам.
        $aggregates = [];
        if ($tenantIds !== []) {
            $rows = DB::table('balance_transactions')
                ->whereIn('tenant_id', $tenantIds)
                ->where('created_at', '>=', $monthStart)
                ->selectRaw('
                    tenant_id,
                    SUM(CASE WHEN type = ? THEN amount_rub ELSE 0 END) as topups,
                    SUM(CASE WHEN type = ? THEN ABS(amount_rub) ELSE 0 END) as charges,
                    MAX(CASE WHEN type = ? THEN created_at ELSE NULL END) as last_payment_at
                ', ['topup', 'lead_charge', 'topup'])
                ->groupBy('tenant_id')
                ->get();

            foreach ($rows as $r) {
                $aggregates[(int) $r->tenant_id] = [
                    'topups' => (string) $r->topups,
                    'charges' => (string) $r->charges,
                    'last_payment_at' => $r->last_payment_at,
                ];
            }
        }

        $rows = $tenants->map(function ($t) use ($aggregates) {
            $agg = $aggregates[(int) $t->id] ?? [
                'topups' => '0.00',
                'charges' => '0.00',
                'last_payment_at' => null,
            ];

            return [
                'id' => (int) $t->id,
                'subdomain' => $t->subdomain,
                'organization_name' => $t->organization_name,
                'contact_email' => $t->contact_email,
                'status' => $t->status,
                'balance_rub' => (string) $t->balance_rub,
                'tariff_id' => $t->tariff_id !== null ? (int) $t->tariff_id : null,
                'tariff_name' => $t->tariff_name,
                'mrr_rub' => $t->tariff_price_monthly !== null && ! $t->is_trial
                    ? (string) $t->tariff_price_monthly
                    : '0.00',
                'monthly_topups_rub' => $agg['topups'],
                'monthly_charges_rub' => $agg['charges'],
                'last_payment_at' => $agg['last_payment_at'] !== null
                    ? CarbonImmutable::parse($agg['last_payment_at'])->toIso8601String()
                    : null,
                'chargeback_unrecovered_rub' => (string) $t->chargeback_unrecovered_rub,
            ];
        });

        return response()->json([
            'tenants' => $rows,
            'summary' => $this->computeSummary($monthStart),
        ]);
    }

    /**
     * Общая выручка за месяц + кол-во просрочек + возвраты за 30 дн.
     *
     * @return array<string, int|string>
     */
    private function computeSummary(Carbon $monthStart): array
    {
        $thirtyDaysAgo = now()->subDays(30);

        // Total MRR — сумма tariff_price_monthly для не-trial тенантов с активным тарифом.
        $totalMrr = DB::table('tenants')
            ->leftJoin('tariff_plans', 'tariff_plans.id', '=', 'tenants.current_tariff_id')
            ->whereNull('tenants.deleted_at')
            ->where('tenants.is_trial', false)
            ->whereNotNull('tariff_plans.price_monthly')
            ->sum('tariff_plans.price_monthly');

        // Monthly revenue = сумма всех topups за текущий месяц.
        $monthlyRevenue = DB::table('balance_transactions')
            ->where('type', 'topup')
            ->where('created_at', '>=', $monthStart)
            ->sum('amount_rub');

        // Overdue tenants (balance<0 OR chargeback>0).
        $overdueCount = DB::table('tenants')
            ->whereNull('deleted_at')
            ->where(function ($q) {
                $q->where('balance_rub', '<', 0)
                    ->orWhere('chargeback_unrecovered_rub', '>', 0);
            })
            ->count();

        // Refunds за 30 дн — count balance_transactions type='refund'.
        $refundsCount = DB::table('balance_transactions')
            ->where('type', 'refund')
            ->where('created_at', '>=', $thirtyDaysAgo)
            ->count();

        return [
            'total_mrr_rub' => (string) $totalMrr,
            'monthly_revenue_rub' => (string) $monthlyRevenue,
            'overdue_count' => $overdueCount,
            'refunds_count_30d' => $refundsCount,
        ];
    }
}
