<?php

namespace App\Http\Controllers\Api;

use App\Classes\Common;
use App\Classes\Notify;
use App\Http\Controllers\ApiBaseController;
use App\Http\Requests\Api\Auth\LoginRequest;
use App\Http\Requests\Api\Auth\ProfileRequest;
use App\Http\Requests\Api\Auth\RefreshTokenRequest;
use App\Http\Requests\Api\Auth\UploadFileRequest;
use App\Models\Appreciation;
use App\Models\Asset;
use App\Models\Attendance;
use App\Models\Company;
use App\Models\Complaint;
use App\Models\EmployeeWorkStatus;
use App\Models\Generate;
use App\Models\Holiday;
use App\Models\Warning;
use App\Models\Expense;
use App\Models\FeedbackUser;
use App\Models\IncrementPromotion;
use App\Models\Lang;
use App\Models\Settings;
use App\Models\StaffMember;
use Carbon\Carbon;
use Examyou\RestAPI\ApiResponse;
use Examyou\RestAPI\Exceptions\ApiException;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Mockery\Matcher\Not;
use PDF;

class AuthController extends ApiBaseController
{
    /**
     * Get company settings
     *
     * @return \Examyou\RestAPI\ApiResponse
     */
    public function companySetting()
    {
        $settings = Company::first();

        return ApiResponse::make('Success', [
            'global_setting' => $settings,
        ]);
    }

    /**
     * Check if email settings are verified
     *
     * @return int
     */
    public function emailSettingVerified()
    {
        $emailSettingVerified = Settings::where('setting_type', 'email')
            ->where('status', 1)
            ->where('verified', 1)
            ->count();

        return $emailSettingVerified > 0 ? 1 : 0;
    }

    /**
     * Get application data
     *
     * @return \Examyou\RestAPI\ApiResponse
     */
    public function app()
    {
        $company = company(true);
        $addMenuSetting = $company ? Settings::where('setting_type', 'shortcut_menus')->first() : null;

        return ApiResponse::make('Success', [
            'app' => $company,
            'shortcut_menus' => $addMenuSetting,
            'email_setting_verified' => $this->emailSettingVerified(),
            'email_variables' => Notify::mailVariables(),
        ]);
    }

    /**
     * Check subscription module visibility
     *
     * @return \Examyou\RestAPI\ApiResponse
     */
    public function checkSubscriptionModuleVisibility()
    {
        $request = request();
        $itemType = $request->item_type;

        $visible = Common::checkSubscriptionModuleVisibility($itemType);

        return ApiResponse::make('Success', [
            'visible' => $visible,
        ]);
    }

    /**
     * Get all visible subscription modules
     *
     * @return \Examyou\RestAPI\ApiResponse
     */
    public function visibleSubscriptionModules()
    {
        $visibleSubscriptionModules = Common::allVisibleSubscriptionModules();

        return ApiResponse::make('Success', $visibleSubscriptionModules);
    }

    /**
     * Get all enabled languages
     *
     * @return \Examyou\RestAPI\ApiResponse
     */
    public function allEnabledLangs()
    {
        $allLangs = Lang::select('id', 'name', 'key', 'flag_code', 'is_rtl')->where('enabled', 1)->get();

        return ApiResponse::make('Success', [
            'langs' => $allLangs
        ]);
    }

    /**
     * Authenticate user and return token
     *
     * @param LoginRequest $request
     * @return \Examyou\RestAPI\ApiResponse
     * @throws ApiException
     */
    public function login(LoginRequest $request)
    {
        // Removing all sessions before login
        session()->flush();

        $phone = "";
        $email = "";

        $credentials = [
            'password' =>  $request->password
        ];

        if (is_numeric($request->get('email'))) {
            $credentials['phone'] = $request->email;
            $phone = $request->email;
        } else {
            $credentials['email'] = $request->email;
            $email = $request->email;
        }

        // For checking user
        $user = StaffMember::select('*');
        if ($email != '') {
            $user = $user->where('email', $email);
        } else if ($phone != '') {
            $user = $user->where('phone', $phone);
        }
        $user = $user->first();

        // Adding user type according to email/phone
        if ($user) {
            $credentials['user_type'] = 'staff_members';
            $credentials['is_superadmin'] = 0;
            $userCompany = Company::where('id', $user->company_id)->first();

            // Check if user is allowed to login
            if (!$user->allow_login) {
                throw new ApiException('You are not allowed to login. Please contact administrator.');
            }
        }

        if (!$token = auth('api')->attempt($credentials)) {
            throw new ApiException('These credentials do not match our records.');
        } else if ($userCompany->status === 'pending') {
            throw new ApiException('Your company not verified.');
        } else if ($userCompany->status === 'inactive') {
            throw new ApiException('Company account deactivated.');
        } else if (auth('api')->user()->status === 'waiting') {
            throw new ApiException('User not verified.');
        } else if (auth('api')->user()->status === 'disabled') {
            throw new ApiException('Account deactivated.');
        }

        $company = company();
        $response = $this->respondWithToken($token);
        $addMenuSetting = Settings::where('setting_type', 'shortcut_menus')->first();
        $response['app'] = $company;
        $response['shortcut_menus'] = $addMenuSetting;
        $response['email_setting_verified'] = $this->emailSettingVerified();
        $response['visible_subscription_modules'] = Common::allVisibleSubscriptionModules();

        return ApiResponse::make('Loggged in successfull', $response);
    }

    /**
     * Get the authenticated user
     *
     * @return \Examyou\RestAPI\ApiResponse
     */
    public function user()
    {
        $user = auth('api')->user();
        $user = $user->load('role', 'role.perms');

        session(['user' => $user]);

        return ApiResponse::make('Data successfull', [
            'user' => $user
        ]);
    }

    /**
     * Update user profile
     *
     * @param ProfileRequest $request
     * @return \Examyou\RestAPI\ApiResponse
     * @throws ApiException
     */
    public function profile(ProfileRequest $request)
    {
        $user = auth('api')->user();

        // In Demo Mode
        if (env('APP_ENV') == 'production') {
            $request = request();

            if ($request->email == 'admin@example.com' && $request->has('password') && $request->password != '') {
                throw new ApiException('Not Allowed In Demo Mode');
            }
        }

        $user->name = $request->name;

        // Handle profile image upload
        if ($request->hasFile('profile_image')) {
            // Get the old file before uploading new one
            $oldFile = $user->profile_image;

            // Get folder path for user images
            $folderPath = "users";

            // Upload new file using driver (S3 or local)
            $file = $request->file('profile_image');
            $fileName = Common::uploadFileUsingDriver($file, $folderPath);

            // Delete old file if exists
            if (!empty($oldFile)) {
                Common::deleteFileUsingDriver($oldFile, $folderPath);
            }

            // Set uploaded filename to user
            $user->profile_image = $fileName;
        }

        if ($request->password != '') {
            $user->password = $request->password;
        }
        $user->phone = $request->phone;
        $user->address = $request->address;
        $user->save();

        return ApiResponse::make('Profile updated successfull', [
            'user' => $user->load('role', 'role.perms')
        ]);
    }

    /**
     * Refresh authentication token
     *
     * @param RefreshTokenRequest $request
     * @return \Examyou\RestAPI\ApiResponse
     */
    public function refreshToken(RefreshTokenRequest $request)
    {
        $newToken = auth('api')->refresh();

        $response = $this->respondWithToken($newToken);

        return ApiResponse::make('Token fetched successfully', $response);
    }

    /**
     * Log out the user
     *
     * @return \Examyou\RestAPI\ApiResponse
     */
    public function logout()
    {
        $request = request();

        if (auth('api')->user() && $request->bearerToken() != '') {
            auth('api')->logout();
        }

        session()->flush();

        return ApiResponse::make(__('Session closed successfully'));
    }

    /**
     * Upload a file
     *
     * @param UploadFileRequest $request
     * @return \Examyou\RestAPI\ApiResponse
     */
    public function uploadFile(UploadFileRequest $request)
    {
        $result = Common::uploadFile($request);

        return ApiResponse::make('File Uploaded', $result);
    }

    /**
     * Get language translations
     *
     * @return \Examyou\RestAPI\ApiResponse
     */
    public function langTrans()
    {
        $request = request();
        $langKey = $request->input('lang'); // Optional: fetch specific language only
        $groups = $request->input('groups'); // Optional: comma-separated list of groups (e.g., "common,menu,staff_member")
        $excludeGroups = $request->input('exclude_groups'); // Optional: comma-separated list of groups to exclude

        // Build the query with optional group filtering
        if ($groups || $excludeGroups) {
            $query = Lang::query();

            if ($langKey) {
                $query->where('key', $langKey);
            }

            // Apply group filtering to the translations relationship
            $query->with(['translations' => function ($q) use ($groups, $excludeGroups) {
                if ($groups) {
                    $groupList = array_map('trim', explode(',', $groups));
                    $q->whereIn('group', $groupList);
                }
                if ($excludeGroups) {
                    $excludeList = array_map('trim', explode(',', $excludeGroups));
                    $q->whereNotIn('group', $excludeList);
                }
            }]);
        } else {
            $query = Lang::with('translations');

            if ($langKey) {
                $query->where('key', $langKey);
            }
        }

        $langs = $query->get();

        // Get the last updated timestamp for cache validation
        $lastUpdated = \App\Models\Translation::max('updated_at');

        return ApiResponse::make('Langs fetched', [
            'data' => $langs,
            'last_updated' => $lastUpdated,
        ]);
    }

    /**
     * Change theme mode
     *
     * @param Request $request
     * @return \Examyou\RestAPI\ApiResponse
     */
    public function changeThemeMode(Request $request)
    {
        $mode = $request->has('theme_mode') ? $request->theme_mode : 'light';

        session(['theme_mode' => $mode]);

        if ($mode == 'dark') {
            $company = company();
            $company->left_sidebar_theme = 'dark';
            $company->save();

            $updatedCompany = company(true);
        }

        return ApiResponse::make('Success', [
            'status' => "success",
            'themeMode' => $mode,
            'themeModee' => session()->all(),
        ]);
    }

    /**
     * Get all available timezones and date/time formats
     *
     * @return \Examyou\RestAPI\ApiResponse
     */
    public function getAllTimezones()
    {
        $timezones = \DateTimeZone::listIdentifiers(\DateTimeZone::ALL);

        return ApiResponse::make('Success', [
            'timezones' => $timezones,
            'date_formates' => [
                'd-m-Y' => 'DD-MM-YYYY',
                'm-d-Y' => 'MM-DD-YYYY',
                'Y-m-d' => 'YYYY-MM-DD',
                'd.m.Y' => 'DD.MM.YYYY',
                'm.d.Y' => 'MM.DD.YYYY',
                'Y.m.d' => 'YYYY.MM.DD',
                'd/m/Y' => 'DD/MM/YYYY',
                'm/d/Y' => 'MM/DD/YYYY',
                'Y/m/d' => 'YYYY/MM/DD',
                'd/M/Y' => 'DD/MMM/YYYY',
                'd.M.Y' => 'DD.MMM.YYYY',
                'd-M-Y' => 'DD-MMM-YYYY',
                'd M Y' => 'DD MMM YYYY',
                'd F, Y' => 'DD MMMM, YYYY',
                'D/M/Y' => 'ddd/MMM/YYYY',
                'D.M.Y' => 'ddd.MMM.YYYY',
                'D-M-Y' => 'ddd-MMM-YYYY',
                'D M Y' => 'ddd MMM YYYY',
                'd D M Y' => 'DD ddd MMM YYYY',
                'D d M Y' => 'ddd DD MMM YYYY',
                'dS M Y' => 'Do MMM YYYY',
            ],
            'time_formates' => [
                "hh:mm A" => '12 Hours hh:mm A',
                'hh:mm a' => '12 Hours hh:mm a',
                'hh:mm:ss A' => '12 Hours hh:mm:ss A',
                'hh:mm:ss a' => '12 Hours hh:mm:ss a',
                'HH:mm ' => '24 Hours HH:mm:ss',
                'HH:mm:ss' => '24 Hours hh:mm:ss',
            ]
        ]);
    }

    /**
     * Format the token response
     *
     * @param string $token
     * @return array
     */
    protected function respondWithToken($token)
    {
        $user = user();

        return [
            'token' => $token,
            'token_type' => 'bearer',
            'expires_in' => Carbon::now()->addDays(180),
            'user' => $user
        ];
    }
}
