<?php

namespace Database\Seeders;

use App\Enums\ApprovalStatusEnum;
use App\Enums\UserTypeEnum;
use App\Enums\WorkingPeriodEnum;
use App\Models\Address;
use App\Models\City;
use App\Models\Provider;
use App\Models\ProviderServicesType;
use App\Models\ProviderSpeciality;
use App\Models\ProviderWorkingDay;
use App\Models\ServiceType;
use App\Models\Speciality;
use App\Models\State;
use App\Models\User;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;

class ProviderSeeder extends Seeder
{
    public function run(): void
    {
        $providers = [
            [
                'user' => [
                    'name'                  => 'Prestador Teste',
                    'email'                 => 'prestador.teste@softpar.inf.br',
                    'phone'                 => '11990000001',
                    'code'                  => '100001',
                    'password'              => 'S@ft2080.',
                    'type'                  => UserTypeEnum::PROVIDER,
                    'email_verified_at'     => now(),
                    'validated_code'        => true,
                    'registration_complete' => true,
                ],

                'provider' => [
                    'document'          => '52998224725',
                    'rg'                => '12.345.678-9',
                    'birth_date'        => '1988-03-12',
                    'average_rating'    => 4.9,
                    'total_services'    => 128,
                    'selfie_verified'   => true,
                    'document_verified' => true,
                    'approval_status'   => ApprovalStatusEnum::ACCEPTED,
                    'daily_price_8h'    => 180.00,
                    'daily_price_6h'    => 140.00,
                    'daily_price_4h'    => 110.00,
                    'daily_price_2h'    => 80.00,
                ],

                'address' => [
                    'zip_code'     => '01001000',
                    'address'      => 'Praça da Sé',
                    'number'       => '100',
                    'district'     => 'Sé',
                    'complement'   => 'Sala 12',
                    'nickname'     => 'Base Centro',
                    'instructions' => 'Atendimento pela portaria principal.',
                    'state_code'   => 'SP',
                    'city_name'    => 'São Paulo',
                    'address_type' => 'home',
                    'is_primary'   => true,
                    'latitude'     => -23.550520,
                    'longitude'    => -46.633308,
                ],

                'service_types' => [
                    'Limpeza residencial',
                    'Passadoria',
                    'Organização de ambientes',
                ],

                'specialities' => [
                    'Casa',
                    'Apartamento',
                    'Banheiro',
                ],

                'working_days' => [
                    ['day' => 1, 'period' => WorkingPeriodEnum::MORNING->value],
                    ['day' => 2, 'period' => WorkingPeriodEnum::MORNING->value],
                    ['day' => 3, 'period' => WorkingPeriodEnum::MORNING->value],
                    ['day' => 4, 'period' => WorkingPeriodEnum::MORNING->value],
                    ['day' => 5, 'period' => WorkingPeriodEnum::MORNING->value],
                ],
            ],

            [
                'user' => [
                    'name'                  => 'Mariana Souza',
                    'email'                 => 'mariana.souza@softpar.inf.br',
                    'phone'                 => '11990000002',
                    'code'                  => '100002',
                    'password'              => 'S@ft2080.',
                    'type'                  => UserTypeEnum::PROVIDER,
                    'email_verified_at'     => now(),
                    'validated_code'        => true,
                    'registration_complete' => true,
                ],

                'provider' => [
                    'document'          => '11144477735',
                    'rg'                => '21.456.789-0',
                    'birth_date'        => '1991-07-24',
                    'average_rating'    => 4.7,
                    'total_services'    => 96,
                    'selfie_verified'   => true,
                    'document_verified' => true,
                    'approval_status'   => ApprovalStatusEnum::ACCEPTED,
                    'daily_price_8h'    => 210.00,
                    'daily_price_6h'    => 160.00,
                    'daily_price_4h'    => 120.00,
                    'daily_price_2h'    => 90.00,
                ],

                'address' => [
                    'zip_code'     => '20040002',
                    'address'      => 'Avenida Rio Branco',
                    'number'       => '120',
                    'district'     => 'Centro',
                    'complement'   => '8 andar',
                    'nickname'     => 'Base Centro RJ',
                    'instructions' => 'Recepção no térreo.',
                    'state_code'   => 'RJ',
                    'city_name'    => 'Rio de Janeiro',
                    'address_type' => 'home',
                    'is_primary'   => true,
                    'latitude'     => -22.906847,
                    'longitude'    => -43.172896,
                ],

                'service_types' => [
                    'Limpeza comercial',
                    'Limpeza pós-obra',
                ],

                'specialities' => [
                    'Escritório',
                    'Vidros',
                    'Faxina pesada',
                ],

                'working_days' => [
                    ['day' => 1, 'period' => WorkingPeriodEnum::MORNING->value],
                    ['day' => 2, 'period' => WorkingPeriodEnum::MORNING->value],
                    ['day' => 3, 'period' => WorkingPeriodEnum::MORNING->value],
                    ['day' => 4, 'period' => WorkingPeriodEnum::MORNING->value],
                    ['day' => 5, 'period' => WorkingPeriodEnum::MORNING->value],
                    ['day' => 6, 'period' => WorkingPeriodEnum::MORNING->value],
                ],
            ],

            [
                'user' => [
                    'name'                  => 'Ana Costa',
                    'email'                 => 'ana.costa@softpar.inf.br',
                    'phone'                 => '11990000003',
                    'code'                  => '100003',
                    'password'              => 'S@ft2080.',
                    'type'                  => UserTypeEnum::PROVIDER,
                    'email_verified_at'     => now(),
                    'validated_code'        => true,
                    'registration_complete' => true,
                ],

                'provider' => [
                    'document'          => '16899535009',
                    'rg'                => '32.987.654-1',
                    'birth_date'        => '1987-11-03',
                    'average_rating'    => 4.8,
                    'total_services'    => 142,
                    'selfie_verified'   => true,
                    'document_verified' => true,
                    'approval_status'   => ApprovalStatusEnum::ACCEPTED,
                    'daily_price_8h'    => 170.00,
                    'daily_price_6h'    => 130.00,
                    'daily_price_4h'    => 100.00,
                    'daily_price_2h'    => 70.00,
                ],

                'address' => [
                    'zip_code'     => '30140071',
                    'address'      => 'Avenida Afonso Pena',
                    'number'       => '500',
                    'district'     => 'Centro',
                    'complement'   => 'Conjunto 1205',
                    'nickname'     => 'Base BH',
                    'instructions' => 'Entrada pela lateral do edifício.',
                    'state_code'   => 'MG',
                    'city_name'    => 'Belo Horizonte',
                    'address_type' => 'home',
                    'is_primary'   => true,
                    'latitude'     => -19.916681,
                    'longitude'    => -43.934493,
                ],

                'service_types' => [
                    'Lavanderia',
                    'Passadoria',
                    'Organização de ambientes',
                ],

                'specialities' => [
                    'Closet',
                    'Cozinha',
                    'Lavanderia',
                ],

                'working_days' => [
                    ['day' => 2, 'period' => WorkingPeriodEnum::AFTERNOON->value],
                    ['day' => 3, 'period' => WorkingPeriodEnum::AFTERNOON->value],
                    ['day' => 4, 'period' => WorkingPeriodEnum::AFTERNOON->value],
                    ['day' => 5, 'period' => WorkingPeriodEnum::AFTERNOON->value],
                    ['day' => 6, 'period' => WorkingPeriodEnum::MORNING->value],
                ],
            ],

            [
                'user' => [
                    'name'                  => 'Juliana Lima',
                    'email'                 => 'juliana.lima@softpar.inf.br',
                    'phone'                 => '11990000004',
                    'code'                  => '100004',
                    'password'              => 'S@ft2080.',
                    'type'                  => UserTypeEnum::PROVIDER,
                    'email_verified_at'     => now(),
                    'validated_code'        => true,
                    'registration_complete' => true,
                ],

                'provider' => [
                    'document'          => '12345678909',
                    'rg'                => '45.321.987-6',
                    'birth_date'        => '1993-02-15',
                    'average_rating'    => 4.6,
                    'total_services'    => 87,
                    'selfie_verified'   => true,
                    'document_verified' => true,
                    'approval_status'   => ApprovalStatusEnum::ACCEPTED,
                    'daily_price_8h'    => 190.00,
                    'daily_price_6h'    => 150.00,
                    'daily_price_4h'    => 115.00,
                    'daily_price_2h'    => 75.00,
                ],

                'address' => [
                    'zip_code'     => '80010020',
                    'address'      => 'Rua XV de Novembro',
                    'number'       => '250',
                    'district'     => 'Centro',
                    'complement'   => 'Sala 3',
                    'nickname'     => 'Base Curitiba',
                    'instructions' => 'Subir até o segundo andar.',
                    'state_code'   => 'PR',
                    'city_name'    => 'Curitiba',
                    'address_type' => 'home',
                    'is_primary'   => true,
                    'latitude'     => -25.428356,
                    'longitude'    => -49.273251,
                ],

                'service_types' => [
                    'Limpeza residencial',
                    'Limpeza pós-obra',
                    'Lavanderia',
                ],

                'specialities' => [
                    'Casa',
                    'Apartamento',
                    'Organização de ambientes',
                ],

                'working_days' => [
                    ['day' => 1, 'period' => WorkingPeriodEnum::MORNING->value],
                    ['day' => 2, 'period' => WorkingPeriodEnum::MORNING->value],
                    ['day' => 3, 'period' => WorkingPeriodEnum::MORNING->value],
                    ['day' => 4, 'period' => WorkingPeriodEnum::MORNING->value],
                    ['day' => 5, 'period' => WorkingPeriodEnum::AFTERNOON->value],
                ],
            ],

            [
                'user' => [
                    'name'                  => 'Renata Alves',
                    'email'                 => 'renata.alves@softpar.inf.br',
                    'phone'                 => '11990000005',
                    'code'                  => '100005',
                    'password'              => 'S@ft2080.',
                    'type'                  => UserTypeEnum::PROVIDER,
                    'email_verified_at'     => now(),
                    'validated_code'        => true,
                    'registration_complete' => true,
                ],

                'provider' => [
                    'document'          => '93541134780',
                    'rg'                => '58.741.236-4',
                    'birth_date'        => '1990-09-08',
                    'average_rating'    => 4.5,
                    'total_services'    => 75,
                    'selfie_verified'   => true,
                    'document_verified' => true,
                    'approval_status'   => ApprovalStatusEnum::ACCEPTED,
                    'daily_price_8h'    => 175.00,
                    'daily_price_6h'    => 135.00,
                    'daily_price_4h'    => 105.00,
                    'daily_price_2h'    => 65.00,
                ],

                'address' => [
                    'zip_code'     => '90010010',
                    'address'      => 'Avenida Borges de Medeiros',
                    'number'       => '700',
                    'district'     => 'Centro Histórico',
                    'complement'   => 'Andar 6',
                    'nickname'     => 'Base POA',
                    'instructions' => 'Interfone para o bloco B.',
                    'state_code'   => 'RS',
                    'city_name'    => 'Porto Alegre',
                    'address_type' => 'home',
                    'is_primary'   => true,
                    'latitude'     => -30.034647,
                    'longitude'    => -51.217659,
                ],

                'service_types' => [
                    'Limpeza residencial',
                    'Limpeza comercial',
                ],

                'specialities' => [
                    'Escritório',
                    'Cozinha',
                    'Banheiro',
                ],

                'working_days' => [
                    ['day' => 1, 'period' => WorkingPeriodEnum::AFTERNOON->value],
                    ['day' => 2, 'period' => WorkingPeriodEnum::AFTERNOON->value],
                    ['day' => 3, 'period' => WorkingPeriodEnum::AFTERNOON->value],
                    ['day' => 4, 'period' => WorkingPeriodEnum::AFTERNOON->value],
                    ['day' => 5, 'period' => WorkingPeriodEnum::AFTERNOON->value],
                ],
            ],
        ];

        DB::transaction(function () use ($providers): void {
            foreach ($providers as $data) {
                $user = User::updateOrCreate(
                    ['email' => $data['user']['email']],
                    $data['user']
                );

                $provider = Provider::updateOrCreate(
                    ['user_id' => $user->id],
                    $data['provider'] + [
                        'user_id' => $user->id,
                    ]
                );

                $this->seedAddress($provider->id, $data['address']);
                $this->seedProviderServicesTypes($provider->id, $data['service_types']);
                $this->seedProviderSpecialities($provider->id, $data['specialities']);
                $this->seedProviderWorkingDays($provider->id, $data['working_days']);
            }
        });
    }

    private function seedAddress(int $providerId, array $data): void
    {
        $state = State::query()
            ->whereRaw('LOWER(code) = ?', [mb_strtolower($data['state_code'])])
            ->first();

        $city = null;

        if ($state) {
            $city = City::query()
                ->where('state_id', $state->id)
                ->whereRaw('LOWER(name) = ?', [mb_strtolower($data['city_name'])])
                ->first();
        }

        Address::updateOrCreate(
            [
                'source'    => 'provider',
                'source_id' => $providerId,
            ],
            [
                'zip_code'       => $data['zip_code'],
                'address'        => $data['address'],
                'number'         => $data['number']   ?? null,
                'district'       => $data['district'] ?? null,
                'has_complement' => ! empty($data['complement']),
                'complement'     => $data['complement']   ?? null,
                'nickname'       => $data['nickname']     ?? null,
                'instructions'   => $data['instructions'] ?? null,
                'city_id'        => $city?->id,
                'state_id'       => $state?->id,
                'address_type'   => $data['address_type'] ?? 'home',
                'is_primary'     => $data['is_primary']   ?? true,
                'latitude'       => $data['latitude']     ?? null,
                'longitude'      => $data['longitude']    ?? null,
            ]
        );
    }

    private function seedProviderServicesTypes(int $providerId, array $descriptions): void
    {
        $serviceTypeIds = ServiceType::query()
            ->whereIn('description', $descriptions)
            ->pluck('id')
            ->all();

        foreach ($serviceTypeIds as $serviceTypeId) {
            ProviderServicesType::updateOrCreate(
                [
                    'provider_id'     => $providerId,
                    'service_type_id' => $serviceTypeId,
                ],
                [
                    'provider_id'     => $providerId,
                    'service_type_id' => $serviceTypeId,
                ]
            );
        }
    }

    private function seedProviderSpecialities(int $providerId, array $descriptions): void
    {
        $specialityIds = Speciality::query()
            ->whereIn('description', $descriptions)
            ->pluck('id')
            ->all();

        foreach ($specialityIds as $specialityId) {
            ProviderSpeciality::updateOrCreate(
                [
                    'provider_id'   => $providerId,
                    'speciality_id' => $specialityId,
                ],
                [
                    'provider_id'   => $providerId,
                    'speciality_id' => $specialityId,
                ]
            );
        }
    }

    private function seedProviderWorkingDays(int $providerId, array $workingDays): void
    {
        foreach ($workingDays as $workingDay) {
            ProviderWorkingDay::updateOrCreate(
                [
                    'provider_id' => $providerId,
                    'day'         => $workingDay['day'],
                    'period'      => $workingDay['period'],
                ],
                [
                    'provider_id' => $providerId,
                    'day'         => $workingDay['day'],
                    'period'      => $workingDay['period'],
                ]
            );
        }
    }
}
