<?php

declare(strict_types=1);

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\PricingTier;
use App\Models\SaasAdminAuditLog;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\DB;

/**
 * SaaS-admin CRUD для pricing_tiers (7-ступенчатый тариф).
 *
 * Spec: docs/superpowers/specs/2026-05-11-plan4-billing-csv-admin-design.md §6.1.
 * Без auth-middleware на MVP (паритет с другими /api/admin/*; gated на Б-1).
 * Audit trail в saas_admin_audit_log (action='pricing_tiers.create_scheduled' /
 * 'pricing_tiers.delete_scheduled').
 *
 * Конструкция audit-log:
 *   - schema.saas_admin_audit_log требует NOT NULL admin_user_id и ip_address;
 *     на MVP admin_user_id берётся из request param (как в
 *     AdminSystemSettingsController), либо создаётся системный стаб
 *     `system-pricing@liderra.local`. ip_address — $request->ip() или '127.0.0.1'.
 *   - payload_after хранит {effective_from, tiers} для воспроизводимости.
 */
final class AdminPricingTiersController extends Controller
{
    /** GET /api/admin/pricing-tiers */
    public function index(): JsonResponse
    {
        $today = Carbon::now('Europe/Moscow')->toDateString();

        $active = PricingTier::query()->where('is_active', true)
            ->where('effective_from', '<=', $today)
            ->orderBy('tier_no')->orderBy('effective_from', 'desc')
            ->get()
            ->groupBy('tier_no')
            ->map(fn ($g) => $g->first())
            ->values();

        $scheduled = PricingTier::query()->where('is_active', true)
            ->where('effective_from', '>', $today)
            ->orderBy('effective_from')->orderBy('tier_no')
            ->get()
            ->groupBy(fn (PricingTier $t) => $t->effective_from->toDateString());

        return response()->json([
            'data' => [
                'active' => $active,
                'scheduled' => $scheduled,
            ],
        ]);
    }

    /** POST /api/admin/pricing-tiers */
    public function store(Request $request): JsonResponse
    {
        $todayMsk = Carbon::now('Europe/Moscow')->toDateString();

        $request->validate([
            'tiers' => ['required', 'array', 'size:7'],
            'tiers.*.tier_no' => ['required', 'integer', 'between:1,7'],
            'tiers.*.leads_in_tier' => ['nullable', 'integer', 'min:1'],
            'tiers.*.price_rub' => ['required', 'string', 'regex:/^\d+(\.\d{1,2})?$/'],
            'effective_from' => ['sometimes', 'date_format:Y-m-d', 'after_or_equal:'.$todayMsk],
        ]);

        /** @var array<int, array{tier_no:int, leads_in_tier:?int, price_rub:string|float}> $tiers */
        $tiers = $request->input('tiers');

        $tierNos = array_column($tiers, 'tier_no');
        if (count(array_unique($tierNos)) !== 7) {
            abort(422, 'tier_no must be unique 1..7');
        }
        if (array_diff([1, 2, 3, 4, 5, 6, 7], $tierNos) !== []) {
            abort(422, 'all 7 tier_no values required');
        }

        $tier7 = collect($tiers)->firstWhere('tier_no', 7);
        if ($tier7['leads_in_tier'] !== null) {
            abort(422, 'tier_no=7 leads_in_tier must be null');
        }

        foreach ($tiers as $tier) {
            if ($tier['tier_no'] !== 7 && ($tier['leads_in_tier'] === null || $tier['leads_in_tier'] < 1)) {
                abort(422, "tier_no={$tier['tier_no']} leads_in_tier must be >= 1");
            }
        }

        $effectiveFrom = $request->input('effective_from')
            ?? Carbon::now('Europe/Moscow')->startOfMonth()->addMonth()->toDateString();
        $adminUserId = $this->resolveAdminUserId($request);

        DB::transaction(function () use ($tiers, $effectiveFrom, $adminUserId, $request): void {
            foreach ($tiers as $tier) {
                PricingTier::create([
                    'tier_no' => $tier['tier_no'],
                    'leads_in_tier' => $tier['leads_in_tier'],
                    'price_per_lead_kopecks' => (int) bcmul((string) $tier['price_rub'], '100', 0),
                    'is_active' => true,
                    'effective_from' => $effectiveFrom,
                ]);
            }

            SaasAdminAuditLog::create([
                'admin_user_id' => $adminUserId,
                'action' => 'pricing_tiers.create_scheduled',
                'target_type' => 'pricing_tiers',
                'target_id' => null,
                'payload_before' => null,
                'payload_after' => ['effective_from' => $effectiveFrom, 'tiers' => $tiers],
                'reason' => 'Scheduled pricing-tier update via admin UI.',
                'ip_address' => $request->ip() ?? '127.0.0.1',
                'user_agent' => $request->userAgent(),
            ]);
        });

        return response()->json(['effective_from' => $effectiveFrom], Response::HTTP_CREATED);
    }

    /** DELETE /api/admin/pricing-tiers/scheduled/{effective_from} */
    public function deleteScheduled(Request $request, string $effectiveFrom): JsonResponse
    {
        if (! preg_match('/^\d{4}-\d{2}-\d{2}$/', $effectiveFrom)) {
            abort(400, 'invalid date format');
        }

        $todayMsk = Carbon::now('Europe/Moscow')->toDateString();
        if ($effectiveFrom <= $todayMsk) {
            abort(409, 'cannot delete past or active set');
        }

        $adminUserId = $this->resolveAdminUserId($request);

        DB::transaction(function () use ($effectiveFrom, $adminUserId, $request): void {
            $deleted = PricingTier::where('effective_from', $effectiveFrom)->delete();

            SaasAdminAuditLog::create([
                'admin_user_id' => $adminUserId,
                'action' => 'pricing_tiers.delete_scheduled',
                'target_type' => 'pricing_tiers',
                'target_id' => null,
                'payload_before' => ['effective_from' => $effectiveFrom],
                'payload_after' => ['rows_deleted' => $deleted],
                'reason' => 'Cancelled scheduled pricing-tier set via admin UI.',
                'ip_address' => $request->ip() ?? '127.0.0.1',
                'user_agent' => $request->userAgent(),
            ]);
        });

        return response()->json(['ok' => true]);
    }

    /**
     * Резолвит admin_user_id: из request input (на MVP) либо создаёт
     * системный стаб-аккаунт `system-pricing@liderra.local`, чтобы соблюсти
     * NOT NULL constraint + FK на saas_admin_users.
     */
    private function resolveAdminUserId(Request $request): int
    {
        // Прод: crm_app_user не имеет прав на saas_admin_users → берём системный
        // admin-id из конфига, не обращаясь к таблице. null (dev/test) → fallback ниже.
        $configured = config('admin.audit_system_user_id');
        if ($configured !== null) {
            return (int) $configured;
        }

        $requested = $request->input('admin_user_id');
        if (is_int($requested) || (is_string($requested) && ctype_digit($requested))) {
            $existing = DB::table('saas_admin_users')->where('id', (int) $requested)->value('id');
            if ($existing !== null) {
                return (int) $existing;
            }
        }

        $existingId = DB::table('saas_admin_users')
            ->where('email', 'system-pricing@liderra.local')
            ->value('id');
        if ($existingId !== null) {
            return (int) $existingId;
        }

        return (int) DB::table('saas_admin_users')->insertGetId([
            'email' => 'system-pricing@liderra.local',
            'full_name' => 'System Pricing Bot',
            'password_hash' => '$2y$04$system-stub-not-loginable',
            'role' => 'super_admin',
            'is_active' => false,
            'sso_provider' => 'local',
            'is_break_glass' => false,
        ]);
    }
}
