<?php

namespace Database\Seeders;

use App\Enums\CrmModule;
use App\Enums\ExpenseCategory;
use App\Enums\LeadStatus;
use App\Enums\PropertyStatus;
use App\Models\Booking;
use App\Models\Client;
use App\Models\DailyProgressReport;
use App\Models\Expense;
use App\Models\Installment;
use App\Models\Lead;
use App\Models\Material;
use App\Models\MaterialStock;
use App\Models\Milestone;
use App\Models\PaymentPlan;
use App\Models\Project;
use App\Models\Property;
use App\Models\Receipt;
use App\Models\User;
use App\Models\Vendor;
use Illuminate\Database\Seeder;

class CrmDemoDataSeeder extends Seeder
{
    public function run(): void
    {
        if (Project::query()->where('name', 'Green Valley Residency')->exists()) {
            return;
        }

        $engineer = User::query()->where('email', 'construction@crm.com')->first();
        $salesAgent = User::query()->where('email', 'sales@crm.com')->first();

        $this->seedConstruction($engineer);
        $this->seedRealEstate($salesAgent);
    }

    protected function seedConstruction(?User $engineer): void
    {
        $projects = [
            ['name' => 'Green Valley Residency', 'location' => 'Lahore', 'budget' => 45000000],
            ['name' => 'Skyline Commercial Plaza', 'location' => 'Islamabad', 'budget' => 82000000],
            ['name' => 'Canal View Apartments', 'location' => 'Faisalabad', 'budget' => 31000000],
        ];

        $vendor = Vendor::query()->create([
            'name' => 'Al-Habib Building Supplies',
            'contact_person' => 'Imran Khan',
            'phone' => '0300-1234567',
        ]);

        $materials = collect([
            ['name' => 'Cement', 'unit' => 'bag'],
            ['name' => 'Steel Bars', 'unit' => 'ton'],
            ['name' => 'Bricks', 'unit' => '1000 pcs'],
        ])->map(fn (array $data) => Material::query()->create($data));

        foreach ($projects as $index => $data) {
            $project = Project::query()->create([
                ...$data,
                'status' => $index === 2 ? 'on_hold' : 'active',
                'start_date' => now()->subMonths(8 - $index),
                'end_date' => now()->addMonths(6 + $index),
            ]);

            $stages = ['foundation', 'structure', 'finishing', 'handover'];
            foreach ($stages as $i => $stage) {
                Milestone::query()->create([
                    'project_id' => $project->id,
                    'name' => str($stage)->headline()->toString(),
                    'stage' => $stage,
                    'completion_percentage' => min(100, 20 + ($i * 25) + ($index * 5)),
                    'target_date' => now()->addWeeks($i * 3 - $index),
                    'completed_at' => $i === 0 && $index > 0 ? now()->subWeek() : null,
                ]);
            }

            foreach ($materials as $m => $material) {
                $received = 500 + ($m * 200);
                $used = $received * (0.5 + ($index * 0.15));
                MaterialStock::query()->create([
                    'project_id' => $project->id,
                    'material_id' => $material->id,
                    'vendor_id' => $vendor->id,
                    'quantity_received' => $received,
                    'quantity_used' => $used,
                    'unit_price' => rand(800, 2500),
                    'received_date' => now()->subDays(rand(1, 30)),
                    'bill_number' => 'BILL-'.rand(1000, 9999),
                ]);
            }

            for ($m = 0; $m < 6; $m++) {
                Expense::query()->create([
                    'category' => collect(ExpenseCategory::cases())->random()->value,
                    'amount' => rand(150000, 900000),
                    'expense_date' => now()->subMonths(5 - $m)->addDays(rand(1, 20)),
                    'project_id' => $project->id,
                    'vendor_id' => $vendor->id,
                    'module' => CrmModule::Construction,
                    'user_id' => $engineer?->id,
                    'payment_method' => 'bank_transfer',
                    'paid_to' => $vendor->name,
                ]);
            }

            if ($engineer) {
                DailyProgressReport::query()->create([
                    'project_id' => $project->id,
                    'user_id' => $engineer->id,
                    'report_date' => today(),
                    'work_description' => 'Concrete pouring and steel fixing on floor '.rand(1, 5),
                    'labor_count' => rand(15, 45),
                    'weather' => collect(['Sunny', 'Cloudy', 'Clear'])->random(),
                ]);

                DailyProgressReport::query()->create([
                    'project_id' => $project->id,
                    'user_id' => $engineer->id,
                    'report_date' => today()->subDay(),
                    'work_description' => 'Brick work and plastering progress',
                    'labor_count' => rand(10, 30),
                    'weather' => 'Sunny',
                ]);
            }
        }

        Project::query()->create([
            'name' => 'Model Town Extension',
            'location' => 'Multan',
            'status' => 'completed',
            'budget' => 22000000,
            'start_date' => now()->subYear(),
            'end_date' => now()->subMonth(),
        ]);
    }

    protected function seedRealEstate(?User $agent): void
    {
        $clients = collect([
            ['name' => 'Ahmed Hassan', 'phone' => '0321-1112233', 'email' => 'ahmed@example.com'],
            ['name' => 'Sara Malik', 'phone' => '0333-4455667', 'email' => 'sara@example.com'],
            ['name' => 'Bilal Raza', 'phone' => '0345-7788990', 'email' => 'bilal@example.com'],
        ])->map(fn (array $data) => Client::query()->create([
            ...$data,
            'module' => CrmModule::RealEstate,
            'assigned_to' => $agent?->id,
        ]));

        $statuses = [
            LeadStatus::New,
            LeadStatus::Contacted,
            LeadStatus::Qualified,
            LeadStatus::SiteVisit,
            LeadStatus::Negotiation,
            LeadStatus::Won,
            LeadStatus::Lost,
        ];

        foreach ($statuses as $i => $status) {
            Lead::query()->create([
                'name' => 'Lead '.($i + 1).' — '.fake()->firstName(),
                'phone' => '03'.rand(10, 99).'-'.rand(1000000, 9999999),
                'email' => fake()->safeEmail(),
                'source' => collect(['facebook', 'referral', 'walk_in', 'website'])->random(),
                'status' => $status,
                'module' => CrmModule::RealEstate,
                'assigned_to' => $agent?->id,
                'follow_up_at' => now()->addDays(rand(-3, 7)),
                'created_at' => now()->subMonths(rand(0, 5))->subDays(rand(0, 20)),
            ]);
        }

        $project = Project::query()->first();

        $properties = [
            ['title' => 'Plot 12-A Block C', 'type' => 'plot', 'status' => PropertyStatus::Available, 'price' => 5500000],
            ['title' => 'Shop 4 Ground Floor', 'type' => 'commercial', 'status' => PropertyStatus::Available, 'price' => 12000000],
            ['title' => 'Apartment 3B Tower 1', 'type' => 'apartment', 'status' => PropertyStatus::Sold, 'price' => 8500000],
            ['title' => 'Plot 7-B Block A', 'type' => 'plot', 'status' => PropertyStatus::OnHold, 'price' => 4800000],
            ['title' => 'Penthouse Tower 2', 'type' => 'apartment', 'status' => PropertyStatus::Sold, 'price' => 22000000],
        ];

        foreach ($properties as $data) {
            Property::query()->create([
                ...$data,
                'area' => rand(5, 20).' Marla',
                'location' => 'Green Valley',
                'project_id' => $project?->id,
            ]);
        }

        $soldProperty = Property::query()->where('status', PropertyStatus::Sold)->first();
        $client = $clients->first();

        if ($soldProperty && $client) {
            $booking = Booking::query()->create([
                'property_id' => $soldProperty->id,
                'client_id' => $client->id,
                'booking_number' => 'BK-'.now()->format('Y').'-001',
                'booking_date' => now()->subMonths(3),
                'amount' => $soldProperty->price,
                'status' => 'active',
            ]);

            $plan = PaymentPlan::query()->create([
                'booking_id' => $booking->id,
                'total_amount' => $soldProperty->price,
                'plan_type' => 'monthly',
            ]);

            for ($i = 0; $i < 6; $i++) {
                $due = now()->subMonths(3 - $i);
                $isPaid = $i < 3;
                $installment = Installment::query()->create([
                    'payment_plan_id' => $plan->id,
                    'amount' => 500000,
                    'due_date' => $due,
                    'paid_amount' => $isPaid ? 500000 : ($i === 3 ? 200000 : 0),
                    'paid_at' => $isPaid ? $due : null,
                    'status' => $isPaid ? 'paid' : 'pending',
                ]);

                if ($isPaid) {
                    Receipt::query()->create([
                        'installment_id' => $installment->id,
                        'client_id' => $client->id,
                        'receipt_number' => 'RCP-'.str_pad((string) ($i + 1), 4, '0', STR_PAD_LEFT),
                        'amount' => 500000,
                        'payment_method' => 'bank_transfer',
                        'paid_at' => $due,
                        'module' => CrmModule::RealEstate,
                    ]);
                }
            }

            Installment::query()->create([
                'payment_plan_id' => $plan->id,
                'amount' => 750000,
                'due_date' => now()->subWeeks(2),
                'paid_amount' => 0,
                'status' => 'pending',
            ]);
        }

        for ($m = 0; $m < 6; $m++) {
            Receipt::query()->create([
                'client_id' => $clients->random()->id,
                'receipt_number' => 'RCP-M'.($m + 10),
                'amount' => rand(200000, 800000),
                'payment_method' => 'cash',
                'paid_at' => now()->subMonths(5 - $m)->addDays(rand(1, 15)),
                'module' => CrmModule::RealEstate,
            ]);
        }
    }
}
