<?php

declare(strict_types=1);

namespace ImovelZapAi\SuperAdmin\Infrastructure\Http\Controllers\Web;

use Illuminate\Contracts\View\View;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use ImovelZapAi\Organizations\Infrastructure\Persistence\Eloquent\OrganizationSubscriptionModel;
use ImovelZapAi\Organizations\Infrastructure\Persistence\Eloquent\SubscriptionPlanModel;
use ImovelZapAi\SuperAdmin\Application\Actions\PlatformChangeTenantPlanAction;
use ImovelZapAi\SuperAdmin\Application\Actions\PlatformChangeTenantStatusAction;
use ImovelZapAi\SuperAdmin\Application\Actions\PlatformCreateTenantAction;
use ImovelZapAi\Tenancy\Domain\Enums\TenantStatus;
use ImovelZapAi\Tenancy\Infrastructure\Persistence\Eloquent\TenantModel;
use ImovelZapAi\Users\Infrastructure\Persistence\Eloquent\UserModel;
use RuntimeException;
use Throwable;

final class PlatformTenantController
{
    public function index(Request $request): View
    {
        $q = trim((string) $request->query('q', ''));
        $query = TenantModel::query()->orderBy('name');
        if ($q !== '') {
            $query->where(function ($builder) use ($q): void {
                $builder->where('name', 'ilike', "%{$q}%")
                    ->orWhere('slug', 'ilike', "%{$q}%");
            });
        }

        return view('super-admin.tenants.index', [
            'tenants' => $query->paginate(30)->withQueryString(),
            'q' => $q,
        ]);
    }

    public function create(): View
    {
        return view('super-admin.tenants.create');
    }

    public function store(Request $request, PlatformCreateTenantAction $action): RedirectResponse
    {
        $data = $request->validate([
            'name' => ['required', 'string', 'max:160'],
            'slug' => ['required', 'string', 'max:80'],
            'status' => ['nullable', 'string'],
        ]);

        $status = TenantStatus::tryFrom((string) ($data['status'] ?? TenantStatus::Trial->value))
            ?? TenantStatus::Trial;

        try {
            $tenant = $action->execute($data['name'], $data['slug'], $status);
        } catch (Throwable $e) {
            return back()->withErrors(['name' => $e->getMessage()])->withInput();
        }

        return redirect()
            ->route('super-admin.tenants.show', $tenant->id)
            ->with('status', 'Cliente criado.');
    }

    public function show(string $tenant): View
    {
        $model = TenantModel::query()->findOrFail($tenant);
        $subscription = OrganizationSubscriptionModel::query()
            ->with('plan')
            ->where('tenant_id', $model->id)
            ->latest()
            ->first();
        $users = UserModel::query()->where('tenant_id', $model->id)->orderBy('name')->limit(50)->get();
        $plans = SubscriptionPlanModel::query()->where('is_active', true)->orderBy('sort_order')->get();

        return view('super-admin.tenants.show', [
            'tenant' => $model,
            'subscription' => $subscription,
            'users' => $users,
            'plans' => $plans,
            'statuses' => TenantStatus::cases(),
        ]);
    }

    public function updateStatus(
        Request $request,
        string $tenant,
        PlatformChangeTenantStatusAction $action,
    ): RedirectResponse {
        $data = $request->validate([
            'status' => ['required', 'string'],
        ]);
        $status = TenantStatus::tryFrom($data['status']);
        if ($status === null) {
            return back()->withErrors(['status' => 'Status inválido.']);
        }

        try {
            $action->execute($tenant, $status);
        } catch (RuntimeException $e) {
            return back()->withErrors(['status' => $e->getMessage()]);
        }

        return back()->with('status', 'Status do cliente atualizado.');
    }

    public function updatePlan(
        Request $request,
        string $tenant,
        PlatformChangeTenantPlanAction $action,
    ): RedirectResponse {
        $data = $request->validate([
            'plan_code' => ['required', 'string'],
        ]);

        try {
            $action->execute($tenant, $data['plan_code']);
        } catch (Throwable $e) {
            return back()->withErrors(['plan_code' => $e->getMessage()]);
        }

        return back()->with('status', 'Plano do cliente atualizado.');
    }
}
