<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Http\Requests\Admin\PreviewCustomReportRequest;
use App\Http\Requests\Admin\StoreCustomReportRequest;
use App\Http\Requests\Admin\UpdateCustomReportRequest;
use App\Models\CustomReport;
use App\Services\Reports\CsvExporter;
use App\Services\Reports\Exceptions\InvalidIrException;
use App\Services\Reports\ReportCompiler;
use App\Services\Reports\ReportExecutor;
use App\Services\Reports\SchemaIntrospector;
use App\Traits\LogsAdminActivity;
use Illuminate\Support\Facades\Auth;

class CustomReportController extends Controller
{
    use LogsAdminActivity;

    public function __construct(
        protected SchemaIntrospector $schema,
        protected ReportCompiler $compiler,
        protected ReportExecutor $executor,
        protected CsvExporter $exporter,
    ) {}

    public function index()
    {
        $this->authorize('viewAny', CustomReport::class);
        return view('admin.reports.custom.index');
    }

    public function create()
    {
        $this->authorize('create', CustomReport::class);
        return view('admin.reports.custom.builder', [
            'report' => null,
            'mode' => 'create',
        ]);
    }

    public function store(StoreCustomReportRequest $request)
    {
        $data = $request->validated();
        $data['owner_admin_id'] = Auth::guard('admin')->id();

        try {
            $this->compiler->compile($data['ir']);
        } catch (InvalidIrException $e) {
            return back()->withInput()->withErrors(['ir' => $e->getMessage()]);
        }

        $report = CustomReport::create($data);
        $this->logCreated(model: $report, description: "Created custom report #{$report->id} - {$report->name}");

        return redirect()->route('admin.reports.custom.show', $report)
            ->with('success', __('admin/reports.custom_report_created'));
    }

    public function show(CustomReport $report)
    {
        $this->authorize('view', $report);
        return view('admin.reports.custom.show', compact('report'));
    }

    public function edit(CustomReport $report)
    {
        $this->authorize('update', $report);
        return view('admin.reports.custom.builder', [
            'report' => $report,
            'mode' => 'edit',
        ]);
    }

    public function update(UpdateCustomReportRequest $request, CustomReport $report)
    {
        $this->authorize('update', $report);

        $data = $request->validated();

        try {
            $this->compiler->compile($data['ir']);
        } catch (InvalidIrException $e) {
            return back()->withInput()->withErrors(['ir' => $e->getMessage()]);
        }

        $report->update($data);
        $this->logUpdated(model: $report, description: "Updated custom report #{$report->id}");

        return redirect()->route('admin.reports.custom.show', $report)
            ->with('success', __('admin/reports.custom_report_updated'));
    }

    public function destroy(CustomReport $report)
    {
        $this->authorize('delete', $report);

        $this->logDeleted(model: $report, description: "Deleted custom report #{$report->id}");
        $report->delete();

        return redirect()->route('admin.reports.custom.index')
            ->with('success', __('admin/reports.custom_report_deleted'));
    }

    public function togglePublic(CustomReport $report)
    {
        $this->authorize('togglePublic', $report);

        $report->update(['is_public' => ! $report->is_public]);
        $this->logUpdated(model: $report, description: "Toggled public on report #{$report->id} to " . ($report->is_public ? 'public' : 'private'));

        return back()->with('success', __('admin/reports.public_toggled'));
    }

    public function preview(PreviewCustomReportRequest $request)
    {
        try {
            $rows = $this->executor->preview($request->input('ir'));
            return response()->json([
                'success' => true,
                'rows' => $rows,
                'count' => count($rows),
            ]);
        } catch (InvalidIrException $e) {
            return response()->json([
                'success' => false,
                'error' => $e->getMessage(),
            ], 422);
        } catch (\Throwable $e) {
            return response()->json([
                'success' => false,
                'error' => 'Query failed: ' . $e->getMessage(),
            ], 500);
        }
    }

    public function export(CustomReport $report)
    {
        $this->authorize('view', $report);
        if (! request()->user('admin')?->can('export custom reports')) {
            abort(403);
        }
        return $this->exporter->streamResponse($report);
    }
}
