<?php

namespace Modules\PMCore\App\Services;

use App\Helpers\CurrencyHelper;
use App\Helpers\FormattingHelper;
use Modules\CRMCore\App\Models\Company;
use Modules\SystemCore\App\Models\CoreCustomer;
use Nwidart\Modules\Facades\Module;

class PMIntegrationService
{
    /**
     * Check if CRMCore module is available.
     */
    public function isCRMCoreAvailable(): bool
    {
        return Module::isEnabled('CRMCore');
    }

    /**
     * Check if TaskSystem module is available.
     */
    public function isTaskSystemAvailable(): bool
    {
        return Module::isEnabled('TaskSystem');
    }

    /**
     * Check if AccountingCore module is available.
     */
    public function isAccountingCoreAvailable(): bool
    {
        return Module::isEnabled('AccountingCore');
    }

    /**
     * Get available clients for project assignment.
     * Uses CoreCustomer from SystemCore (always available).
     */
    public function getAvailableClients()
    {
        return CoreCustomer::where('is_active', true)
            ->select('id', 'name', 'email', 'phone')
            ->orderBy('name')
            ->get();
    }

    /**
     * Get available companies for project assignment.
     */
    public function getAvailableCompanies()
    {
        if (! $this->isCRMCoreAvailable()) {
            return collect();
        }

        return Company::active()
            ->select('id', 'name', 'email', 'phone')
            ->orderBy('name')
            ->get();
    }

    /**
     * Get project managers (users with PM role).
     */
    public function getProjectManagers()
    {
        return \App\Models\User::employeesOnly()
            ->where(function ($q) {
                $q->whereHas('roles', function ($query) {
                    $query->where('name', 'project_manager');
                })->orWhereHas('roles', function ($query) {
                    $query->where('name', 'admin');
                });
            })
            ->select('id', 'name', 'email')
            ->orderBy('name')
            ->get();
    }

    /**
     * Get available team members.
     */
    public function getAvailableTeamMembers()
    {
        return \App\Models\User::active()
            ->select('id', 'name', 'email', 'designation')
            ->orderBy('name')
            ->get();
    }

    /**
     * Get project tasks count.
     * Uses polymorphic relationship to TaskSystem.
     */
    public function getProjectTasksCount($projectId): int
    {
        if (! $this->isTaskSystemAvailable()) {
            return 0;
        }

        try {
            $project = \Modules\PMCore\App\Models\Project::find($projectId);

            return $project ? $project->tasks()->count() : 0;
        } catch (\Exception $e) {
            return 0;
        }
    }

    /**
     * Get project completed tasks count.
     * Uses polymorphic relationship to TaskSystem.
     */
    public function getProjectCompletedTasksCount($projectId): int
    {
        if (! $this->isTaskSystemAvailable()) {
            return 0;
        }

        try {
            $project = \Modules\PMCore\App\Models\Project::find($projectId);

            return $project ? $project->completedTasks()->count() : 0;
        } catch (\Exception $e) {
            return 0;
        }
    }

    /**
     * Get project progress percentage.
     */
    public function getProjectProgress($projectId): float
    {
        $totalTasks = $this->getProjectTasksCount($projectId);
        if ($totalTasks === 0) {
            return 0;
        }

        $completedTasks = $this->getProjectCompletedTasksCount($projectId);

        return round(($completedTasks / $totalTasks) * 100, 2);
    }

    /**
     * Get project budget information.
     */
    public function getProjectBudgetInfo($projectId)
    {
        if (! $this->isAccountingCoreAvailable()) {
            return [
                'total_budget' => 0,
                'spent_amount' => 0,
                'remaining_budget' => 0,
                'budget_utilization' => 0,
            ];
        }

        // This would integrate with AccountingCore for actual budget tracking
        // For now, return default values
        return [
            'total_budget' => 0,
            'spent_amount' => 0,
            'remaining_budget' => 0,
            'budget_utilization' => 0,
        ];
    }

    /**
     * Get currency symbol for display.
     * Uses global settings currency or falls back to CurrencyHelper.
     */
    public function getCurrencySymbol(?string $currencyCode = null): string
    {
        if ($currencyCode) {
            return CurrencyHelper::getCurrencySymbol($currencyCode);
        }

        return FormattingHelper::getCurrentCurrencySymbol();
    }

    /**
     * Get currency code from settings.
     */
    public function getCurrencyCode(): string
    {
        return FormattingHelper::getCurrentCurrencyCode();
    }

    /**
     * Format currency amount.
     * Uses FormattingHelper for consistent formatting across the application.
     *
     * @param  float|int|string  $amount  The amount to format
     * @param  string|null  $currencyCode  Optional currency code (e.g., 'USD', 'EUR')
     */
    public function formatCurrency($amount, ?string $currencyCode = null): string
    {
        if ($currencyCode) {
            return FormattingHelper::formatCurrencyWithCurrency($amount, $currencyCode);
        }

        return FormattingHelper::formatCurrency($amount);
    }

    /**
     * Get all available currencies for dropdowns.
     *
     * @return array<string, string> Currency options [code => label]
     */
    public function getAvailableCurrencies(): array
    {
        return CurrencyHelper::getCurrencyOptions();
    }

    /**
     * Get currency details by code.
     *
     * @return array{name: string, symbol: string}|null
     */
    public function getCurrencyDetails(string $currencyCode): ?array
    {
        $currencies = CurrencyHelper::getAllCurrencies();

        return $currencies[$currencyCode] ?? null;
    }

    /**
     * Convert amount between currencies.
     * Note: Requires MultiCurrency module for actual conversion rates.
     * Without it, returns the original amount.
     */
    public function convertCurrency(float $amount, string $fromCurrency, string $toCurrency): float
    {
        return FormattingHelper::convertCurrency($amount, $fromCurrency, $toCurrency);
    }

    /**
     * Check if user can manage projects.
     */
    public function canManageProjects($user = null): bool
    {
        $user = $user ?: auth()->user();

        return $user->hasRole(['admin', 'project_manager']) ||
               $user->hasPermissionTo('manage_projects');
    }

    /**
     * Check if user can view project.
     */
    public function canViewProject($projectId, $user = null): bool
    {
        $user = $user ?: auth()->user();

        if ($this->canManageProjects($user)) {
            return true;
        }

        // Check if user is a project member
        return \Modules\PMCore\App\Models\ProjectMember::where('project_id', $projectId)
            ->where('user_id', $user->id)
            ->exists();
    }

    /**
     * Get project statistics.
     */
    public function getProjectStats()
    {
        $stats = [
            'total_projects' => \Modules\PMCore\App\Models\Project::count(),
            'active_projects' => \Modules\PMCore\App\Models\Project::where('status', \Modules\PMCore\App\Enums\ProjectStatus::IN_PROGRESS->value)->count(),
            'completed_projects' => \Modules\PMCore\App\Models\Project::where('status', \Modules\PMCore\App\Enums\ProjectStatus::COMPLETED->value)->count(),
            'overdue_projects' => \Modules\PMCore\App\Models\Project::where('end_date', '<', now())
                ->whereNotIn('status', [\Modules\PMCore\App\Enums\ProjectStatus::COMPLETED->value, \Modules\PMCore\App\Enums\ProjectStatus::CANCELLED->value])
                ->count(),
        ];

        return $stats;
    }

    /**
     * Get filter data for project lists.
     */
    public function getFilterData()
    {
        return [
            'statuses' => \Modules\PMCore\App\Enums\ProjectStatus::cases(),
            'types' => \Modules\PMCore\App\Enums\ProjectType::cases(),
            'priorities' => \Modules\PMCore\App\Enums\ProjectPriority::cases(),
            'project_managers' => $this->getProjectManagers(),
            'clients' => $this->getAvailableClients(),
            'companies' => $this->getAvailableCompanies(),
        ];
    }
}
