<?php

declare(strict_types=1);

namespace ImovelZapAi\Analytics\Presentation\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
use ImovelZapAi\Analytics\Application\Actions\AcknowledgeAnalyticsAlertAction;
use ImovelZapAi\Analytics\Application\Actions\ExportAnalyticsReportAction;
use ImovelZapAi\Analytics\Application\Actions\GetOrCreateDashboardLayoutAction;
use ImovelZapAi\Analytics\Application\Actions\UpdateDashboardLayoutAction;
use ImovelZapAi\Analytics\Application\Queries\GetAnalyticsDashboardQuery;
use ImovelZapAi\Analytics\Application\Queries\GetExecutiveKpisQuery;
use ImovelZapAi\Analytics\Application\Queries\GetFunnelQuery;
use ImovelZapAi\Analytics\Application\Queries\GetRankingQuery;
use ImovelZapAi\Analytics\Application\Queries\ListAnalyticsAlertsQuery;
use ImovelZapAi\Analytics\Domain\Enums\DashboardRole;
use ImovelZapAi\Analytics\Domain\Exceptions\AnalyticsException;
use ImovelZapAi\Authentication\Domain\Enums\SystemRole;
use ImovelZapAi\Tenancy\Support\TenantContext;

final class AnalyticsController extends Controller
{
    public function kpis(GetExecutiveKpisQuery $query, Request $request): JsonResponse
    {
        return response()->json($query->execute((string) TenantContext::id(), $this->filters($request)));
    }

    public function funnel(GetFunnelQuery $query, Request $request): JsonResponse
    {
        return response()->json($query->execute((string) TenantContext::id(), $this->filters($request)));
    }

    public function rankings(GetRankingQuery $query, Request $request): JsonResponse
    {
        return response()->json($query->execute((string) TenantContext::id(), $this->filters($request)));
    }

    public function dashboard(GetAnalyticsDashboardQuery $query, Request $request): JsonResponse
    {
        $user = $request->user();

        return response()->json(
            $query->execute((string) TenantContext::id(), $user, $this->resolveRole($user), $this->filters($request)),
        );
    }

    public function alerts(ListAnalyticsAlertsQuery $query, Request $request): JsonResponse
    {
        $result = $query->execute((string) TenantContext::id(), [
            'per_page' => (int) $request->query('per_page', 20),
            'status' => $request->query('status'),
        ]);

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

    public function ackAlert(string $alertId, AcknowledgeAnalyticsAlertAction $action): JsonResponse
    {
        try {
            $alert = $action->execute((string) TenantContext::id(), $alertId);
        } catch (AnalyticsException $e) {
            return response()->json(['message' => $e->getMessage()], 404);
        }

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

    public function widgets(GetOrCreateDashboardLayoutAction $layout, Request $request): JsonResponse
    {
        $user = $request->user();

        return response()->json(
            $layout->execute((string) TenantContext::id(), $user, $this->resolveRole($user)),
        );
    }

    public function updateWidgets(Request $request, UpdateDashboardLayoutAction $action): JsonResponse
    {
        $data = $request->validate([
            'widgets' => ['required', 'array'],
            'widgets.*.type' => ['required', 'string'],
            'widgets.*.title' => ['required', 'string', 'max:120'],
            'widgets.*.config' => ['nullable', 'array'],
        ]);

        try {
            $layout = $action->execute((string) TenantContext::id(), $request->user(), $data['widgets']);
        } catch (AnalyticsException $e) {
            return response()->json(['message' => $e->getMessage()], 403);
        }

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

    public function export(ExportAnalyticsReportAction $export, Request $request): JsonResponse
    {
        $format = (string) $request->query('format', 'csv');

        try {
            $result = $export->execute((string) TenantContext::id(), $format, $this->filters($request));
        } catch (AnalyticsException $e) {
            return response()->json(['message' => $e->getMessage()], 422);
        }

        return response()->json([
            'disk' => $result['disk'],
            'path' => $result['path'],
            'filename' => $result['filename'],
            'download_url' => Storage::disk($result['disk'])->url($result['path']),
        ]);
    }

    private function resolveRole(User $user): DashboardRole
    {
        if ($user->hasRole(SystemRole::Admin->value)) {
            return DashboardRole::Owner;
        }
        if ($user->hasRole(SystemRole::Gestor->value)) {
            return DashboardRole::Manager;
        }

        return DashboardRole::Broker;
    }

    /** @return array{days?: int, from?: string, to?: string} */
    private function filters(Request $request): array
    {
        $filters = [];

        if ($request->filled('from')) {
            $filters['from'] = (string) $request->query('from');
        }
        if ($request->filled('to')) {
            $filters['to'] = (string) $request->query('to');
        }
        $filters['days'] = (int) $request->query('days', config('analytics.default_period_days', 30));

        return $filters;
    }
}
