<?php

use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
// Note: Image processing requires intervention/image package
use App\Models\User;
use App\Models\Setting;
use App\Models\Merchant;
use App\Models\Subscription;

/**
 * Validate email
 * 
 * @param string $identifier
 * @return bool
 */
function validate_email(string $identifier): bool
{
    return filter_var($identifier, FILTER_VALIDATE_EMAIL) !== false;
}

/**
 * Validate phone
 * 
 * @param string $identifier
 * @return bool
 */
function validate_phone(string $identifier): bool
{
    return preg_match('/^\+243[0-9]{9}$/', $identifier) === 1;
}

/**
 * Validate password
 * 
 * @param string $password
 * @return bool
 */
function validate_password(string $password): bool
{
    // Password must be at least 8 characters long
    // Password must contain at least one uppercase letter
    // Password must contain at least one lowercase letter
    // Password must contain at least one number
    // Password must contain at least one special character
    return preg_match(
        '/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*(),.?":{}|<>])[A-Za-z\d!@#$%^&*(),.?":{}|<>]{8,}$/',
        $password
    ) === 1;
}

/**
 * Get count of "en attente" prescriptions from the local database
 * 
 * @return int
 */
function getEnAttentePrescriptionsCount(): int
{
    try {
        // Try to get count from API
        $response = getHttpClient(true)->get(config('app.api_url').'/merchants/orders/pending-count');
        
        if ($response->successful()) {
            $data = $response->json();
            return (int) ($data['pending_orders_count'] ?? 0);
        }
        
        // If API fails, return 0 to not block the app
        return 0;
    } catch (\Illuminate\Http\Client\ConnectionException $e) {
        // Connection error - return 0 silently
        Log::debug('Failed to fetch pending prescriptions count (connection error)', [
            'error' => $e->getMessage(),
        ]);
        return 0;
    } catch (\Exception $e) {
        // Any other error - return 0 silently
        Log::debug('Failed to fetch pending prescriptions count', [
            'error' => $e->getMessage(),
            'type' => get_class($e),
        ]);
        return 0;
    }
}




/**
 * Get settings
 * 
 * @param string|null $key
 * @return mixed
 */
function settings(?string $key = null): mixed
{
    try {
        $settings = Setting::first();
        if (!$settings) {
            return null;
        }
        if ($key) {
            return $settings->$key ?? null;
        } else {
            return $settings;
        }
    } catch (\Exception $e) {
        // If database is not ready, return null instead of crashing
        Log::error('Settings function error: ' . $e->getMessage());
        return null;
    }
}


/**
 * Upload photo
 * @param mixed $photo
 * @param mixed $model
 * @param string $folderName
 * @param int|null $width
 * @param int|null $height
 * @param string $columnName
 * @return array
 */
function upload_photo($photo, $model, string $folderName, ?int $width = null, ?int $height = null, string $columnName = 'photo_path'): array
{
    try {
        // 1) If there is already a photo on disk, delete it
        if ($model->$columnName) {
            $oldFullPath = storage_path('app/public/'.$model->$columnName);
            if (file_exists($oldFullPath)) {
                unlink($oldFullPath);
            }
        }

        // 2) Grab the uploaded file
        $file = $photo;

        // 3) File name and folder
        $extension = 'webp';
        $imageName = time().'_'.uniqid().'.'.$extension;
        $fullPath = storage_path('app/public/'.$folderName);

        // 4) Create directory if it doesn't exist
        if (! file_exists($fullPath)) {
            mkdir($fullPath, 0755, true);
        }

        // 5) Store the file into storage/app/public/$folder
        // Note: This requires intervention/image package
        // For now, just move the file without processing
        $file->move($fullPath, $imageName);

        // 6) Update the database with that relative path
        $model->update([
            $columnName => '/storage/'.$folderName.'/'.$imageName,
        ]);

        return ['status' => true, 'message' => 'Photo uploaded successfully'];
    } catch (\Exception $e) {
        return ['status' => false, 'message' => $e->getMessage()];
    }
}

/**
 * Delete photo
 * @param string|null $photo_path
 * @param mixed $model
 * @param string $columnName
 * @return array
 */
function delete_photo(?string $photo_path, $model, string $columnName = 'photo_path'): array
{
    if (! $photo_path) {
        return ['status' => false, 'message' => 'No photo path provided.'];
    }

    // Build the full path to the file in the public disk
    $fullPath = public_path($photo_path);

    if (file_exists($fullPath)) {
        try {
            unlink($fullPath);
        } catch (\Exception $e) {
            return ['status' => false, 'message' => 'Error deleting file: '.$e->getMessage()];
        }
    }

    // Optionally update model column to null
    if ($model && $columnName && isset($model->$columnName)) {
        $model->update([
            $columnName => null,
        ]);
    }

    return ['status' => true, 'message' => 'Photo deleted successfully.'];
}

/**
 * Upload document
 * @param mixed $file
 * @param mixed $model
 * @param string $folderName
 * @param string $columnName
 * @return array
 */
function upload_document($file, $model, string $folderName, string $columnName = 'license_path'): array
{
    $validator = Validator::make(compact('file'), [
        'file' => 'required|file|mimes:pdf|max:10240',
    ]);

    if ($validator->fails()) {
        return ['status' => false, 'errors' => $validator->errors()];
    }

    try {
        // Delete old document if it exists
        if ($model->$columnName) {
            $oldFullPath = storage_path('app/public/'.$model->$columnName);
            if (file_exists($oldFullPath)) {
                unlink($oldFullPath);
            }
        }

        // Store new document
        $filename = time().'_'.uniqid().'.'.$file->getClientOriginalExtension();
        $path = $file->storeAs($folderName, $filename, 'public');

        // Attach to model
        $model->update([
            $columnName => '/storage/'.$path,
        ]);

        return ['status' => true, 'message' => 'Document uploaded successfully.'];
    } catch (\Exception $e) {
        return ['status' => false, 'message' => 'Upload failed: '.$e->getMessage()];
    }
}

/**
 * Delete document
 * @param mixed $model
 * @param string $columnName
 * @return array
 */
function delete_document($model, string $columnName = 'license_path'): array
{
    if (! $model || ! $model->$columnName) {
        return ['status' => false, 'message' => 'No document found.'];
    }

    try {
        $document = $model->$columnName;
        $storagePath = str_replace('/storage/', '', $document);
        if (Storage::disk('public')->exists($storagePath)) {
            Storage::disk('public')->delete($storagePath);
        }
        $model->update([$columnName => null]);

        return ['status' => true, 'message' => 'Document deleted successfully.'];
    } catch (\Exception $e) {
        return ['status' => false, 'message' => 'Delete failed: '.$e->getMessage()];
    }
}


function generate_avatar_data(string $name): array
{
    $initials = collect(explode(' ', $name))
        ->map(fn ($part) => strtoupper(mb_substr($part, 0, 1)))
        ->take(2)
        ->implode('');

    // List of soft professional colors
    $colors = [
        '#16A34A',
        '#0EA5E9',
        '#F59E0B',
        '#8B5CF6',
        '#EF4444',
        '#14B8A6',
        '#D946EF',
        '#6366F1',
        '#10B981',
        '#EA580C',
    ];

    // Deterministic color by hashing the name
    $color = $colors[crc32($name) % count($colors)];

    return [
        'initials' => $initials,
        'color' => $color,
    ];
}

/**
 * Truncate text
 * @param string $text
 * @param int $length_before
 * @param int $length_after
 * @return string
 */
function truncate_text(string $text, int $length_before = 10, int $length_after = 10): string
{
    $length = strlen($text);
    if ($length > $length_before + $length_after) {
        return substr($text, 0, $length_before).'...'.substr($text, -$length_after);
    }

    return $text;
}

/**
 * Format currency
 * @param mixed $amount
 * @param string $currency
 * @param string $locale
 * @return string
 */
function format_currency($amount, string $currency = 'USD', string $locale = 'fr_FR'): string
{
    if ($amount === null || $amount === '') {
        return '0,00 $';
    }

    // Convert to float if it's a string
    $amount = floatval($amount);

    // Format for French locale (comma as decimal separator, space as thousands separator)
    $formatted = number_format($amount, 2, ',', ' ');

    // Add currency symbol
    switch (strtoupper($currency)) {
        case 'USD':
            return $formatted.' $';
        case 'EUR':
            return $formatted.' €';
        case 'CDF':
            return $formatted.' FC';
        default:
            return $formatted.' '.$currency;
    }
}

/**
 * Get setting instance
 * @return mixed
 */
function setting(): mixed
{
    return Setting::instance();
}

/**
 * Get owner user
 * @return User|null
 */
function getOwner(): ?User
{
    return User::where('role', 'owner')->first();
}

/**
 * Check if user has active subscription
 * @return bool|null
 */
function has_active_subscription(): ?bool
{
    $owner = getOwner();

    if (!$owner) {
        return null;
    }

    try {
        $response = Http::withHeaders([
            'Authorization' => 'Bearer ' . session('auth_token'),
        ])->get(config('app.api_url') . '/subscriptions/' . $owner->slug . '/current-subscription');

        if ($response->successful()) {
            $data = $response->json();
            if ($data['success'] == false) {
                return null;
            }
            if ($data['has_active_subscription'] == true && $data['subscription']) {
                Subscription::updateOrCreate(
                    ['slug' => $data['subscription']['slug']],
                    [
                        'start_date' => $data['subscription']['start_date'],
                        'end_date' => $data['subscription']['end_date'],
                        'duration_in_days' => $data['subscription']['duration_days'],
                        'category' => $data['subscription']['category'],
                        'code' => $data['subscription']['code'],
                        'allowed_merchant_types' => $data['subscription']['allowed_merchant_types'],
                        'max_merchants' => $data['subscription']['max_merchants'],
                        'max_members_per_merchant' => $data['subscription']['max_members_per_merchant'],
                        'status' => $data['subscription']['status'],
                    ],
                );
            }

            return true;
        }
    } catch (\Exception $e) {
        return null;
    }

    return null;
}

/**
 * Check if has local active subscription
 * @return bool
 */
function has_local_active_subscription(): bool
{
    return Subscription::active()->exists();
}

/**
 * Get local active subscription
 * @return Subscription|null
 */
function get_local_active_subscription(): ?Subscription
{
    return Subscription::active()->first();
}

/**
 * Get local active subscription max merchants
 * @return int
 */
function get_local_active_subscription_max_merchants(): int
{
    $subscription = get_local_active_subscription();
    if (!$subscription) {
        return 0;
    }

    return $subscription->max_merchants;
}

/**
 * Get local active subscription allowed merchant types
 * @return \Illuminate\Support\Collection
 */
function get_local_active_subscription_allowed_merchant_types(): \Illuminate\Support\Collection
{
    $subscription = get_local_active_subscription();
    if (!$subscription) {
        return collect([]);
    }

    return collect($subscription->allowed_merchant_types)->map(function ($type) {
        return (object) [
            'id' => Str::slug($type),
            'name' => ucfirst($type),
        ];
    });
}

/**
 * Check if current user is owner
 * @return bool
 */
function is_owner(): bool
{
    $user = Auth::user();
    return $user && $user->role == 'owner';
}

/**
 * Check if current user is owner of merchant
 * @param mixed $merchant
 * @return bool
 */
function is_owner_of_merchant($merchant): bool
{
    $user = Auth::user();
    return $user && $user->id == $merchant->owner_id;
}

/**
 * Check if current user is owner of merchant or admin
 * @param mixed $merchant
 * @return bool
 */
function is_owner_of_merchant_or_admin($merchant): bool
{
    $user = Auth::user();
    return $user && ($user->id == $merchant->owner_id || $user->role == 'admin');
}

/**
 * Check if current user is admin
 * @return bool
 */
function is_admin(): bool
{
    $user = Auth::user();
    return $user && $user->role == 'admin';
}

/**
 * Sync merchants from API to local database
 *
 * @return array Returns sync results with counts and any errors
 */
/**
 * Sync merchants debug
 * @return array
 */
function sync_merchants_debug(): array
{
    // Simple test version - just return success without doing anything
    return [
        'success' => true,
        'synced' => 0,
        'skipped' => 0,
        'errors' => 0,
        'error_messages' => [],
        'total_processed' => 0,
    ];
}

/**
 * Get dashboard stats
 * @return array
 */
function getStats(): array
{
    $total_sales_today = \App\Models\Sale::whereDate('created_at', now()->today())->sum('total_amount');
    $total_pending_debts = \App\Models\Debt::where('status', \App\Models\Debt::STATUS_PENDING)->count();
    $total_products_low_stock = \App\Models\Product::whereColumn('current_stock', '<=', 'reorder_level')->count();
    $total_expenses_today = \App\Models\Expense::whereDate('created_at', now()->today())
        ->whereIn('status', [\App\Models\Expense::STATUS_APPROVED])
        ->sum('amount');

    return [
        [
            'title' => 'Ventes',
            'count' => number_format($total_sales_today),
            'subtitle' => 'aujourd\'hui',
            'change' => '', // You can add monthly change logic
            'trend' => 'up',
            'color' => 'green',
            'icon' => 'ph-shopping-cart',
            'link' => route('sales.index'),
        ],
        [
            'title' => 'Dettes',
            'count' => number_format($total_pending_debts),
            'subtitle' => 'en attente',
            'change' => '',
            'trend' => 'down',
            'color' => 'indigo',
            'icon' => 'ph-credit-card',
            'link' => route('debts.index'),
        ],
        [
            'title' => 'Stock Faible',
            'count' => number_format($total_products_low_stock),
            'subtitle' => 'à réapprovisionner',
            'change' => '',
            'trend' => 'down',
            'color' => 'red',
            'icon' => 'ph-warning',
            'link' => route('products.index'),
        ],
        [
            'title' => 'Dépenses',
            'count' => number_format($total_expenses_today),
            'subtitle' => 'aujourd\'hui',
            'change' => '',
            'trend' => 'up',
            'color' => 'yellow',
            'icon' => 'ph-receipt',
            'link' => route('expenses.index'),
        ],
    ];
}

/**
 * Get sales chart data
 * @return array
 */
function getSalesChart(): array
{
    $currentMonth = now();
    $daysInMonth = $currentMonth->daysInMonth;
    $dailySales = collect();

    for ($day = 1; $day <= $daysInMonth; $day++) {
        $date = $currentMonth->copy()->day($day);
        $dailySales->push([
            'day' => $date->format('d'),
            'total' => \App\Models\Sale::whereYear('created_at', $date->year)
                ->whereMonth('created_at', $date->month)
                ->whereDay('created_at', $date->day)
                ->sum('total_amount'),
        ]);
    }

    return [
        'labels' => $dailySales->pluck('day'),
        'data' => $dailySales->pluck('total'),
    ];
}

/**
 * Get weekly financial chart data
 * @return array
 */
function getWeeklyFinancialChart(): array
{
    $weeklyData = collect();
    // Get sales and expenses for the last 7 days
    for ($i = 6; $i >= 0; $i--) {
        $date = now()->subDays($i);

        $dailySales = \App\Models\Sale::whereDate('created_at', $date->format('Y-m-d'))
            ->sum('total_amount');

        $dailyExpenses = \App\Models\Expense::whereDate('created_at', $date->format('Y-m-d'))
            ->whereIn('status', [\App\Models\Expense::STATUS_APPROVED])
            ->sum('amount');

        $weeklyData->push([
            'day' => $date->format('D'), // Day abbreviation (Mon, Tue, etc.)
            'date' => $date->format('d/m'), // Date format
            'sales' => $dailySales,
            'expenses' => $dailyExpenses,
        ]);
    }

    return [
        'labels' => $weeklyData->pluck('date'),
        'sales_data' => $weeklyData->pluck('sales'),
        'expenses_data' => $weeklyData->pluck('expenses'),
    ];
}

/**
 * Get payment methods chart data
 * @return array
 */
function getPaymentMethodsChart(): array
{
    $paymentMethods = \App\Models\PaymentMethod::withCount(['sales as total_amount' => function ($query) {
        $query->select(\Illuminate\Support\Facades\DB::raw('COALESCE(SUM(total_amount), 0)'));
    }])->get();

    // Filter out payment methods with no sales
    $paymentMethods = $paymentMethods->filter(function ($method) {
        return $method->total_amount > 0;
    });

    return [
        'labels' => $paymentMethods->pluck('name'),
        'data' => $paymentMethods->pluck('total_amount'),
    ];
}

/**
 * Get recent sales
 * @return \Illuminate\Database\Eloquent\Collection
 */
function getRecentSales(): \Illuminate\Database\Eloquent\Collection
{
    return \App\Models\Sale::with('customer')->latest()->take(5)->get();
}

/**
 * Get top products
 * @return \Illuminate\Database\Eloquent\Collection
 */
function getTopProducts(): \Illuminate\Database\Eloquent\Collection
{
    return \App\Models\Product::with('category')->orderByDesc('current_stock')->take(5)->get();
}

/**
 * Get recent prescriptions
 * @return \Illuminate\Database\Eloquent\Collection
 */
function getRecentPrescriptions(): \Illuminate\Database\Eloquent\Collection
{
    return \App\Models\Order::with('customer')->latest()->take(5)->get();
}


/**
 * Check if merchant is active
 * @return bool
 */
function isMerchantActive(): bool
{
    if (! $settings = settings()) {
        return false;
    }

    return $settings->merchant_status == Merchant::STATUS_ACTIVE;
}

/**
 * Check if all required fields are filled
 * @return array
 */
function hasAllRequiredFields(): array
{
    $settings = settings();
    if (! $settings) {
        return ['success' => false, 'message' => 'Les paramètres de la pharmacie sont requis'];
    }

    if (! $settings->merchant_name) {
        return ['success' => false, 'message' => 'Le nom de la pharmacie est requis'];
    } elseif (! $settings->merchant_slug) {
        return ['success' => false, 'message' => 'Le slug de la pharmacie est requis'];
    } elseif (! $settings->merchant_phone) {
        return ['success' => false, 'message' => 'Le numéro de téléphone de la pharmacie est requis'];
    } elseif (! $settings->merchant_type) {
        return ['success' => false, 'message' => 'Le type de la pharmacie est requis'];
    } elseif (! $settings->merchant_province_id) {
        return ['success' => false, 'message' => 'La province de la pharmacie est requis'];
    } elseif (! $settings->merchant_city_id) {
        return ['success' => false, 'message' => 'La ville de la pharmacie est requis'];
    } elseif (! $settings->merchant_latitude) {
        return ['success' => false, 'message' => 'La latitude de la pharmacie est requis'];
    } elseif (! $settings->merchant_longitude) {
        return ['success' => false, 'message' => 'La longitude de la pharmacie est requis'];
    } else {
        return ['success' => true, 'message' => 'Tous les champs requis sont remplis'];
    }
}


/**
 * Get the current setup status
 * @return array
 */
function getSetupStatus(): array
{
    return [
        'is_first_launch' => isFirstLaunch(),
        'is_merchant_setup_complete' => isMerchantSetupComplete(),
        'user_count' => \App\Models\User::count(),
        'settings_count' => \App\Models\Setting::count(),
    ];
}

/**
 * Get "En attente" prescription numbers from the local database
 * @return \Illuminate\Support\Collection
 */
function getEnAttentePrescriptionNumbers(): \Illuminate\Support\Collection
{
    return \App\Models\Prescription::where('status', 'En attente')->pluck('reference');
}

