<?php

namespace App\Services;

use App\Models\HealthMarketorApplication;
use App\Models\MembershipApplication;
use App\Models\MembershipCategory;
use App\Models\Mentorship\Application as MentorshipApplication;
use App\Models\RPartner;
use App\Models\RPartnerContact;
use App\Models\TrainerApplication;
use App\Models\User;
use App\Models\UserProfile;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Log;

class RoleRegistrationService
{
    public function __construct(
        protected NotificationService $notificationService,
        protected RegistrationService $registrationService
    ) {}

    // -------------------------------------------------------------------------
    // Registration Methods
    // -------------------------------------------------------------------------

    /**
     * Register a new Member applicant.
     * Creates User (is_active=false) + MembershipApplication (pending).
     */
    public function registerMember(array $data): MembershipApplication
    {
        return DB::transaction(function () use ($data) {
            $user = $this->createUser($data, isActive: false);

            $category = MembershipCategory::findOrFail($data['membership_category_id']);

            $application = MembershipApplication::create([
                'reference_number'       => MembershipApplication::generateReferenceNumber(),
                'user_id'                => $user->id,
                'membership_category_id' => $category->id,
                'applicant_data'         => [],
                'first_name'             => $data['first_name'],
                'last_name'              => $data['last_name'],
                'email'                  => $data['email'],
                'phone'                  => $data['phone'] ?? null,
                'address'                => $data['address'] ?? null,
                'city'                   => $data['city'] ?? null,
                'country'                => $data['country'] ?? null,
                'occupation'             => $data['occupation'] ?? null,
                'organization'           => $data['organization'] ?? null,
                'professional_background'=> $data['professional_background'] ?? null,
                'status'                 => 'pending',
                'payment_required'       => (bool) $category->activeSubscriptionFee(),
                'payment_completed'      => false,
            ]);

            $this->sendApplicationConfirmationEmail($application->email, $application->full_name, $application->reference_number, 'Member');

            Log::info('Member registration submitted', ['user_id' => $user->id, 'reference' => $application->reference_number]);

            return $application;
        });
    }

    /**
     * Register a new Trainer applicant.
     * Creates User (is_active=false) + TrainerApplication (pending).
     */
    public function registerTrainer(array $data, ?object $cvFile = null): TrainerApplication
    {
        return DB::transaction(function () use ($data, $cvFile) {
            $user = $this->createUser($data, isActive: false);

            $cvPath = null;
            if ($cvFile) {
                $cvPath = $cvFile->store('trainer-applications', 'private');
            }

            // Remove the file key from data array before passing to model create
            unset($data['cv']);

            $application = TrainerApplication::create([
                'reference_number'   => TrainerApplication::generateReferenceNumber(),
                'user_id'            => $user->id,
                'first_name'         => $data['first_name'],
                'last_name'          => $data['last_name'],
                'email'              => $data['email'],
                'phone'              => $data['phone'] ?? null,
                'address'            => $data['address'] ?? null,
                'city'               => $data['city'] ?? null,
                'country'            => $data['country'] ?? null,
                'professional_title' => $data['professional_title'] ?? null,
                'specialization'     => $data['specialization'] ?? null,
                'years_of_experience'=> $data['years_of_experience'] ?? null,
                'certifications'     => $data['certifications'] ?? null,
                'bio'                => $data['bio'] ?? null,
                'expertise_areas'    => $data['expertise_areas'] ?? [],
                'availability'       => $data['availability'] ?? null,
                'cv_path'            => $cvPath,
                'status'             => TrainerApplication::STATUS_PENDING,
                'terms_accepted'     => (bool) ($data['terms_accepted'] ?? false),
            ]);

            $this->sendApplicationConfirmationEmail($application->email, $application->full_name, $application->reference_number, 'Trainer');

            Log::info('Trainer registration submitted', ['user_id' => $user->id, 'reference' => $application->reference_number]);

            return $application;
        });
    }

    /**
     * Register a new Trainee.
     * Instant-access: creates User (is_active=true), assigns Trainees role, creates UserProfile.
     */
    public function registerTrainee(array $data): User
    {
        return DB::transaction(function () use ($data) {
            $user = $this->createUser($data, isActive: true, nameField: 'name');

            $user->assignRole('Trainees');

            UserProfile::create([
                'user_id'        => $user->id,
                'address'        => $data['address'] ?? null,
                'city'           => $data['city'] ?? null,
                'country'        => $data['country'] ?? null,
                'experience_level' => $data['education_level'] ?? null,
                'learning_goals' => $data['learning_goals'] ?? null,
                'availability'   => $data['availability'] ?? null,
                'role_specific_data' => [
                    'areas_of_interest' => $data['areas_of_interest'] ?? [],
                    'current_occupation'=> $data['current_occupation'] ?? null,
                ],
            ]);

            Log::info('Trainee registered instantly', ['user_id' => $user->id]);

            return $user;
        });
    }

    /**
     * Register a new Mentor applicant.
     * Creates User (is_active=false) + mentorship_applications (role_preference=mentor, pending).
     */
    public function registerMentor(array $data): MentorshipApplication
    {
        return DB::transaction(function () use ($data) {
            $user = $this->createUser($data, isActive: false, nameField: 'name');

            $application = MentorshipApplication::create([
                'user_id'              => $user->id,
                'name'                 => $data['name'],
                'email'                => $data['email'],
                'phone'                => $data['phone'] ?? null,
                'country'              => $data['country'] ?? null,
                'city'                 => $data['city'] ?? null,
                'occupation'           => $data['occupation'] ?? null,
                'organization'         => $data['organization'] ?? null,
                'education_level'      => $data['education_level'] ?? null,
                'bio'                  => $data['bio'] ?? null,
                'expertise_areas'      => $data['expertise_areas'] ?? [],
                'years_of_experience'  => $data['years_of_experience'] ?? null,
                'mentoring_experience' => $data['mentoring_experience'] ?? null,
                'availability'         => $data['availability'] ?? null,
                'motivation'           => $data['motivation'] ?? null,
                'category_id'          => $data['category_id'] ?? null,
                'role_preference'      => MentorshipApplication::ROLE_MENTOR,
                'status'               => MentorshipApplication::STATUS_PENDING,
                'terms_accepted'       => (bool) ($data['terms_accepted'] ?? false),
            ]);

            $this->sendApplicationConfirmationEmail($application->email, $application->name, null, 'Mentor');

            Log::info('Mentor registration submitted', ['user_id' => $user->id, 'application_id' => $application->id]);

            return $application;
        });
    }

    /**
     * Register a new Mentee applicant.
     * Creates User (is_active=false) + mentorship_applications (role_preference=mentee, pending).
     */
    public function registerMentee(array $data): MentorshipApplication
    {
        return DB::transaction(function () use ($data) {
            $user = $this->createUser($data, isActive: false, nameField: 'name');

            $application = MentorshipApplication::create([
                'user_id'                  => $user->id,
                'name'                     => $data['name'],
                'email'                    => $data['email'],
                'phone'                    => $data['phone'] ?? null,
                'country'                  => $data['country'] ?? null,
                'city'                     => $data['city'] ?? null,
                'occupation'               => $data['occupation'] ?? null,
                'education_level'          => $data['education_level'] ?? null,
                'bio'                      => $data['bio'] ?? null,
                'areas_of_interest'        => $data['areas_of_interest'] ?? [],
                'skills'                   => $data['skills'] ?? [],
                'learning_goals'           => $data['learning_goals'] ?? null,
                'preferred_mentor_qualities'=> $data['preferred_mentor_qualities'] ?? null,
                'time_commitment'          => $data['time_commitment'] ?? null,
                'motivation'               => $data['motivation'] ?? null,
                'category_id'              => $data['category_id'] ?? null,
                'role_preference'          => MentorshipApplication::ROLE_MENTEE,
                'status'                   => MentorshipApplication::STATUS_PENDING,
                'terms_accepted'           => (bool) ($data['terms_accepted'] ?? false),
            ]);

            $this->sendApplicationConfirmationEmail($application->email, $application->name, null, 'Mentee');

            Log::info('Mentee registration submitted', ['user_id' => $user->id, 'application_id' => $application->id]);

            return $application;
        });
    }

    /**
     * Register a new Partner applicant.
     * Creates User (is_active=false) + RPartner (pending) + RPartnerContact (primary).
     */
    public function registerPartner(array $data): RPartner
    {
        return DB::transaction(function () use ($data) {
            // Use the contact email as the login email
            $user = User::create([
                'name'     => $data['contact_name'],
                'email'    => $data['email'],
                'username' => User::generateUsername($data['email']),
                'password' => Hash::make($data['password']),
                'phone'    => $data['contact_phone'] ?? null,
                'is_active'=> false,
            ]);

            $partner = RPartner::create([
                'user_id'           => $user->id,
                'organization_name' => $data['organization_name'],
                'slug'              => RPartner::generateSlug($data['organization_name']),
                'legal_name'        => $data['legal_name'] ?? null,
                'description'       => $data['description'] ?? null,
                'mission_statement' => $data['mission_statement'] ?? null,
                'email'             => $data['email'],
                'phone'             => $data['phone'] ?? null,
                'website'           => $data['website'] ?? null,
                'address_line_1'    => $data['address'] ?? null,
                'city'              => $data['city'] ?? null,
                'country'           => $data['country'] ?? null,
                'organization_type' => $data['organization_type'],
                'services_offered'  => $data['services_offered'] ?? [],
                'partnership_status'=> RPartner::PARTNERSHIP_PENDING,
                'partnership_level' => RPartner::LEVEL_BRONZE,
                'show_in_directory' => false,
                'is_verified'       => false,
            ]);

            RPartnerContact::create([
                'partner_id' => $partner->id,
                'name'       => $data['contact_name'],
                'title'      => $data['contact_title'] ?? null,
                'email'      => $data['contact_email'],
                'phone'      => $data['contact_phone'] ?? null,
                'role'       => RPartnerContact::ROLE_PRIMARY_CONTACT,
                'is_primary' => true,
                'is_active'  => true,
            ]);

            $this->sendApplicationConfirmationEmail($data['email'], $data['contact_name'], null, 'Partner');

            Log::info('Partner registration submitted', ['user_id' => $user->id, 'partner_id' => $partner->id]);

            return $partner;
        });
    }

    /**
     * Register a new Contributor.
     * Instant-access: delegates to existing RegistrationService.
     */
    public function registerContributor(array $data): User
    {
        return $this->registrationService->registerContributor($data);
    }

    /**
     * Register a new Health Marketor applicant.
     * Creates User (is_active=false) + HealthMarketorApplication (pending).
     */
    public function registerHealthMarketor(array $data): HealthMarketorApplication
    {
        return DB::transaction(function () use ($data) {
            $user = $this->createUser($data, isActive: false);

            $application = HealthMarketorApplication::create([
                'reference_number'    => HealthMarketorApplication::generateReferenceNumber(),
                'user_id'             => $user->id,
                'first_name'          => $data['first_name'],
                'last_name'           => $data['last_name'],
                'email'               => $data['email'],
                'phone'               => $data['phone'] ?? null,
                'address'             => $data['address'] ?? null,
                'city'                => $data['city'] ?? null,
                'country'             => $data['country'] ?? null,
                'organization'        => $data['organization'] ?? null,
                'marketing_focus'     => $data['marketing_focus'] ?? [],
                'target_audience'     => $data['target_audience'] ?? null,
                'campaign_experience' => $data['campaign_experience'] ?? null,
                'years_of_experience' => $data['years_of_experience'] ?? null,
                'bio'                 => $data['bio'] ?? null,
                'social_media'        => array_filter([
                    'facebook'  => $data['facebook'] ?? null,
                    'twitter'   => $data['twitter'] ?? null,
                    'linkedin'  => $data['linkedin'] ?? null,
                    'instagram' => $data['instagram'] ?? null,
                ]),
                'status'          => HealthMarketorApplication::STATUS_PENDING,
                'terms_accepted'  => (bool) ($data['terms_accepted'] ?? false),
            ]);

            $this->sendApplicationConfirmationEmail($application->email, $application->full_name, $application->reference_number, 'Health Marketor');

            Log::info('Health Marketor registration submitted', ['user_id' => $user->id, 'reference' => $application->reference_number]);

            return $application;
        });
    }

    // -------------------------------------------------------------------------
    // Approval Methods
    // -------------------------------------------------------------------------

    /**
     * Approve a Trainer application.
     * Assigns Trainers role, activates user, creates/updates UserProfile.
     */
    public function approveTrainer(TrainerApplication $application, int $approvedBy): User
    {
        return DB::transaction(function () use ($application, $approvedBy) {
            $user = $application->user;

            $user->update(['is_active' => true]);
            $user->assignRole('Trainers');

            UserProfile::updateOrCreate(
                ['user_id' => $user->id],
                [
                    'bio'                => $application->bio,
                    'specialization'     => $application->specialization,
                    'experience_years'   => $application->years_of_experience,
                    'certification'      => $application->certifications,
                    'expertise_areas'    => $application->expertise_areas ? implode(', ', $application->expertise_areas) : null,
                    'availability'       => $application->availability,
                    'address'            => $application->address,
                    'city'               => $application->city,
                    'country'            => $application->country,
                ]
            );

            $application->approve($approvedBy);

            $this->sendApprovalEmail($user->email, $user->name, 'Trainer');

            Log::info('Trainer application approved', ['user_id' => $user->id, 'application_id' => $application->id]);

            return $user;
        });
    }

    /**
     * Approve a Partner application.
     * Assigns Partners role, activates user, updates RPartner status to active.
     */
    public function approvePartner(RPartner $partner, int $approvedBy): User
    {
        return DB::transaction(function () use ($partner, $approvedBy) {
            $user = $partner->user;

            $user->update(['is_active' => true]);
            $user->assignRole('Partners');

            $partner->update([
                'partnership_status'    => RPartner::PARTNERSHIP_ACTIVE,
                'partnership_start_date'=> now(),
                'is_verified'           => true,
                'verified_at'           => now(),
                'verified_by'           => $approvedBy,
                'show_in_directory'     => true,
            ]);

            $this->sendApprovalEmail($user->email, $user->name, 'Partner');

            Log::info('Partner application approved', ['user_id' => $user->id, 'partner_id' => $partner->id]);

            return $user;
        });
    }

    /**
     * Approve a Health Marketor application.
     * Assigns Health Marketor role, activates user, creates/updates UserProfile.
     */
    public function approveHealthMarketor(HealthMarketorApplication $application, int $approvedBy): User
    {
        return DB::transaction(function () use ($application, $approvedBy) {
            $user = $application->user;

            $user->update(['is_active' => true]);
            $user->assignRole('Health Marketor');

            UserProfile::updateOrCreate(
                ['user_id' => $user->id],
                [
                    'bio'                 => $application->bio,
                    'marketing_focus'     => $application->marketing_focus ? implode(', ', $application->marketing_focus) : null,
                    'target_audience'     => $application->target_audience,
                    'campaign_experience' => $application->campaign_experience,
                    'address'             => $application->address,
                    'city'                => $application->city,
                    'country'             => $application->country,
                    'linkedin'            => $application->social_media['linkedin'] ?? null,
                    'twitter'             => $application->social_media['twitter'] ?? null,
                    'facebook'            => $application->social_media['facebook'] ?? null,
                    'instagram'           => $application->social_media['instagram'] ?? null,
                ]
            );

            $application->approve($approvedBy);

            $this->sendApprovalEmail($user->email, $user->name, 'Health Marketor');

            Log::info('Health Marketor application approved', ['user_id' => $user->id, 'application_id' => $application->id]);

            return $user;
        });
    }

    // -------------------------------------------------------------------------
    // Private Helpers
    // -------------------------------------------------------------------------

    /**
     * Create a User record from registration data.
     * Supports both first_name/last_name and single name field.
     */
    private function createUser(array $data, bool $isActive, string $nameField = 'first_name'): User
    {
        if ($nameField === 'name') {
            $name = strip_tags($data['name']);
        } else {
            $name = trim(strip_tags($data['first_name']) . ' ' . strip_tags($data['last_name']));
        }

        return User::create([
            'name'      => $name,
            'email'     => $data['email'],
            'username'  => User::generateUsername($data['email']),
            'password'  => Hash::make($data['password']),
            'phone'     => $data['phone'] ?? null,
            'is_active' => $isActive,
        ]);
    }

    /**
     * Send a generic application confirmation email.
     */
    private function sendApplicationConfirmationEmail(string $email, string $name, ?string $referenceNumber, string $roleLabel): void
    {
        try {
            $subject = "Your {$roleLabel} Application Has Been Received";
            $body = "Dear {$name},\n\nThank you for applying to become a {$roleLabel} on the SSHIA platform. "
                . "Your application has been received and is currently under review.\n"
                . ($referenceNumber ? "Your reference number is: {$referenceNumber}\n" : '')
                . "\nWe will notify you once a decision has been made.\n\nThank you,\nThe SSHIA Team";

            $emailService = app(\App\Services\EmailService::class);
            if (method_exists($emailService, 'isReady') && $emailService->isReady()) {
                $emailService->sendTemplate(
                    $email,
                    $subject,
                    'emails.registration.application-received',
                    [
                        'name'            => $name,
                        'role'            => $roleLabel,
                        'referenceNumber' => $referenceNumber,
                    ]
                );
            }
        } catch (\Exception $e) {
            Log::warning("Failed to send {$roleLabel} application confirmation email", [
                'email' => $email,
                'error' => $e->getMessage(),
            ]);
        }
    }

    /**
     * Send an approval email to the user.
     */
    private function sendApprovalEmail(string $email, string $name, string $roleLabel): void
    {
        try {
            $emailService = app(\App\Services\EmailService::class);
            if (method_exists($emailService, 'isReady') && $emailService->isReady()) {
                $emailService->sendTemplate(
                    $email,
                    "Your {$roleLabel} Application Has Been Approved",
                    'emails.registration.application-approved',
                    [
                        'name'     => $name,
                        'role'     => $roleLabel,
                        'loginUrl' => route('login'),
                    ]
                );
            }
        } catch (\Exception $e) {
            Log::warning("Failed to send {$roleLabel} approval email", [
                'email' => $email,
                'error' => $e->getMessage(),
            ]);
        }
    }
}
