<?php

namespace App\Modules\Accounting\Controllers;

use App\Http\Controllers\Controller;
use App\Http\Responses\ApiResponse;
use App\Modules\Accounting\Models\ExpenseCategory;
use App\Modules\Accounting\Requests\StoreExpenseCategoryRequest;
use App\Modules\Accounting\Requests\UpdateExpenseCategoryRequest;
use App\Modules\Accounting\Resources\ExpenseCategoryResource;
use App\Modules\Tenant\Models\Company;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Str;

class ExpenseCategoryController extends Controller
{
    public function index(Request $request): JsonResponse
    {
        $company = $this->currentCompany($request);

        $categories = ExpenseCategory::query()
            ->where('company_id', $company->id)
            ->when($request->filled('status'), function ($query) use ($request): void {
                $query->where('status', $request->string('status')->toString());
            })
            ->orderBy('name')
            ->get();

        return ApiResponse::success(ExpenseCategoryResource::collection($categories));
    }

    public function store(StoreExpenseCategoryRequest $request): JsonResponse
    {
        $company = $this->currentCompany($request);
        $data = $request->validated();

        $category = ExpenseCategory::query()->create([
            'company_id' => $company->id,
            'name' => $data['name'],
            'slug' => $this->uniqueSlug($company, $data['name']),
            'status' => $data['status'] ?? 'active',
        ]);

        return ApiResponse::success(
            new ExpenseCategoryResource($category),
            'Expense category created successfully',
            201
        );
    }

    public function update(UpdateExpenseCategoryRequest $request, ExpenseCategory $expenseCategory): JsonResponse
    {
        $company = $this->currentCompany($request);

        if ((int) $expenseCategory->company_id !== (int) $company->id) {
            return ApiResponse::error('Expense category not found', 404);
        }

        $data = $request->validated();

        if (array_key_exists('name', $data) && $data['name'] !== $expenseCategory->name) {
            $data['slug'] = $this->uniqueSlug($company, $data['name'], $expenseCategory->id);
        }

        $expenseCategory->update($data);

        return ApiResponse::success(
            new ExpenseCategoryResource($expenseCategory->fresh()),
            'Expense category updated successfully'
        );
    }

    private function uniqueSlug(Company $company, string $name, ?int $ignoreCategoryId = null): string
    {
        $baseSlug = Str::slug($name) ?: 'category';
        $slug = $baseSlug;
        $counter = 2;

        while (
            ExpenseCategory::query()
                ->where('company_id', $company->id)
                ->where('slug', $slug)
                ->when($ignoreCategoryId, function ($query) use ($ignoreCategoryId): void {
                    $query->whereKeyNot($ignoreCategoryId);
                })
                ->exists()
        ) {
            $slug = "{$baseSlug}-{$counter}";
            $counter++;
        }

        return $slug;
    }

    private function currentCompany(Request $request): Company
    {
        return $request->attributes->get('currentCompany');
    }
}
