<?php

namespace Database\Factories;

use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;
use ImovelZapAi\Properties\Domain\Enums\PropertyPurpose;
use ImovelZapAi\Properties\Domain\Enums\PropertyStatus;
use ImovelZapAi\Properties\Domain\Enums\PropertyType;
use ImovelZapAi\Properties\Infrastructure\Persistence\Eloquent\CityModel;
use ImovelZapAi\Properties\Infrastructure\Persistence\Eloquent\NeighborhoodModel;
use ImovelZapAi\Properties\Infrastructure\Persistence\Eloquent\PropertyModel;
use ImovelZapAi\Properties\Infrastructure\Persistence\Eloquent\StateModel;
use ImovelZapAi\Tenancy\Infrastructure\Persistence\Eloquent\TenantModel;

/**
 * @extends Factory<PropertyModel>
 */
class PropertyFactory extends Factory
{
    protected $model = PropertyModel::class;

    /**
     * @return array<string, mixed>
     */
    public function definition(): array
    {
        return [
            'tenant_id' => TenantModel::factory(),
            'created_by' => User::factory(),
            'internal_code' => 'IMV-'.strtoupper(Str::random(8)),
            'title' => fake()->sentence(4),
            'short_description' => fake()->sentence(8),
            'full_description' => fake()->paragraph(),
            'price' => fake()->randomFloat(2, 150000, 2500000),
            'condominium_fee' => fake()->optional()->randomFloat(2, 200, 2000),
            'iptu' => fake()->optional()->randomFloat(2, 100, 5000),
            'bedrooms' => fake()->numberBetween(1, 5),
            'suites' => fake()->numberBetween(0, 3),
            'bathrooms' => fake()->numberBetween(1, 4),
            'parking_spaces' => fake()->numberBetween(0, 3),
            'useful_area' => fake()->optional()->randomFloat(2, 40, 300),
            'total_area' => fake()->optional()->randomFloat(2, 50, 500),
            'type' => fake()->randomElement(PropertyType::cases()),
            'purpose' => fake()->randomElement(PropertyPurpose::cases()),
            'status' => PropertyStatus::Available,
            'cep' => sprintf('%05d-%03d', fake()->numberBetween(0, 99999), fake()->numberBetween(0, 999)),
            'street' => fake()->streetName(),
            'number' => (string) fake()->buildingNumber(),
            'complement' => null,
            'latitude' => fake()->optional()->latitude(),
            'longitude' => fake()->optional()->longitude(),
        ];
    }

    public function configure(): static
    {
        return $this->afterMaking(function (PropertyModel $property): void {
            if ($property->state_id !== null) {
                return;
            }

            do {
                $code = strtoupper(Str::random(2));
            } while (StateModel::query()->where('code', $code)->exists());

            $state = StateModel::query()->create([
                'code' => $code,
                'name' => fake()->state(),
            ]);

            $city = CityModel::query()->create([
                'state_id' => $state->id,
                'name' => fake()->city(),
            ]);

            $neighborhood = NeighborhoodModel::query()->create([
                'city_id' => $city->id,
                'name' => fake()->streetName(),
            ]);

            $property->state_id = $state->id;
            $property->city_id = $city->id;
            $property->neighborhood_id = $neighborhood->id;
        });
    }
}
