<?php

namespace Modules\AiCore\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Modules\AiCore\Entities\AiFeedback;
use Modules\AiCore\Entities\AiProvider;
use Modules\AiCore\Entities\AiUsageLog;

/**
 * AI usage & cost dashboard — aggregates ai_usage_logs for the current business:
 * tokens & calls per feature, per provider/model (so you can see Groq vs the
 * Bynara fallback), a daily trend, the success/failover rate, and recent errors.
 */
class AiUsageController extends Controller
{
    private function biz(): int
    {
        return (int) request()->session()->get('user.business_id');
    }

    private function gate(): void
    {
        $u = auth()->user();
        if (!$u->can('aicore.view_usage') && !$u->can('aicore.manage') && !$u->can('aicore.access_settings')) {
            abort(403, 'Unauthorized action.');
        }
    }

    public function index(Request $request)
    {
        $this->gate();
        $biz  = $this->biz();
        $days = max(1, min(180, (int) $request->input('days', 30)));
        $since = now()->subDays($days - 1)->startOfDay();

        $base = fn () => AiUsageLog::forBusiness($biz)->where('created_at', '>=', $since);

        $totals = $base()->selectRaw(
            'COUNT(*) as calls, '
            . 'COALESCE(SUM(tokens_in),0) as tin, '
            . 'COALESCE(SUM(tokens_out),0) as tout, '
            . 'COALESCE(SUM(ok),0) as ok_calls'
        )->first();

        // A fallback attempt is logged with feature suffixed ":fallback".
        $fallbackCalls = $base()->where('feature', 'like', '%:fallback')->count();

        $byFeature = $base()->selectRaw(
            'module, feature, COUNT(*) as calls, '
            . 'COALESCE(SUM(tokens_in)+SUM(tokens_out),0) as tokens, '
            . 'COALESCE(SUM(ok),0) as ok_calls'
        )->groupBy('module', 'feature')->orderByDesc('tokens')->limit(50)->get();

        $byModel = $base()->selectRaw(
            'provider, model, COUNT(*) as calls, '
            . 'COALESCE(SUM(tokens_in)+SUM(tokens_out),0) as tokens, '
            . 'COALESCE(SUM(ok),0) as ok_calls'
        )->groupBy('provider', 'model')->orderByDesc('tokens')->get();

        $daily = $base()->selectRaw(
            'DATE(created_at) as d, COUNT(*) as calls, '
            . 'COALESCE(SUM(tokens_in)+SUM(tokens_out),0) as tokens'
        )->groupBy('d')->orderBy('d')->get();

        $errors = $base()->where('ok', 0)->orderByDesc('id')->limit(15)->get();

        // Cost guardrail: month-to-date spend vs the business's monthly budget, so
        // the dashboard can warn before calls start getting refused.
        $settings = AiProvider::forBusiness($biz, 'default');
        $budget = [
            'limit'    => (int) ($settings->monthly_token_budget ?? 0),
            'used'     => $settings->monthToDateTokens(),
            'fraction' => $settings->budgetUsedFraction(),   // null when no budget set
            'near'     => $settings->budgetNearLimit(),
            'over'     => $settings->budgetExceeded(),
            'enforced' => (bool) config('aicore.budget_enforce', true),
        ];

        // Audit trail: how many AI suggestions were generated vs applied/accepted.
        $acceptance    = AiFeedback::acceptanceSince($biz, $since);
        $accGenerated  = (int) $acceptance->sum('generated');
        $accApplied    = (int) $acceptance->sum('accepted');
        $acceptancePct = $accGenerated ? round($accApplied / $accGenerated * 100) : null;

        return view('aiCore::usage.index', compact(
            'totals', 'fallbackCalls', 'byFeature', 'byModel', 'daily', 'errors', 'days', 'budget',
            'acceptance', 'accGenerated', 'accApplied', 'acceptancePct'
        ));
    }
}
