<?php

namespace App\Http\Controllers;

use App\Models\Bank;
use App\Models\Organization;
use App\Models\User;
use App\Traits\ActiveStatesTrait;
use App\Traits\LocationTrait;
use App\Traits\ProfilePermissionTrait;
use Illuminate\Http\Request;
use Mcamara\LaravelLocalization\Facades\LaravelLocalization;

class ProfileController extends Controller
{
    use ActiveStatesTrait;
    use LocationTrait;
    use ProfilePermissionTrait;



    public function show($type, $id)
    {
        if (strtolower($type) === strtolower(__('user'))) {
            return $this->showUser($id);
        }
        if (strtolower($type) === strtolower(__('organization'))) {
            return $this->showOrganization($id);
        }
        if (strtolower($type) === strtolower(__('bank'))) {
            return $this->showBank($id);
        }
        return view('profile.not_found');
    }


    public function showActive()
    {
        $profile = getActiveProfile();
        return $this->show(__(class_basename($profile)), $profile->id);
    }


    public function showUser($id)
    {
        $user = User::select([
            'id',
            'name',
            'full_name',
            'profile_photo_path',
            'about',
            'about_short',
            'motivation',
            'date_of_birth',
            'website',
            'phone_public',
            'phone',
            'cyclos_skills',
            'lang_preference',
            'email_verified_at',
            'created_at',
            'last_login_at',
            'love_reactant_id',
            'inactive_at',
            'deleted_at'
        ])
        ->with([
            'organizations:id,name,profile_photo_path',
            'accounts:id,name,accountable_type,accountable_id',
            'languages:id,name,lang_code,flag',
            'tags:tag_id',
            'socials:id,name,icon,urL_structure',
            'locations.district.translations:district_id,name',
            'locations.city.translations:city_id,name',
            'locations.division.translations:division_id,name',
            'locations.country.translations:country_id,name',
            'loveReactant.reactions.reacter.reacterable',
            'loveReactant.reactionCounters',
        ])
        ->find($id);

        if (!$user) {
            return view('profile.not_found');
        }

        $states = $this->getActiveStates($user);
        $canManageProfiles = $this->getCanManageProfiles();
        $canViewIncompleteProfiles = $this->canViewIncompleteProfiles();
        $isViewingOwnProfile = getActiveProfile() &&
                               get_class(getActiveProfile()) === User::class &&
                               getActiveProfile()->id === $user->id;

        // For admins/banks: Always show incomplete label if profile is incomplete (ignore config)
        if ($canManageProfiles) {
            $states['hidden'] = false;
            $states['inactiveLabel'] = !$user->isActive();
            $states['inactiveSince'] = $user->inactive_at
            ? \Illuminate\Support\Carbon::parse($user->inactive_at)->diffForHumans()
            : '';
            $states['emailUnverifiedLabel'] = !$user->isEmailVerified();
            $states['incompleteLabel'] = $user->hasIncompleteProfile($user);
        }

        // When viewing own profile, never hide but show all labels
        if ($isViewingOwnProfile) {
            $states['hidden'] = false;
            $states['inactiveLabel'] = !$user->isActive();
            $states['inactiveSince'] = $user->inactive_at
                ? \Illuminate\Support\Carbon::parse($user->inactive_at)->diffForHumans()
                : '';
            $states['emailUnverifiedLabel'] = !$user->isEmailVerified();
            $states['incompleteLabel'] = $user->hasIncompleteProfile($user);

            // Show incomplete warning modal when viewing own profile
            $states['showIncompleteWarning'] = timebank_config('profile_incomplete.show_warning_modal') &&
                                                $user->hasIncompleteProfile($user);
        }

        // Check if profile should be hidden
        if ($states['hidden'] && !$canManageProfiles && !$isViewingOwnProfile) {
            // Only allow Admin and Bank profiles to view incomplete-only profiles
            // Inactive profiles should be hidden from everyone except admins/banks
            $isIncompleteOnly = ($states['isIncomplete'] ?? false) &&
                               !($states['inactive'] ?? false) &&
                               !($states['emailUnverifiedLabel'] ?? false);

            // Show profile only if it's incomplete-only AND viewer is admin/bank
            if (!($isIncompleteOnly && $canViewIncompleteProfiles)) {
                return view('profile.not_found');
            }
        }

        $user->reactionCounter =  $user->loveReactant->reactionCounters->first() ? (int)$user->loveReactant->reactionCounters->first()->weight : null;

        $profile = $user;
        $header = __('Personal profile');

        return $profile != null
        ? view('profile.show', array_merge(compact('profile', 'header'), $states))
        : abort(403);

    }

    public function showOrganization($id)
    {
        $organization = Organization::select([
            'id',
            'name',
            'profile_photo_path',
            'about',
            'motivation',
            'website',
            'phone_public',
            'phone',
            'cyclos_skills',
            'lang_preference',
            'email_verified_at',
            'created_at',
            'last_login_at',
            'love_reactant_id',
            'inactive_at',
            'deleted_at'
        ])
        ->with([
            'managers:id,name,profile_photo_path',
            'accounts:id,name,accountable_type,accountable_id',
            'languages:id,name,lang_code,flag',
            'tags:tag_id',
            'socials:id,name,icon,urL_structure',
            'locations.district.translations:district_id,name',
            'locations.city.translations:city_id,name',
            'locations.division.translations:division_id,name',
            'locations.country.translations:country_id,name',
            'loveReactant.reactions.reacter.reacterable',
            // 'loveReactant.reactions.type',
            'loveReactant.reactionCounters',
            // 'loveReactant.reactionTotal',
        ])
        ->find($id);

        if (!$organization) {
            return view('profile.not_found');
        }

        $states = $this->getActiveStates($organization);
        $canManageProfiles = $this->getCanManageProfiles();
        $canViewIncompleteProfiles = $this->canViewIncompleteProfiles();
        $isViewingOwnProfile = getActiveProfile() &&
                               get_class(getActiveProfile()) === Organization::class &&
                               getActiveProfile()->id === $organization->id;

        // For admins/banks: Always show incomplete label if profile is incomplete (ignore config)
        if ($canManageProfiles) {
            $states['hidden'] = false;
            $states['inactiveLabel'] = !$organization->isActive();
            $states['inactiveSince'] = $organization->inactive_at
                ? \Illuminate\Support\Carbon::parse($organization->inactive_at)->diffForHumans()
                : '';
            $states['emailUnverifiedLabel'] = !$organization->isEmailVerified();
            $states['incompleteLabel'] = $organization->hasIncompleteProfile($organization);
        }

        // When viewing own profile, never hide but show all labels
        if ($isViewingOwnProfile) {
            $states['hidden'] = false;
            $states['inactiveLabel'] = !$organization->isActive();
            $states['inactiveSince'] = $organization->inactive_at
                ? \Illuminate\Support\Carbon::parse($organization->inactive_at)->diffForHumans()
                : '';
            $states['emailUnverifiedLabel'] = !$organization->isEmailVerified();
            $states['incompleteLabel'] = $organization->hasIncompleteProfile($organization);

            // Show incomplete warning modal when viewing own profile
            $states['showIncompleteWarning'] = timebank_config('profile_incomplete.show_warning_modal') &&
                                                $organization->hasIncompleteProfile($organization);
        }

        // Check if profile should be hidden
        if ($states['hidden'] && !$canManageProfiles && !$isViewingOwnProfile) {
            // Only allow Admin and Bank profiles to view incomplete-only profiles
            // Inactive profiles should be hidden from everyone except admins/banks
            $isIncompleteOnly = ($states['isIncomplete'] ?? false) &&
                               !($states['inactive'] ?? false) &&
                               !($states['emailUnverifiedLabel'] ?? false);

            // Show profile only if it's incomplete-only AND viewer is admin/bank
            if (!($isIncompleteOnly && $canViewIncompleteProfiles)) {
                return view('profile.not_found');
            }
        }

        $organization->reactionCounter =  $organization->loveReactant->reactionCounters->first() ? (int)$organization->loveReactant->reactionCounters->first()->weight : null;

        $profile = $organization;
        $header = __('Organization profile');

        return $profile != null
            ? view('profile.show', array_merge(compact('profile', 'header'), $states))
            : abort(403);

    }



    public function showBank($id)
    {
        $bank = Bank::select([
            'id',
            'name',
            'profile_photo_path',
            'about',
            'motivation',
            'website',
            'phone_public',
            'phone',
            'cyclos_skills',
            'lang_preference',
            'email_verified_at',
            'created_at',
            'last_login_at',
            'love_reactant_id',
            'inactive_at',
            'deleted_at'
        ])
        ->with([
            'managers:id,name,profile_photo_path',
            'accounts:id,name,accountable_type,accountable_id',
            'languages:id,name,lang_code,flag',
            'tags:tag_id',
            'socials:id,name,icon,urL_structure',
            'locations.district.translations:district_id,name',
            'locations.city.translations:city_id,name',
            'locations.division.translations:division_id,name',
            'locations.country.translations:country_id,name',
            'loveReactant.reactions.reacter.reacterable',
            // 'loveReactant.reactions.type',
            'loveReactant.reactionCounters',
            // 'loveReactant.reactionTotal',
        ])
        ->find($id);

        if (!$bank) {
            return view('profile.not_found');
        }

        $states = $this->getActiveStates($bank);
        $canManageProfiles = $this->getCanManageProfiles();
        $canViewIncompleteProfiles = $this->canViewIncompleteProfiles();
        $isViewingOwnProfile = getActiveProfile() &&
                               get_class(getActiveProfile()) === Bank::class &&
                               getActiveProfile()->id === $bank->id;

        // For admins/banks: Always show incomplete label if profile is incomplete (ignore config)
        if ($canManageProfiles) {
            $states['hidden'] = false;
            $states['inactiveLabel'] = !$bank->isActive();
            $states['inactiveSince'] = $bank->inactive_at
                ? \Illuminate\Support\Carbon::parse($bank->inactive_at)->diffForHumans()
                : '';
            $states['emailUnverifiedLabel'] = !$bank->isEmailVerified();
            $states['incompleteLabel'] = $bank->hasIncompleteProfile($bank);
        }

        // When viewing own profile, never hide but show all labels
        if ($isViewingOwnProfile) {
            $states['hidden'] = false;
            $states['inactiveLabel'] = !$bank->isActive();
            $states['inactiveSince'] = $bank->inactive_at
                ? \Illuminate\Support\Carbon::parse($bank->inactive_at)->diffForHumans()
                : '';
            $states['emailUnverifiedLabel'] = !$bank->isEmailVerified();
            $states['incompleteLabel'] = $bank->hasIncompleteProfile($bank);

            // Show incomplete warning modal when viewing own profile
            $states['showIncompleteWarning'] = timebank_config('profile_incomplete.show_warning_modal') &&
                                                $bank->hasIncompleteProfile($bank);
        }

        // Check if profile should be hidden
        if ($states['hidden'] && !$canManageProfiles && !$isViewingOwnProfile) {
            // Only allow Admin and Bank profiles to view incomplete-only profiles
            // Inactive profiles should be hidden from everyone except admins/banks
            $isIncompleteOnly = ($states['isIncomplete'] ?? false) &&
                               !($states['inactive'] ?? false) &&
                               !($states['emailUnverifiedLabel'] ?? false);

            // Show profile only if it's incomplete-only AND viewer is admin/bank
            if (!($isIncompleteOnly && $canViewIncompleteProfiles)) {
                return view('profile.not_found');
            }
        }

        $bank->reactionCounter =  $bank->loveReactant->reactionCounters->first() ? (int)$bank->loveReactant->reactionCounters->first()->weight : null;

        $profile = $bank;
        $header = __('Bank profile');

        return $profile != null
            ? view('profile.show', array_merge(compact('profile', 'header'), $states))
            : abort(403);

    }



    /**
     * Show the form for editing the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function edit()
    {
        $type = strtolower(class_basename(getActiveProfile()));
        $profile = getActiveProfile();

        // Check if profile is incomplete - show warning if config allows
        $showIncompleteWarning = false;

        if (timebank_config('profile_incomplete.show_warning_modal') &&
            method_exists($profile, 'hasIncompleteProfile') &&
            $profile->hasIncompleteProfile($profile)) {
            $showIncompleteWarning = true;
        }

        return view('profile-' . $type . '.edit', compact('showIncompleteWarning'));
    }


    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, $id)
    {
        //
    }


    /**
     * Remove the specified resource from storage.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function destroy($id)
    {
        //
    }

    /**
     * Redirects the authenticated user to their profile settings page with locale-specific routing.
     *
     * This method is used by the route profile.settings.no_locale.
     * The email footer template uses this route because when sending the locale of the
     * recipient is unknown.
     *
     * @return \Illuminate\Http\RedirectResponse Redirects to the localized profile settings page.
     */
    public function settingsNoLocale()
    {
        $user = auth()->user();
        $locale = $user->lang_preference ?? config('app.fallback_locale');

        // Load the route translations for the specific locale
        $routeTranslations = include resource_path("lang/{$locale}/routes.php");
        $translatedRoute = $routeTranslations['profile.settings'] ?? 'profile/settings';

        $localizedUrl = url("/{$locale}/{$translatedRoute}");

        return redirect($localizedUrl . '#message_settings');
    }


    /**
     * Show the user settings screen.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\View\View
     */
    public function settings(Request $request)
    {

        $type = strtolower(class_basename(getActiveProfile()));

        if ($type === 'user') {

            return view('profile.settings', [
                'request' => $request,
                'user' => $request->user(),
            ]);

        } else {

            return view('profile-' . $type . '.settings');
        }
    }



    public function manage()
    {
        return view('profiles.manage');
    }


    /**
     * Determines the inactive status flags for a given profile.
     *
     * @param  mixed  $profile  The profile object to check for inactivity.
     * @return array  An associative array containing:
     *                - 'inactive' (bool): Whether the profile is inactive.
     *                - 'hidden' (bool): Whether the profile should be hidden.
     *                - 'inactiveLabel' (bool): Whether the profile should be labeled as inactive.
     *                - 'inactiveSince' (string): Human-readable duration since the profile became inactive.
     */
    private function getActiveStates($profile)
    {
        $inactive = false;
        $hidden = false;
        $inactiveLabel = false;
        $inactiveSince = '';
        $emailUnverifiedLabel = false;
        $isIncomplete = false;
        $incompleteLabel = false;
        $noExchangesYetLabel = false;
        $removedSince = '';

        if (method_exists($profile, 'isActive') && !$profile->isActive()) {
            $inactive = true;
            if (timebank_config('profile_inactive.profile_hidden')) {
                $hidden = true;
            }
            if (timebank_config('profile_inactive.profile_labeled')) {
                $inactiveLabel = true;
                $inactiveSince = $profile->inactive_at
                    ? \Illuminate\Support\Carbon::parse($profile->inactive_at)->diffForHumans()
                    : '';
            }
        }

        if (method_exists($profile, 'isEmailVerified') && !$profile->isEmailVerified()) {
            $emailUnverifiedLabel = false;
            if (timebank_config('profile_email_unverified.profile_hidden')) {
                $hidden = true;
            }
            if (timebank_config('profile_email_unverified.profile_labeled')) {
                $emailUnverifiedLabel = true;
            }
        }

        if (method_exists($profile, 'hasIncompleteProfile') && $profile->hasIncompleteProfile($profile)) {
            $isIncomplete = true;
            if (timebank_config('profile_incomplete.profile_hidden')) {
                $hidden = true;
            }
            if (timebank_config('profile_incomplete.profile_labeled')) {
                $incompleteLabel = true;
            }
        }

        if (
            timebank_config('profile_incomplete.no_exchanges_yet_label') &&
            method_exists($profile, 'hasNeverReceivedTransaction') &&
            $profile->hasNeverReceivedTransaction($profile)
        ) {
            $noExchangesYetLabel = true;
        }

        if (
            (method_exists($profile, 'isRemoved') && $profile->isRemoved()) ||
            (!empty($profile->deleted_at) && \Carbon\Carbon::parse($profile->deleted_at)->isPast())
        ) {
            $hidden = true;
            $removedSince = !empty($profile->deleted_at)
                ? \Carbon\Carbon::parse($profile->deleted_at)->diffForHumans()
                : '';
        }

        return compact('inactive', 'hidden', 'inactiveLabel', 'inactiveSince', 'emailUnverifiedLabel', 'isIncomplete', 'incompleteLabel', 'noExchangesYetLabel', 'removedSince');
    }
}
