<?php

namespace App\Services;

use App\Models\Company;
use App\Models\PortalUser;
use Illuminate\Database\QueryException;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Validation\ValidationException;

class CompanyService
{
    public function __construct(
        private readonly PortalUserService $portalUserService
    ) {}

    /**
     * Create a new company along with its first company admin.
     *
     * @param array $data Should contain:
     *   - company_name: The name of the company
     *   - company_email: The email of the company
     *   - recipient_email: (optional) Custom email to send invitation to (not saved to DB)
     */
    public function createCompanyWithAdmin(array $data): Company
    {
        try {
            // First: Create company and portal user in a transaction
            $result = DB::transaction(function () use ($data) {
                // Create the company
                $company = Company::create([
                    'name' => $data['company_name'],
                    'email' => $data['company_email'],
                    'status' => 'active',
                ]);

                // Create the company admin portal user (using company details)
                $portalUser = PortalUser::create([
                    'name' => $data['company_name'],
                    'email' => $data['company_email'],
                    'role' => 'company_admin',
                    'company_id' => $company->id,
                    'employee_id' => null,
                    'password' => null,
                ]);

                return ['company' => $company, 'portalUser' => $portalUser];
            });

            // Second: Send invitation email AFTER transaction commits successfully
            // This prevents sending emails for failed/rolled-back transactions
            try {
                // Use recipient_email if provided, otherwise use portal user's email
                $recipientEmail = $data['recipient_email'] ?? null;
                $this->portalUserService->sendInvitation($result['portalUser'], $recipientEmail);
            } catch (\Exception $e) {
                // Log email failure but don't rollback since transaction already committed
                Log::error('Failed to send invitation email after company creation: ' . $e->getMessage(), [
                    'company_id' => $result['company']->id,
                    'portal_user_id' => $result['portalUser']->id,
                    'exception' => $e,
                ]);
                // Email can be resent later via resend-invitation endpoint
            }

            return $result['company']->fresh(['portalUsers']);
        } catch (QueryException $e) {
            // Check for duplicate entry error
            if ($e->getCode() === '23000' && str_contains($e->getMessage(), 'Duplicate entry')) {
                throw ValidationException::withMessages([
                    'company_email' => ['This email is already registered.'],
                ]);
            }
            Log::error('QueryException in createCompanyWithAdmin: ' . $e->getMessage(), ['exception' => $e]);
            throw $e;
        } catch (\Exception $e) {
            Log::error('Exception in createCompanyWithAdmin: ' . $e->getMessage(), ['exception' => $e]);
            throw $e;
        }
    }

    /**
     * Get all companies with their admin count (paginated).
     */
    public function getAllCompanies(int $perPage = 15)
    {
        return Company::withCount('portalUsers')
            ->orderBy('created_at', 'desc')
            ->paginate($perPage);
    }

    /**
     * Get a specific company with its admins and employee count.
     */
    public function getCompanyDetails(Company $company)
    {
        return $company->load(['portalUsers' => function ($query) {
            $query->where('role', 'company_admin');
        }])->loadCount('employees');
    }

    /**
     * Load the company profile for the full-profile endpoint.
     *
     * Returns admins, employee stats (counts only), and the last 10 employees.
     * No full employee details, beneficiaries, NIN data, or KYC submissions.
     */
    public function getFullCompanyProfile(Company $company): array
    {
        $admins = $company->portalUsers()
            ->where('role', 'company_admin')
            ->orderBy('created_at')
            ->get();

        $stats = [
            'total'             => $company->employees()->count(),
            'active'            => $company->employees()->where('employment_status', 'active')->count(),
            'inactive'          => $company->employees()->where('employment_status', 'inactive')->count(),
            'terminated'        => $company->employees()->where('employment_status', 'terminated')->count(),
            'nin_verified'      => $company->employees()->where('is_nin_verified', true)->count(),
            'no_portal_access'  => $company->employees()->whereNull('portal_user_id')->count(),
            'invitation_sent'   => $company->employees()
                ->whereNotNull('portal_user_id')
                ->whereHas('portalUser', fn ($q) => $q->whereNull('password_set_at'))
                ->count(),
            'password_set'      => $company->employees()
                ->whereNotNull('portal_user_id')
                ->whereHas('portalUser', fn ($q) => $q->whereNotNull('password_set_at'))
                ->count(),
        ];

        $recentEmployees = $company->employees()
            ->orderByDesc('created_at')
            ->limit(10)
            ->get(['id', 'first_name', 'last_name', 'email', 'position', 'hire_date', 'created_at']);

        return compact('admins', 'stats', 'recentEmployees');
    }
}
