#!/usr/bin/env python3
"""
Ad Server — سكريبت الإعداد الكامل
شغّله مرة واحدة وسيبني كل ملفات المشروع
"""

import os

BASE = "ad-server"

files = {}

# ─── .env ────────────────────────────────────────────────────────────────────
files[".env"] = """APP_NAME="Ad Server"
APP_ENV=production
APP_KEY=
APP_DEBUG=false
APP_URL=https://ads.tarwej.kapsolat.com

APP_LOCALE=ar
APP_FALLBACK_LOCALE=en
APP_TIMEZONE=Asia/Riyadh

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=kpsolat_tarwej
DB_USERNAME=kpsolat_tarwej
DB_PASSWORD="Mg8j;FWY665[hJQ*"

CACHE_STORE=redis
QUEUE_CONNECTION=redis
SESSION_DRIVER=redis

REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379

MAIL_MAILER=smtp
MAIL_HOST=
MAIL_PORT=587
MAIL_USERNAME=
MAIL_PASSWORD=
MAIL_FROM_ADDRESS="noreply@ads.tarwej.kapsolat.com"
MAIL_FROM_NAME="${APP_NAME}"

FILESYSTEM_DISK=local

ADS_API_SECRET=
"""

# ─── app/Models/User.php ─────────────────────────────────────────────────────
files["app/Models/User.php"] = """<?php

namespace App\\Models;

use Filament\\Models\\Contracts\\FilamentUser;
use Filament\\Models\\Contracts\\HasAvatar;
use Filament\\Panel;
use Illuminate\\Database\\Eloquent\\Factories\\HasFactory;
use Illuminate\\Foundation\\Auth\\User as Authenticatable;
use Illuminate\\Notifications\\Notifiable;
use Spatie\\Permission\\Traits\\HasRoles;

class User extends Authenticatable implements FilamentUser, HasAvatar
{
    use HasFactory, Notifiable, HasRoles;

    protected $fillable = [
        'name',
        'email',
        'password',
        'avatar_url',
        'is_active',
    ];

    protected $hidden = ['password', 'remember_token'];

    protected function casts(): array
    {
        return [
            'email_verified_at' => 'datetime',
            'password'          => 'hashed',
            'is_active'         => 'boolean',
        ];
    }

    public function canAccessPanel(Panel $panel): bool
    {
        return $this->is_active && $this->hasAnyRole(['super_admin', 'admin']);
    }

    public function getFilamentAvatarUrl(): ?string
    {
        return $this->avatar_url;
    }

    public function isSuperAdmin(): bool
    {
        return $this->hasRole('super_admin');
    }

    public function isAdmin(): bool
    {
        return $this->hasRole('admin');
    }
}
"""

# ─── app/Models/Advertiser.php ───────────────────────────────────────────────
files["app/Models/Advertiser.php"] = """<?php

namespace App\\Models;

use Illuminate\\Database\\Eloquent\\Model;
use Illuminate\\Database\\Eloquent\\Relations\\HasMany;
use Illuminate\\Database\\Eloquent\\SoftDeletes;

class Advertiser extends Model
{
    use SoftDeletes;

    protected $fillable = ['name', 'email', 'phone', 'company', 'is_active'];

    protected function casts(): array
    {
        return ['is_active' => 'boolean'];
    }

    public function campaigns(): HasMany
    {
        return $this->hasMany(Campaign::class);
    }
}
"""

# ─── app/Models/Campaign.php ─────────────────────────────────────────────────
files["app/Models/Campaign.php"] = """<?php

namespace App\\Models;

use Illuminate\\Database\\Eloquent\\Model;
use Illuminate\\Database\\Eloquent\\Relations\\BelongsTo;
use Illuminate\\Database\\Eloquent\\Relations\\HasMany;
use Illuminate\\Database\\Eloquent\\SoftDeletes;

class Campaign extends Model
{
    use SoftDeletes;

    protected $fillable = [
        'advertiser_id',
        'name',
        'status',
        'budget',
        'budget_spent',
        'starts_at',
        'ends_at',
    ];

    protected function casts(): array
    {
        return [
            'budget'       => 'decimal:2',
            'budget_spent' => 'decimal:2',
            'starts_at'    => 'datetime',
            'ends_at'      => 'datetime',
        ];
    }

    public function advertiser(): BelongsTo
    {
        return $this->belongsTo(Advertiser::class);
    }

    public function ads(): HasMany
    {
        return $this->hasMany(Ad::class);
    }

    public function isActive(): bool
    {
        return $this->status === 'active'
            && now()->between($this->starts_at, $this->ends_at)
            && $this->budget_spent < $this->budget;
    }
}
"""

# ─── app/Models/Ad.php ───────────────────────────────────────────────────────
files["app/Models/Ad.php"] = """<?php

namespace App\\Models;

use Illuminate\\Database\\Eloquent\\Model;
use Illuminate\\Database\\Eloquent\\Relations\\BelongsTo;
use Illuminate\\Database\\Eloquent\\Relations\\HasMany;
use Illuminate\\Database\\Eloquent\\SoftDeletes;

class Ad extends Model
{
    use SoftDeletes;

    protected $fillable = [
        'campaign_id',
        'ad_zone_id',
        'type',
        'title',
        'content',
        'media_url',
        'click_url',
        'is_active',
        'weight',
    ];

    protected function casts(): array
    {
        return [
            'is_active' => 'boolean',
            'weight'    => 'integer',
        ];
    }

    public function campaign(): BelongsTo
    {
        return $this->belongsTo(Campaign::class);
    }

    public function zone(): BelongsTo
    {
        return $this->belongsTo(AdZone::class, 'ad_zone_id');
    }

    public function impressions(): HasMany
    {
        return $this->hasMany(Impression::class);
    }

    public function clicks(): HasMany
    {
        return $this->hasMany(Click::class);
    }
}
"""

# ─── app/Models/AdZone.php ───────────────────────────────────────────────────
files["app/Models/AdZone.php"] = """<?php

namespace App\\Models;

use Illuminate\\Database\\Eloquent\\Model;
use Illuminate\\Database\\Eloquent\\Relations\\BelongsTo;
use Illuminate\\Database\\Eloquent\\Relations\\HasMany;

class AdZone extends Model
{
    protected $fillable = [
        'platform_id',
        'name',
        'slug',
        'type',
        'width',
        'height',
        'is_active',
    ];

    protected function casts(): array
    {
        return ['is_active' => 'boolean'];
    }

    public function platform(): BelongsTo
    {
        return $this->belongsTo(Platform::class);
    }

    public function ads(): HasMany
    {
        return $this->hasMany(Ad::class);
    }
}
"""

# ─── app/Models/Platform.php ─────────────────────────────────────────────────
files["app/Models/Platform.php"] = """<?php

namespace App\\Models;

use Illuminate\\Database\\Eloquent\\Model;
use Illuminate\\Database\\Eloquent\\Relations\\HasMany;
use Illuminate\\Support\\Str;

class Platform extends Model
{
    protected $fillable = ['name', 'domain', 'api_key', 'is_active'];

    protected function casts(): array
    {
        return ['is_active' => 'boolean'];
    }

    protected static function booted(): void
    {
        static::creating(function ($platform) {
            $platform->api_key = Str::random(64);
        });
    }

    public function zones(): HasMany
    {
        return $this->hasMany(AdZone::class);
    }
}
"""

# ─── app/Models/Impression.php ───────────────────────────────────────────────
files["app/Models/Impression.php"] = """<?php

namespace App\\Models;

use Illuminate\\Database\\Eloquent\\Model;
use Illuminate\\Database\\Eloquent\\Relations\\BelongsTo;

class Impression extends Model
{
    public $timestamps = false;

    protected $fillable = [
        'ad_id',
        'platform_id',
        'ip',
        'user_agent',
        'country',
        'is_bot',
        'viewed_at',
    ];

    protected function casts(): array
    {
        return [
            'is_bot'    => 'boolean',
            'viewed_at' => 'datetime',
        ];
    }

    public function ad(): BelongsTo
    {
        return $this->belongsTo(Ad::class);
    }
}
"""

# ─── app/Models/Click.php ────────────────────────────────────────────────────
files["app/Models/Click.php"] = """<?php

namespace App\\Models;

use Illuminate\\Database\\Eloquent\\Model;
use Illuminate\\Database\\Eloquent\\Relations\\BelongsTo;

class Click extends Model
{
    public $timestamps = false;

    protected $fillable = [
        'ad_id',
        'platform_id',
        'ip',
        'user_agent',
        'is_bot',
        'clicked_at',
    ];

    protected function casts(): array
    {
        return [
            'is_bot'     => 'boolean',
            'clicked_at' => 'datetime',
        ];
    }

    public function ad(): BelongsTo
    {
        return $this->belongsTo(Ad::class);
    }
}
"""

# ─── app/Models/BotLog.php ───────────────────────────────────────────────────
files["app/Models/BotLog.php"] = """<?php

namespace App\\Models;

use Illuminate\\Database\\Eloquent\\Model;

class BotLog extends Model
{
    protected $fillable = [
        'ip',
        'user_agent',
        'reason',
        'request_data',
        'is_blocked',
    ];

    protected function casts(): array
    {
        return [
            'request_data' => 'array',
            'is_blocked'   => 'boolean',
        ];
    }
}
"""

# ─── app/Models/IpBlock.php ──────────────────────────────────────────────────
files["app/Models/IpBlock.php"] = """<?php

namespace App\\Models;

use Illuminate\\Database\\Eloquent\\Model;

class IpBlock extends Model
{
    protected $fillable = ['ip', 'reason', 'blocked_until'];

    protected function casts(): array
    {
        return ['blocked_until' => 'datetime'];
    }

    public function isExpired(): bool
    {
        return $this->blocked_until && $this->blocked_until->isPast();
    }
}
"""

# ─── Migrations ──────────────────────────────────────────────────────────────
files["database/migrations/2024_01_01_000000_create_users_table.php"] = """<?php

use Illuminate\\Database\\Migrations\\Migration;
use Illuminate\\Database\\Schema\\Blueprint;
use Illuminate\\Support\\Facades\\Schema;

return new class extends Migration {
    public function up(): void
    {
        Schema::create('users', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->string('email')->unique();
            $table->timestamp('email_verified_at')->nullable();
            $table->string('password');
            $table->string('avatar_url')->nullable();
            $table->boolean('is_active')->default(true);
            $table->rememberToken();
            $table->timestamps();
        });

        Schema::create('password_reset_tokens', function (Blueprint $table) {
            $table->string('email')->primary();
            $table->string('token');
            $table->timestamp('created_at')->nullable();
        });

        Schema::create('sessions', function (Blueprint $table) {
            $table->string('id')->primary();
            $table->foreignId('user_id')->nullable()->index();
            $table->string('ip_address', 45)->nullable();
            $table->text('user_agent')->nullable();
            $table->longText('payload');
            $table->integer('last_activity')->index();
        });
    }

    public function down(): void
    {
        Schema::dropIfExists('users');
        Schema::dropIfExists('password_reset_tokens');
        Schema::dropIfExists('sessions');
    }
};
"""

files["database/migrations/2024_01_01_000001_create_advertisers_table.php"] = """<?php

use Illuminate\\Database\\Migrations\\Migration;
use Illuminate\\Database\\Schema\\Blueprint;
use Illuminate\\Support\\Facades\\Schema;

return new class extends Migration {
    public function up(): void
    {
        Schema::create('advertisers', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->string('email')->unique();
            $table->string('phone')->nullable();
            $table->string('company')->nullable();
            $table->boolean('is_active')->default(true);
            $table->softDeletes();
            $table->timestamps();
        });
    }

    public function down(): void { Schema::dropIfExists('advertisers'); }
};
"""

files["database/migrations/2024_01_01_000002_create_campaigns_table.php"] = """<?php

use Illuminate\\Database\\Migrations\\Migration;
use Illuminate\\Database\\Schema\\Blueprint;
use Illuminate\\Support\\Facades\\Schema;

return new class extends Migration {
    public function up(): void
    {
        Schema::create('campaigns', function (Blueprint $table) {
            $table->id();
            $table->foreignId('advertiser_id')->constrained()->cascadeOnDelete();
            $table->string('name');
            $table->enum('status', ['draft', 'active', 'paused', 'ended'])->default('draft');
            $table->decimal('budget', 10, 2)->default(0);
            $table->decimal('budget_spent', 10, 2)->default(0);
            $table->timestamp('starts_at')->nullable();
            $table->timestamp('ends_at')->nullable();
            $table->softDeletes();
            $table->timestamps();
        });
    }

    public function down(): void { Schema::dropIfExists('campaigns'); }
};
"""

files["database/migrations/2024_01_01_000003_create_platforms_table.php"] = """<?php

use Illuminate\\Database\\Migrations\\Migration;
use Illuminate\\Database\\Schema\\Blueprint;
use Illuminate\\Support\\Facades\\Schema;

return new class extends Migration {
    public function up(): void
    {
        Schema::create('platforms', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->string('domain')->unique();
            $table->string('api_key', 64)->unique();
            $table->boolean('is_active')->default(true);
            $table->timestamps();
        });
    }

    public function down(): void { Schema::dropIfExists('platforms'); }
};
"""

files["database/migrations/2024_01_01_000004_create_ad_zones_table.php"] = """<?php

use Illuminate\\Database\\Migrations\\Migration;
use Illuminate\\Database\\Schema\\Blueprint;
use Illuminate\\Support\\Facades\\Schema;

return new class extends Migration {
    public function up(): void
    {
        Schema::create('ad_zones', function (Blueprint $table) {
            $table->id();
            $table->foreignId('platform_id')->constrained()->cascadeOnDelete();
            $table->string('name');
            $table->string('slug')->unique();
            $table->enum('type', ['banner', 'text', 'video'])->default('banner');
            $table->integer('width')->nullable();
            $table->integer('height')->nullable();
            $table->boolean('is_active')->default(true);
            $table->timestamps();
        });
    }

    public function down(): void { Schema::dropIfExists('ad_zones'); }
};
"""

files["database/migrations/2024_01_01_000005_create_ads_table.php"] = """<?php

use Illuminate\\Database\\Migrations\\Migration;
use Illuminate\\Database\\Schema\\Blueprint;
use Illuminate\\Support\\Facades\\Schema;

return new class extends Migration {
    public function up(): void
    {
        Schema::create('ads', function (Blueprint $table) {
            $table->id();
            $table->foreignId('campaign_id')->constrained()->cascadeOnDelete();
            $table->foreignId('ad_zone_id')->constrained()->cascadeOnDelete();
            $table->enum('type', ['text', 'image', 'video'])->default('image');
            $table->string('title')->nullable();
            $table->text('content')->nullable();
            $table->string('media_url')->nullable();
            $table->string('click_url');
            $table->boolean('is_active')->default(true);
            $table->integer('weight')->default(1);
            $table->softDeletes();
            $table->timestamps();
        });
    }

    public function down(): void { Schema::dropIfExists('ads'); }
};
"""

files["database/migrations/2024_01_01_000006_create_impressions_table.php"] = """<?php

use Illuminate\\Database\\Migrations\\Migration;
use Illuminate\\Database\\Schema\\Blueprint;
use Illuminate\\Support\\Facades\\Schema;

return new class extends Migration {
    public function up(): void
    {
        Schema::create('impressions', function (Blueprint $table) {
            $table->id();
            $table->foreignId('ad_id')->constrained()->cascadeOnDelete();
            $table->foreignId('platform_id')->constrained()->cascadeOnDelete();
            $table->string('ip', 45);
            $table->text('user_agent')->nullable();
            $table->string('country', 2)->nullable();
            $table->boolean('is_bot')->default(false);
            $table->timestamp('viewed_at');
            $table->index(['ad_id', 'viewed_at']);
            $table->index(['is_bot']);
        });
    }

    public function down(): void { Schema::dropIfExists('impressions'); }
};
"""

files["database/migrations/2024_01_01_000007_create_clicks_table.php"] = """<?php

use Illuminate\\Database\\Migrations\\Migration;
use Illuminate\\Database\\Schema\\Blueprint;
use Illuminate\\Support\\Facades\\Schema;

return new class extends Migration {
    public function up(): void
    {
        Schema::create('clicks', function (Blueprint $table) {
            $table->id();
            $table->foreignId('ad_id')->constrained()->cascadeOnDelete();
            $table->foreignId('platform_id')->constrained()->cascadeOnDelete();
            $table->string('ip', 45);
            $table->text('user_agent')->nullable();
            $table->boolean('is_bot')->default(false);
            $table->timestamp('clicked_at');
            $table->index(['ad_id', 'clicked_at']);
        });
    }

    public function down(): void { Schema::dropIfExists('clicks'); }
};
"""

files["database/migrations/2024_01_01_000008_create_bot_logs_table.php"] = """<?php

use Illuminate\\Database\\Migrations\\Migration;
use Illuminate\\Database\\Schema\\Blueprint;
use Illuminate\\Support\\Facades\\Schema;

return new class extends Migration {
    public function up(): void
    {
        Schema::create('bot_logs', function (Blueprint $table) {
            $table->id();
            $table->string('ip', 45);
            $table->text('user_agent')->nullable();
            $table->string('reason');
            $table->json('request_data')->nullable();
            $table->boolean('is_blocked')->default(false);
            $table->timestamps();
            $table->index('ip');
        });
    }

    public function down(): void { Schema::dropIfExists('bot_logs'); }
};
"""

files["database/migrations/2024_01_01_000009_create_ip_blocks_table.php"] = """<?php

use Illuminate\\Database\\Migrations\\Migration;
use Illuminate\\Database\\Schema\\Blueprint;
use Illuminate\\Support\\Facades\\Schema;

return new class extends Migration {
    public function up(): void
    {
        Schema::create('ip_blocks', function (Blueprint $table) {
            $table->id();
            $table->string('ip', 45)->unique();
            $table->string('reason')->nullable();
            $table->timestamp('blocked_until')->nullable();
            $table->timestamps();
        });
    }

    public function down(): void { Schema::dropIfExists('ip_blocks'); }
};
"""

# ─── Seeder ──────────────────────────────────────────────────────────────────
files["database/seeders/DatabaseSeeder.php"] = """<?php

namespace Database\\Seeders;

use App\\Models\\User;
use Illuminate\\Database\\Seeder;
use Spatie\\Permission\\Models\\Permission;
use Spatie\\Permission\\Models\\Role;

class DatabaseSeeder extends Seeder
{
    public function run(): void
    {
        $superAdmin = Role::firstOrCreate(['name' => 'super_admin']);
        $admin      = Role::firstOrCreate(['name' => 'admin']);

        $permissions = [
            'campaigns.view', 'campaigns.create', 'campaigns.edit', 'campaigns.delete',
            'ads.view', 'ads.create', 'ads.edit', 'ads.delete',
            'platforms.view', 'platforms.create', 'platforms.edit', 'platforms.delete',
            'analytics.view', 'analytics.export',
            'bot-logs.view', 'bot-logs.manage',
            'ip-blocks.manage',
            'settings.view', 'settings.edit',
            'users.view', 'users.create', 'users.edit', 'users.delete',
        ];

        foreach ($permissions as $perm) {
            Permission::firstOrCreate(['name' => $perm]);
        }

        $superAdmin->syncPermissions(Permission::all());

        $adminPerms = array_filter($permissions, fn($p) =>
            ! str_ends_with($p, '.delete') &&
            ! str_starts_with($p, 'users.') &&
            ! str_starts_with($p, 'settings.')
        );
        $admin->syncPermissions($adminPerms);

        $user = User::firstOrCreate(
            ['email' => 'admin@ads.com'],
            [
                'name'      => 'Super Admin',
                'password'  => bcrypt('Admin@1234'),
                'is_active' => true,
            ]
        );
        $user->assignRole('super_admin');

        $this->command->info('تم إنشاء السوبر ادمن: admin@ads.com / Admin@1234');
        $this->command->warn('غيّر كلمة المرور فوراً بعد أول تسجيل دخول');
    }
}
"""

# ─── Providers ───────────────────────────────────────────────────────────────
files["app/Providers/AppServiceProvider.php"] = """<?php

namespace App\\Providers;

use Illuminate\\Database\\Eloquent\\Model;
use Illuminate\\Support\\Facades\\Gate;
use Illuminate\\Support\\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    public function register(): void {}

    public function boot(): void
    {
        Model::preventLazyLoading(! app()->isProduction());
        Model::preventSilentlyDiscardingAttributes(! app()->isProduction());

        Gate::before(function ($user, $ability) {
            return $user->isSuperAdmin() ? true : null;
        });
    }
}
"""

files["app/Providers/Filament/AdminPanelProvider.php"] = """<?php

namespace App\\Providers\\Filament;

use App\\Filament\\Pages\\Dashboard;
use App\\Http\\Middleware\\EnsureUserIsActive;
use Filament\\Http\\Middleware\\Authenticate;
use Filament\\Http\\Middleware\\AuthenticateSession;
use Filament\\Http\\Middleware\\DisableBladeIconComponents;
use Filament\\Http\\Middleware\\DispatchServingFilamentEvent;
use Filament\\Navigation\\NavigationGroup;
use Filament\\Panel;
use Filament\\PanelProvider;
use Filament\\Support\\Colors\\Color;
use Filament\\Widgets\\AccountWidget;
use Illuminate\\Cookie\\Middleware\\AddQueuedCookiesToResponse;
use Illuminate\\Cookie\\Middleware\\EncryptCookies;
use Illuminate\\Foundation\\Http\\Middleware\\VerifyCsrfToken;
use Illuminate\\Routing\\Middleware\\SubstituteBindings;
use Illuminate\\Session\\Middleware\\StartSession;
use Illuminate\\View\\Middleware\\ShareErrorsFromSession;

class AdminPanelProvider extends PanelProvider
{
    public function panel(Panel $panel): Panel
    {
        return $panel
            ->default()
            ->id('admin')
            ->path('/')
            ->login()
            ->colors([
                'primary' => Color::Indigo,
                'danger'  => Color::Red,
                'success' => Color::Emerald,
                'warning' => Color::Amber,
                'info'    => Color::Blue,
            ])
            ->brandName('Ad Server')
            ->favicon(asset('images/favicon.ico'))
            ->darkMode(true)
            ->discoverResources(in: app_path('Filament/Resources'), for: 'App\\\\Filament\\\\Resources')
            ->discoverPages(in: app_path('Filament/Pages'), for: 'App\\\\Filament\\\\Pages')
            ->discoverWidgets(in: app_path('Filament/Widgets'), for: 'App\\\\Filament\\\\Widgets')
            ->pages([Dashboard::class])
            ->widgets([AccountWidget::class])
            ->navigationGroups([
                NavigationGroup::make('الإعلانات')->icon('heroicon-o-megaphone'),
                NavigationGroup::make('الإحصائيات')->icon('heroicon-o-chart-bar'),
                NavigationGroup::make('الأمان')->icon('heroicon-o-shield-check')->collapsed(),
                NavigationGroup::make('الإعدادات')->icon('heroicon-o-cog-6-tooth')->collapsed(),
            ])
            ->middleware([
                EncryptCookies::class,
                AddQueuedCookiesToResponse::class,
                StartSession::class,
                AuthenticateSession::class,
                ShareErrorsFromSession::class,
                VerifyCsrfToken::class,
                SubstituteBindings::class,
                DisableBladeIconComponents::class,
                DispatchServingFilamentEvent::class,
            ])
            ->authMiddleware([
                Authenticate::class,
                EnsureUserIsActive::class,
            ]);
    }
}
"""

# ─── Middleware ───────────────────────────────────────────────────────────────
files["app/Http/Middleware/EnsureUserIsActive.php"] = """<?php

namespace App\\Http\\Middleware;

use Closure;
use Illuminate\\Http\\Request;
use Symfony\\Component\\HttpFoundation\\Response;

class EnsureUserIsActive
{
    public function handle(Request $request, Closure $next): Response
    {
        if (auth()->check() && ! auth()->user()->is_active) {
            auth()->logout();
            return redirect()->route('filament.admin.auth.login')
                ->withErrors(['email' => 'هذا الحساب موقوف. تواصل مع المدير.']);
        }
        return $next($request);
    }
}
"""

# ─── Filament Pages ──────────────────────────────────────────────────────────
files["app/Filament/Pages/Dashboard.php"] = """<?php

namespace App\\Filament\\Pages;

use App\\Filament\\Widgets\\BotDetectionWidget;
use App\\Filament\\Widgets\\ImpressionsChartWidget;
use App\\Filament\\Widgets\\StatsOverviewWidget;
use App\\Filament\\Widgets\\TopAdsWidget;
use Filament\\Pages\\Dashboard as BaseDashboard;

class Dashboard extends BaseDashboard
{
    protected static ?string $navigationIcon  = 'heroicon-o-home';
    protected static ?string $navigationLabel = 'الرئيسية';
    protected static ?string $title           = 'لوحة التحكم';
    protected static ?int    $navigationSort  = 0;

    public function getWidgets(): array
    {
        return [
            StatsOverviewWidget::class,
            ImpressionsChartWidget::class,
            BotDetectionWidget::class,
            TopAdsWidget::class,
        ];
    }

    public function getColumns(): int|string|array
    {
        return 2;
    }
}
"""

# ─── Filament Widgets (stubs) ─────────────────────────────────────────────────
files["app/Filament/Widgets/StatsOverviewWidget.php"] = """<?php

namespace App\\Filament\\Widgets;

use App\\Models\\Click;
use App\\Models\\Impression;
use Filament\\Widgets\\StatsOverviewWidget as BaseWidget;
use Filament\\Widgets\\StatsOverviewWidget\\Stat;

class StatsOverviewWidget extends BaseWidget
{
    protected function getStats(): array
    {
        return [
            Stat::make('مشاهدات اليوم', Impression::whereDate('viewed_at', today())->count())
                ->description('إجمالي المشاهدات')
                ->color('success'),

            Stat::make('نقرات اليوم', Click::whereDate('clicked_at', today())->count())
                ->description('إجمالي النقرات')
                ->color('info'),

            Stat::make('بوتات مكتشفة', Impression::whereDate('viewed_at', today())->where('is_bot', true)->count())
                ->description('هذا اليوم')
                ->color('danger'),
        ];
    }
}
"""

files["app/Filament/Widgets/ImpressionsChartWidget.php"] = """<?php

namespace App\\Filament\\Widgets;

use App\\Models\\Impression;
use Filament\\Widgets\\ChartWidget;
use Illuminate\\Support\\Carbon;

class ImpressionsChartWidget extends ChartWidget
{
    protected static ?string $heading = 'المشاهدات — آخر 7 أيام';
    protected static ?int $sort = 2;

    protected function getData(): array
    {
        $data = collect(range(6, 0))->map(function ($daysAgo) {
            $date = Carbon::today()->subDays($daysAgo);
            return [
                'date'  => $date->format('m/d'),
                'count' => Impression::whereDate('viewed_at', $date)->where('is_bot', false)->count(),
            ];
        });

        return [
            'datasets' => [[
                'label' => 'مشاهدات حقيقية',
                'data'  => $data->pluck('count')->toArray(),
            ]],
            'labels' => $data->pluck('date')->toArray(),
        ];
    }

    protected function getType(): string
    {
        return 'line';
    }
}
"""

files["app/Filament/Widgets/BotDetectionWidget.php"] = """<?php

namespace App\\Filament\\Widgets;

use App\\Models\\BotLog;
use Filament\\Tables;
use Filament\\Tables\\Table;
use Filament\\Widgets\\TableWidget as BaseWidget;

class BotDetectionWidget extends BaseWidget
{
    protected static ?string $heading = 'آخر البوتات المكتشفة';
    protected static ?int $sort = 3;
    protected int|string|array $columnSpan = 'full';

    public function table(Table $table): Table
    {
        return $table
            ->query(BotLog::query()->latest()->limit(10))
            ->columns([
                Tables\\Columns\\TextColumn::make('ip')->label('IP'),
                Tables\\Columns\\TextColumn::make('reason')->label('السبب'),
                Tables\\Columns\\IconColumn::make('is_blocked')->label('محظور')->boolean(),
                Tables\\Columns\\TextColumn::make('created_at')->label('الوقت')->since(),
            ]);
    }
}
"""

files["app/Filament/Widgets/TopAdsWidget.php"] = """<?php

namespace App\\Filament\\Widgets;

use App\\Models\\Ad;
use Filament\\Tables;
use Filament\\Tables\\Table;
use Filament\\Widgets\\TableWidget as BaseWidget;

class TopAdsWidget extends BaseWidget
{
    protected static ?string $heading = 'أفضل الإعلانات';
    protected static ?int $sort = 4;

    public function table(Table $table): Table
    {
        return $table
            ->query(Ad::withCount(['impressions', 'clicks'])->orderByDesc('impressions_count')->limit(5))
            ->columns([
                Tables\\Columns\\TextColumn::make('title')->label('الإعلان'),
                Tables\\Columns\\TextColumn::make('impressions_count')->label('مشاهدات'),
                Tables\\Columns\\TextColumn::make('clicks_count')->label('نقرات'),
            ]);
    }
}
"""

# ─── Controllers ─────────────────────────────────────────────────────────────
files["app/Http/Controllers/AdController.php"] = """<?php

namespace App\\Http\\Controllers;

use App\\DTOs\\AdContext;
use App\\Services\\AdServingService;
use Illuminate\\Http\\JsonResponse;
use Illuminate\\Http\\Request;

class AdController extends Controller
{
    public function __construct(
        private readonly AdServingService $adService
    ) {}

    public function serve(Request $request, string $zone): JsonResponse
    {
        $context = AdContext::fromRequest($request, $zone);
        $ad = $this->adService->serve($context);

        if (! $ad) {
            return response()->json(['ad' => null], 204);
        }

        return response()->json(['ad' => $ad]);
    }
}
"""

files["app/Http/Controllers/TrackController.php"] = """<?php

namespace App\\Http\\Controllers;

use App\\Jobs\\ProcessImpressionBatch;
use App\\Jobs\\ProcessClickBatch;
use Illuminate\\Http\\JsonResponse;
use Illuminate\\Http\\Request;

class TrackController extends Controller
{
    public function impression(Request $request): JsonResponse
    {
        $request->validate([
            'ad_id'       => 'required|integer',
            'platform_id' => 'required|integer',
        ]);

        ProcessImpressionBatch::dispatch($request->all() + [
            'ip'         => $request->ip(),
            'user_agent' => $request->userAgent(),
            'viewed_at'  => now(),
        ]);

        return response()->json(['status' => 'queued']);
    }

    public function click(Request $request): JsonResponse
    {
        $request->validate([
            'ad_id'       => 'required|integer',
            'platform_id' => 'required|integer',
        ]);

        ProcessClickBatch::dispatch($request->all() + [
            'ip'         => $request->ip(),
            'user_agent' => $request->userAgent(),
            'clicked_at' => now(),
        ]);

        return response()->json(['status' => 'queued']);
    }
}
"""

# ─── Services ────────────────────────────────────────────────────────────────
files["app/Services/AdServingService.php"] = """<?php

namespace App\\Services;

use App\\DTOs\\AdContext;
use App\\Models\\Ad;
use App\\Models\\AdZone;

class AdServingService
{
    public function serve(AdContext $context): ?array
    {
        $zone = AdZone::where('slug', $context->zone)
            ->where('is_active', true)
            ->first();

        if (! $zone) return null;

        $ad = Ad::where('ad_zone_id', $zone->id)
            ->where('is_active', true)
            ->whereHas('campaign', fn($q) => $q->where('status', 'active'))
            ->inRandomOrder()
            ->first();

        if (! $ad) return null;

        return [
            'id'        => $ad->id,
            'type'      => $ad->type,
            'title'     => $ad->title,
            'content'   => $ad->content,
            'media_url' => $ad->media_url,
            'click_url' => $ad->click_url,
        ];
    }
}
"""

files["app/Services/BotDetectionService.php"] = """<?php

namespace App\\Services;

use App\\Models\\IpBlock;
use Illuminate\\Http\\Request;

class BotDetectionService
{
    private array $botPatterns = [
        'bot', 'crawler', 'spider', 'scraper',
        'headless', 'phantom', 'selenium', 'puppeteer',
        'curl', 'wget', 'python-requests', 'go-http',
    ];

    public function isBot(Request $request): array
    {
        $ua = strtolower($request->userAgent() ?? '');
        $ip = $request->ip();

        if ($this->isIpBlocked($ip)) {
            return ['is_bot' => true, 'reason' => 'ip_blocked'];
        }

        foreach ($this->botPatterns as $pattern) {
            if (str_contains($ua, $pattern)) {
                return ['is_bot' => true, 'reason' => "ua_pattern:{$pattern}"];
            }
        }

        if (empty($ua)) {
            return ['is_bot' => true, 'reason' => 'empty_user_agent'];
        }

        return ['is_bot' => false, 'reason' => null];
    }

    private function isIpBlocked(string $ip): bool
    {
        return IpBlock::where('ip', $ip)
            ->where(fn($q) => $q->whereNull('blocked_until')
                ->orWhere('blocked_until', '>', now()))
            ->exists();
    }
}
"""

# ─── DTOs ────────────────────────────────────────────────────────────────────
files["app/DTOs/AdContext.php"] = """<?php

namespace App\\DTOs;

use Illuminate\\Http\\Request;

class AdContext
{
    public function __construct(
        public readonly string $zone,
        public readonly string $ip,
        public readonly string $userAgent,
        public readonly ?string $country = null,
    ) {}

    public static function fromRequest(Request $request, string $zone): self
    {
        return new self(
            zone:      $zone,
            ip:        $request->ip(),
            userAgent: $request->userAgent() ?? '',
        );
    }
}
"""

# ─── Jobs ────────────────────────────────────────────────────────────────────
files["app/Jobs/ProcessImpressionBatch.php"] = """<?php

namespace App\\Jobs;

use App\\Models\\Impression;
use Illuminate\\Bus\\Queueable;
use Illuminate\\Contracts\\Queue\\ShouldQueue;
use Illuminate\\Foundation\\Bus\\Dispatchable;
use Illuminate\\Queue\\InteractsWithQueue;

class ProcessImpressionBatch implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable;

    public function __construct(private array $data) {}

    public function handle(): void
    {
        Impression::create($this->data);
    }
}
"""

files["app/Jobs/ProcessClickBatch.php"] = """<?php

namespace App\\Jobs;

use App\\Models\\Click;
use Illuminate\\Bus\\Queueable;
use Illuminate\\Contracts\\Queue\\ShouldQueue;
use Illuminate\\Foundation\\Bus\\Dispatchable;
use Illuminate\\Queue\\InteractsWithQueue;

class ProcessClickBatch implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable;

    public function __construct(private array $data) {}

    public function handle(): void
    {
        Click::create($this->data);
    }
}
"""

# ─── Routes ───────────────────────────────────────────────────────────────────
files["routes/api.php"] = """<?php

use App\\Http\\Controllers\\AdController;
use App\\Http\\Controllers\\TrackController;
use Illuminate\\Support\\Facades\\Route;

Route::prefix('v1')->middleware(['api', 'throttle:300,1'])->group(function () {
    Route::get('/serve/{zone}',          [AdController::class,   'serve'])->name('ads.serve');
    Route::post('/track/impression',     [TrackController::class, 'impression'])->name('ads.track.impression');
    Route::post('/track/click',          [TrackController::class, 'click'])->name('ads.track.click');
    Route::get('/ping', fn() => response()->json(['status' => 'ok']))->name('ads.ping');
});
"""

files["routes/web.php"] = """<?php

use Illuminate\\Support\\Facades\\Route;

Route::get('/', fn() => redirect('/dashboard'));
"""

# ─── README ───────────────────────────────────────────────────────────────────
files["README.md"] = """# Ad Server

## التثبيت السريع

```bash
composer create-project laravel/laravel ad-server
cd ad-server

composer require filament/filament:"^3.3"
composer require spatie/laravel-permission

php artisan filament:install --panels
php artisan vendor:publish --provider="Spatie\\\\Permission\\\\PermissionServiceProvider"

php artisan migrate
php artisan db:seed
```

## تسجيل الدخول
- الرابط: https://ads.tarwej.kapsolat.com
- البريد: admin@ads.com
- كلمة المرور: Admin@1234

## تشغيل Queue
```bash
php artisan queue:work redis --queue=default
```
"""

# ─── بناء الملفات ──────────────────────────────────────────────────────────
def build():
    created = 0
    for path, content in files.items():
        full = os.path.join(BASE, path)
        os.makedirs(os.path.dirname(full), exist_ok=True)
        with open(full, "w", encoding="utf-8") as f:
            f.write(content.lstrip("\n"))
        created += 1
        print(f"  ✓  {path}")

    print(f"\n{'─'*50}")
    print(f"  تم إنشاء {created} ملف في مجلد '{BASE}/'")
    print(f"  اتبع خطوات README.md للإطلاق")
    print(f"{'─'*50}")

if __name__ == "__main__":
    build()
