<?php

namespace App\Controllers;

use App\Core\Controller;
use App\Helpers\Auth;
use App\Helpers\Mailer;
use App\Helpers\Sms;
use App\Helpers\Url;
use App\Models\User;
use App\Models\AuditLog;
use App\Models\MemberProfile;
use App\Models\ProfileField;

class AuthController extends Controller
{
    public function showLogin()
    {
        if (Auth::check()) {
            $this->redirect('/dashboard');
        }
        $settingModel = new \App\Models\Setting();
        $companyLogo = $settingModel->getValue('company_logo', '');
        $companyName = $settingModel->getValue('company_name', 'Ghana Anaesthesiologists Society');
        $this->view('auth/login', [
            'companyLogo' => $companyLogo,
            'companyName' => $companyName,
        ], false);
    }

    public function login()
    {
        $email = isset($_POST['email']) ? $_POST['email'] : '';
        $password = isset($_POST['password']) ? $_POST['password'] : '';

        $userModel = new User();
        $user = $userModel->findByEmail($email);

        if (!$user) {
            $_SESSION['error'] = 'Invalid email or password';
            $this->redirect('/login');
        }

        if ($user->approval_status === 'pending') {
            $_SESSION['error'] = 'Your account is pending approval. You will receive an email once approved.';
            $this->redirect('/login');
        }

        if ($user->approval_status === 'rejected') {
            $_SESSION['error'] = 'Your membership application has been declined. Please contact the society for more information.';
            $this->redirect('/login');
        }

        if ($user->status !== 'active') {
            $_SESSION['error'] = 'Your account has been deactivated. Please contact the administrator.';
            $this->redirect('/login');
        }

        if (Auth::login($email, $password)) {
            $userModel->update($user->id, ['last_login' => date('Y-m-d H:i:s')]);

            $audit = new AuditLog();
            $audit->log(Auth::id(), 'user.login', 'session', Auth::id(), Auth::user()->name . ' logged in');

            $_SESSION['success'] = 'Welcome back, ' . Auth::user()->name . '!';

            // Check for incomplete profile reminder
            $profileModel = new \App\Models\MemberProfile();
            if (!$profileModel->isComplete(Auth::id())) {
                $_SESSION['warning'] = 'Please complete your membership profile to access all features.';
            }

            $redirect = $_POST['redirect'] ?? '/dashboard';
            $this->redirect($redirect);
        }

        $_SESSION['error'] = 'Invalid email or password';
        $this->redirect('/login');
    }

    public function logout()
    {
        Auth::logout();
        $this->redirect('/login');
    }

    public function showRegister()
    {
        if (Auth::check()) {
            $this->redirect('/dashboard');
        }
        $settingModel = new \App\Models\Setting();
        $registrationEnabled = $settingModel->getValue('enable_registration', 'true') === 'true';
        if (!$registrationEnabled) {
            $_SESSION['error'] = 'Registration is currently disabled. Please contact the society administrator.';
            $this->redirect('/login');
        }

        $profileFieldModel = new ProfileField();
        $profileFields = $profileFieldModel->getActive();
        $companyLogo = $settingModel->getValue('company_logo', '');
        $companyName = $settingModel->getValue('company_name', 'Ghana Anaesthesiologists Society');

        $this->view('auth/register', [
            'profileFields' => $profileFields,
            'companyLogo' => $companyLogo,
            'companyName' => $companyName,
        ], false);
    }

    public function register()
    {
        $firstName = trim($_POST['first_name'] ?? '');
        $otherNames = trim($_POST['other_names'] ?? '');
        $lastName = trim($_POST['last_name'] ?? '');
        $professionalPin = trim($_POST['professional_pin'] ?? '');
        $email = trim($_POST['email'] ?? '');
        $password = $_POST['password'] ?? '';
        $passwordConfirm = $_POST['password_confirm'] ?? '';
        $agreeTerms = isset($_POST['agree_terms']);

        $name = trim("$firstName $otherNames $lastName");

        if (empty($firstName) || empty($lastName) || empty($email) || empty($password)) {
            $_SESSION['error'] = 'Please fill in all required fields';
            $this->redirect('/register');
        }

        if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
            $_SESSION['error'] = 'Please enter a valid email address';
            $this->redirect('/register');
        }

        if ($password !== $passwordConfirm) {
            $_SESSION['error'] = 'Passwords do not match';
            $this->redirect('/register');
        }

        if (strlen($password) < 8) {
            $_SESSION['error'] = 'Password must be at least 8 characters';
            $this->redirect('/register');
        }

        if (!$agreeTerms) {
            $_SESSION['error'] = 'You must agree to the terms and conditions';
            $this->redirect('/register');
        }

        $userModel = new User();
        if ($userModel->findByEmail($email)) {
            $_SESSION['error'] = 'An account with this email already exists';
            $this->redirect('/register');
        }

        $settingModel = new \App\Models\Setting();
        $defaultRole = 'member';
        $autoApprove = $settingModel->getValue('auto_approve_registration', 'false') === 'true';
        $approvalStatus = $autoApprove ? 'approved' : 'pending';

        $userModel->create([
            'name' => $name,
            'first_name' => $firstName,
            'other_names' => $otherNames,
            'last_name' => $lastName,
            'professional_pin' => $professionalPin,
            'medical_council_number' => trim($_POST['medical_council_number'] ?? ''),
            'email' => $email,
            'password' => password_hash($password, PASSWORD_DEFAULT),
            'role' => $defaultRole,
            'status' => 'active',
            'approval_status' => $approvalStatus,
        ]);

        $userId = $this->db->lastInsertId();

        // Save member profile data from registration form
        $profileModel = new MemberProfile();
        $previousMemberValue = $_POST['previous_member'] ?? 'no';
        if (is_string($previousMemberValue)) {
            $previousMemberValue = strtolower(trim($previousMemberValue));
            $previousMemberValue = in_array($previousMemberValue, ['1', 'yes', 'true', 'on'], true) ? 1 : 0;
        } else {
            $previousMemberValue = (int)$previousMemberValue;
        }

        $profileData = [
            'user_id' => $userId,
            'gender' => $_POST['gender'] ?? null,
            'nationality' => $_POST['nationality'] ?? null,
            'postal_address' => $_POST['postal_address'] ?? null,
            'residential_address' => $_POST['residential_address'] ?? null,
            'mobile_phone' => trim($_POST['mobile_phone'] ?? ''),
            'alternative_phone' => $_POST['alternative_phone'] ?? null,
            'institution_hospital' => $_POST['institution_hospital'] ?? null,
            'city_town' => $_POST['city_town'] ?? null,
            'country' => $_POST['country'] ?? null,
            'years_practice' => $_POST['years_practice'] ?? null,
            'highest_qualification' => $_POST['highest_qualification'] ?? null,
            'membership_category' => $_POST['membership_category'] ?? null,
            'previous_member' => $previousMemberValue,
            'notify_conferences' => isset($_POST['notify_conferences']) ? 1 : 0,
            'notify_workshops' => isset($_POST['notify_workshops']) ? 1 : 0,
            'notify_webinars' => isset($_POST['notify_webinars']) ? 1 : 0,
            'notify_research' => isset($_POST['notify_research']) ? 1 : 0,
            'notify_scholarships' => isset($_POST['notify_scholarships']) ? 1 : 0,
            'notify_news' => isset($_POST['notify_news']) ? 1 : 0,
            'declaration_initials' => $_POST['declaration_initials'] ?? null,
            'declaration_date' => $_POST['declaration_date'] ?? null,
        ];
        $profileModel->create($profileData);

        // Save dynamic profile field values
        $profileFieldModel = new ProfileField();
        $activeFields = $profileFieldModel->getActive();
        foreach ($activeFields as $pf) {
            $val = $_POST['pf_' . $pf->field_name] ?? '';
            if ($pf->field_type === 'checkbox') {
                $val = isset($_POST['pf_' . $pf->field_name]) ? '1' : '0';
            }
            if ($val !== '') {
                $profileFieldModel->setFieldValue($userId, $pf->id, $val);
            }
        }

        // Notify all admins by email + internal message about new registration
        $adminUsers = $userModel->where('role', 'admin');
        $applicant = (object)[
            'name' => $name,
            'email' => $email,
            'professional_pin' => $professionalPin,
            'created_at' => date('Y-m-d H:i:s'),
        ];
        foreach ($adminUsers as $admin) {
            $adminName = $admin->first_name ? trim($admin->first_name . ' ' . $admin->last_name) : $admin->name;
            Mailer::sendNewRegistrationAlert($admin->email, $adminName, $applicant);
            $this->db->prepare("INSERT INTO messages (sender_id, subject, body) VALUES (?, ?, ?)")->execute([$admin->id, "New Registration: {$name}", "A new membership application has been submitted by {$name} ({$email}). Please review it at " . Url::to('/users/pending')]);
            $messageId = $this->db->lastInsertId();
            $this->db->prepare("INSERT INTO message_recipients (message_id, recipient_id) VALUES (?, ?)")->execute([$messageId, $admin->id]);
        }

        if ($autoApprove) {
            $_SESSION['success'] = 'Registration successful! Welcome to the Ghana Anaesthesiologists Society.';
            $this->redirect('/');
        } else {
            $_SESSION['success'] = 'Registration successful! Your application has been submitted for review. You will receive an email once your membership is approved.';
            $this->redirect('/');
        }
    }

    public function showForgotPassword()
    {
        if (Auth::check()) {
            $this->redirect('/dashboard');
        }

        $settingModel = new \App\Models\Setting();
        $smsEnabled = $settingModel->getValue('sms_api_key') !== '';

        $this->view('auth/forgot-password', [
            'smsEnabled' => $smsEnabled,
        ], false);
    }

    public function forgotPassword()
    {
        $method = $_POST['reset_method'] ?? 'email';

        if ($method === 'email') {
            return $this->forgotPasswordEmail();
        } elseif ($method === 'sms') {
            return $this->forgotPasswordSms();
        }

        $_SESSION['error'] = 'Invalid reset method';
        $this->redirect('/forgot-password');
    }

    private function forgotPasswordEmail()
    {
        $email = isset($_POST['email']) ? $_POST['email'] : '';

        $userModel = new User();
        $user = $userModel->findByEmail($email);

        if ($user) {
            $token = bin2hex(random_bytes(32));
            $stmt = $this->db->prepare("INSERT INTO password_resets (user_id, token, reset_method, expires_at) VALUES (?, ?, 'email', DATE_ADD(NOW(), INTERVAL 1 HOUR))");
            $stmt->execute(array($user->id, $token));

            $resetLink = Url::to('/reset-password?token=' . $token);
            $subject = "Password Reset - Ghana Anaesthesiologists Society";
            $body = "<p>Click the link below to reset your password:</p><p><a href='{$resetLink}'>{$resetLink}</a></p><p>This link expires in 1 hour.</p>";
            Mailer::send($email, $subject, $body);
        }

        $_SESSION['success'] = 'If your email is registered, you will receive a password reset link.';
        $this->redirect('/login');
    }

    private function forgotPasswordSms()
    {
        $phone = isset($_POST['phone']) ? trim($_POST['phone']) : '';

        if (empty($phone)) {
            $_SESSION['error'] = 'Please enter your phone number';
            $this->redirect('/forgot-password');
        }

        $stmt = $this->db->prepare("SELECT u.* FROM users u LEFT JOIN member_profiles mp ON u.id = mp.user_id WHERE mp.mobile_phone = ? OR mp.alternative_phone = ? LIMIT 1");
        $stmt->execute([$phone, $phone]);
        $user = $stmt->fetch(\PDO::FETCH_OBJ);

        if ($user) {
            $otp = str_pad((string)random_int(0, 999999), 6, '0', STR_PAD_LEFT);
            $stmt = $this->db->prepare("INSERT INTO password_resets (user_id, token, reset_method, phone, otp, expires_at) VALUES (?, ?, 'sms', ?, ?, DATE_ADD(NOW(), INTERVAL 15 MINUTE))");
            $stmt->execute([$user->id, bin2hex(random_bytes(16)), $phone, $otp]);

            Sms::sendPasswordResetOtp($phone, $otp);
        }

        $_SESSION['success'] = 'If your phone number is registered, you will receive an OTP via SMS.';
        $this->redirect('/login');
    }

    public function showResetPassword()
    {
        $token = $_GET['token'] ?? '';
        $otpInput = $_GET['otp'] ?? '';

        if ($otpInput) {
            $stmt = $this->db->prepare("SELECT * FROM password_resets WHERE otp = ? AND used = 0 AND expires_at > NOW() AND reset_method = 'sms'");
            $stmt->execute([$otpInput]);
        } else {
            $stmt = $this->db->prepare("SELECT * FROM password_resets WHERE token = ? AND used = 0 AND expires_at > NOW()");
            $stmt->execute([$token]);
        }

        $reset = $stmt->fetch(\PDO::FETCH_OBJ);

        if (!$reset) {
            $_SESSION['error'] = 'Invalid or expired reset link';
            $this->redirect('/login');
        }

        if ($reset->reset_method === 'sms') {
            $this->view('auth/reset-password', ['token' => '', 'otp' => $reset->otp, 'resetId' => $reset->id], false);
        } else {
            $this->view('auth/reset-password', ['token' => $token, 'otp' => '', 'resetId' => null], false);
        }
    }

    public function resetPassword()
    {
        $token = $_POST['token'] ?? '';
        $otp = $_POST['otp'] ?? '';
        $resetId = $_POST['reset_id'] ?? '';
        $password = $_POST['password'] ?? '';
        $passwordConfirm = $_POST['password_confirm'] ?? '';

        if ($password !== $passwordConfirm) {
            $_SESSION['error'] = 'Passwords do not match';
            $redirectUrl = $otp ? "/reset-password?otp=$otp" : "/reset-password?token=$token";
            $this->redirect($redirectUrl);
        }

        if ($otp && $resetId) {
            $stmt = $this->db->prepare("SELECT * FROM password_resets WHERE id = ? AND otp = ? AND used = 0 AND expires_at > NOW() AND reset_method = 'sms'");
            $stmt->execute([$resetId, $otp]);
        } else {
            $stmt = $this->db->prepare("SELECT * FROM password_resets WHERE token = ? AND used = 0 AND expires_at > NOW()");
            $stmt->execute([$token]);
        }

        $reset = $stmt->fetch(\PDO::FETCH_OBJ);

        if (!$reset) {
            $_SESSION['error'] = 'Invalid or expired reset link';
            $this->redirect('/login');
        }

        $userModel = new User();
        $userModel->update($reset->user_id, ['password' => password_hash($password, PASSWORD_DEFAULT)]);

        $stmt = $this->db->prepare("UPDATE password_resets SET used = 1 WHERE id = ?");
        $stmt->execute([$reset->id]);

        $_SESSION['success'] = 'Password has been reset successfully. Please log in.';
        $this->redirect('/login');
    }
}
