<?php

namespace App\Controllers;

use App\Models\ProductModel;
use App\Models\UserModel;
use App\Models\OrderModel;
use App\Models\NotificationModel;
use App\Models\DeliveryPersonModel;

class Admin extends BaseController
{
    protected $productModel;
    protected $userModel;
    protected $orderModel;
    protected $notificationModel;
    protected $deliveryPersonModel;

    public function __construct()
    {
        $this->productModel = new ProductModel();
        $this->userModel = new UserModel();
        $this->orderModel = new OrderModel();
        $this->notificationModel = new NotificationModel();
        $this->deliveryPersonModel = new DeliveryPersonModel();
    }

    private function checkAdminAccess()
    {
        if (!session()->get('logged_in')) {
            return redirect()->to('/login');
        }

        $role = session()->get('role');
        if ($role !== 'admin' && $role !== 'super_admin') {
            return redirect()->to('/dashboard')->with('error', 'Access denied');
        }

        return null;
    }

    public function dashboard()
    {
        $check = $this->checkAdminAccess();
        if ($check) return $check;

        $data = [
            'user' => session()->get(),
            'pending_products' => $this->productModel->where('status', 'pending')->countAllResults(),
            'total_products' => $this->productModel->countAllResults(),
            'total_users' => $this->userModel->countAllResults(),
            'total_orders' => $this->orderModel->countAllResults(),
        ];

        return view('admin/dashboard', $data);
    }

    public function pendingProducts()
    {
        $check = $this->checkAdminAccess();
        if ($check) return $check;

        $data = [
            'user' => session()->get(),
            'products' => $this->productModel->getPendingApprovals(),
        ];

        return view('admin/pending_products', $data);
    }

    public function approveProduct($productId)
    {
        $check = $this->checkAdminAccess();
        if ($check) return $check;

        $product = $this->productModel->find($productId);
        
        if (!$product) {
            return $this->response->setJSON([
                'success' => false,
                'message' => 'Product not found'
            ]);
        }

        $remarks = $this->request->getPost('remarks');
        $this->productModel->approveProduct($productId, $remarks);

        // Notify seller
        $this->notificationModel->insert([
            'user_id' => $product['seller_id'],
            'title' => 'Product Approved',
            'message' => "Your product '{$product['title']}' has been approved and is now live!",
            'type' => 'product_approved',
            'related_id' => $productId,
        ]);

        return $this->response->setJSON([
            'success' => true,
            'message' => 'Product approved successfully'
        ]);
    }

    public function rejectProduct($productId)
    {
        $check = $this->checkAdminAccess();
        if ($check) return $check;

        $product = $this->productModel->find($productId);
        
        if (!$product) {
            return $this->response->setJSON([
                'success' => false,
                'message' => 'Product not found'
            ]);
        }

        $remarks = $this->request->getPost('remarks');
        
        if (empty($remarks)) {
            return $this->response->setJSON([
                'success' => false,
                'message' => 'Please provide a reason for rejection'
            ]);
        }

        $this->productModel->rejectProduct($productId, $remarks);

        // Notify seller
        $this->notificationModel->insert([
            'user_id' => $product['seller_id'],
            'title' => 'Product Rejected',
            'message' => "Your product '{$product['title']}' has been rejected. Reason: {$remarks}",
            'type' => 'product_rejected',
            'related_id' => $productId,
        ]);

        return $this->response->setJSON([
            'success' => true,
            'message' => 'Product rejected'
        ]);
    }

    public function allProducts()
    {
        $check = $this->checkAdminAccess();
        if ($check) return $check;

        $status = $this->request->getGet('status');
        
        $builder = $this->productModel->builder();
        $builder->select('products.*, users.name as seller_name, users.email as seller_email')
                ->join('users', 'users.id = products.seller_id');
        
        if ($status) {
            $builder->where('products.status', $status);
        }
        
        $products = $builder->orderBy('products.created_at', 'DESC')->get()->getResultArray();

        $data = [
            'user' => session()->get(),
            'products' => $products,
            'current_status' => $status,
        ];

        return view('admin/all_products', $data);
    }

    public function users()
    {
        $check = $this->checkAdminAccess();
        if ($check) return $check;

        $userType = $this->request->getGet('type');
        
        $builder = $this->userModel->builder();
        
        if ($userType) {
            $builder->where('user_type', $userType);
        }
        
        $users = $builder->orderBy('created_at', 'DESC')->get()->getResultArray();

        $data = [
            'user' => session()->get(),
            'users' => $users,
            'current_type' => $userType,
        ];

        return view('admin/users', $data);
    }

    public function blockUser($userId)
    {
        $check = $this->checkAdminAccess();
        if ($check) return $check;

        $user = $this->userModel->find($userId);
        
        if (!$user) {
            return $this->response->setJSON([
                'success' => false,
                'message' => 'User not found'
            ]);
        }

        $this->userModel->update($userId, ['is_blocked' => 1]);

        // Notify user
        $this->notificationModel->insert([
            'user_id' => $userId,
            'title' => 'Account Blocked',
            'message' => 'Your account has been blocked by admin',
            'type' => 'account_blocked',
        ]);

        return $this->response->setJSON([
            'success' => true,
            'message' => 'User blocked successfully'
        ]);
    }

    public function unblockUser($userId)
    {
        $check = $this->checkAdminAccess();
        if ($check) return $check;

        $user = $this->userModel->find($userId);
        
        if (!$user) {
            return $this->response->setJSON([
                'success' => false,
                'message' => 'User not found'
            ]);
        }

        $this->userModel->update($userId, ['is_blocked' => 0]);

        // Notify user
        $this->notificationModel->insert([
            'user_id' => $userId,
            'title' => 'Account Unblocked',
            'message' => 'Your account has been unblocked',
            'type' => 'account_unblocked',
        ]);

        return $this->response->setJSON([
            'success' => true,
            'message' => 'User unblocked successfully'
        ]);
    }

    public function orders()
    {
        $check = $this->checkAdminAccess();
        if ($check) return $check;

        $status = $this->request->getGet('status');
        
        $builder = $this->orderModel->builder();
        $builder->select('orders.*, products.title as product_title')
                ->select('buyer.name as buyer_name, seller.name as seller_name')
                ->join('products', 'products.id = orders.product_id')
                ->join('users as buyer', 'buyer.id = orders.buyer_id')
                ->join('users as seller', 'seller.id = orders.seller_id');
        
        if ($status) {
            $builder->where('orders.status', $status);
        }
        
        $orders = $builder->orderBy('orders.created_at', 'DESC')->get()->getResultArray();

        $data = [
            'user' => session()->get(),
            'orders' => $orders,
            'current_status' => $status,
        ];

        return view('admin/orders', $data);
    }

    // A6-A8: Delivery Person Assignment
    public function assignDelivery($orderId)
    {
        $check = $this->checkAdminAccess();
        if ($check) return $check;

        $order = $this->orderModel->find($orderId);
        
        if (!$order) {
            return $this->response->setJSON([
                'success' => false,
                'message' => 'Order not found'
            ]);
        }

        if ($order['status'] !== 'confirmed') {
            return $this->response->setJSON([
                'success' => false,
                'message' => 'Only confirmed orders can be assigned to delivery persons'
            ]);
        }

        $deliveryPersonId = $this->request->getPost('delivery_person_id');
        
        // Verify delivery person
        $deliveryPerson = $this->deliveryPersonModel->find($deliveryPersonId);
        if (!$deliveryPerson || $deliveryPerson['status'] !== 'active') {
            return $this->response->setJSON([
                'success' => false,
                'message' => 'Invalid delivery person'
            ]);
        }

        // Update order
        $this->orderModel->update($orderId, [
            'delivery_person_id' => $deliveryPersonId,
            'status' => 'assigned'
        ]);

        // Notify delivery person
        $this->notificationModel->insert([
            'user_id' => $deliveryPerson['user_id'],
            'title' => 'New Delivery Assignment',
            'message' => 'You have been assigned a new delivery order',
            'type' => 'delivery_assigned',
            'related_id' => $orderId,
        ]);

        return $this->response->setJSON([
            'success' => true,
            'message' => 'Delivery person assigned successfully'
        ]);
    }

    public function getAvailableDeliveryPersons()
    {
        $check = $this->checkAdminAccess();
        if ($check) return $check;

        $deliveryPersons = $this->deliveryPersonModel->getAvailableDeliveryPersons();
        
        return $this->response->setJSON([
            'success' => true,
            'delivery_persons' => $deliveryPersons
        ]);
    }

    // Admin Reports
    public function reports()
    {
        $check = $this->checkAdminAccess();
        if ($check) return $check;

        $period = $this->request->getGet('period') ?? 'weekly';
        
        // Calculate date range
        $startDate = match($period) {
            'daily' => date('Y-m-d'),
            'weekly' => date('Y-m-d', strtotime('-7 days')),
            'monthly' => date('Y-m-d', strtotime('-30 days')),
            default => date('Y-m-d', strtotime('-7 days')),
        };

        $stats = [
            'total_orders' => $this->orderModel->where('created_at >=', $startDate)->countAllResults(),
            'total_revenue' => $this->orderModel->where('created_at >=', $startDate)->selectSum('final_price')->first()['final_price'] ?? 0,
            'new_users' => $this->userModel->where('created_at >=', $startDate)->countAllResults(),
            'new_products' => $this->productModel->where('created_at >=', $startDate)->countAllResults(),
        ];

        $orders = $this->orderModel
            ->select('orders.*, products.title as product_name')
            ->join('products', 'products.id = orders.product_id')
            ->where('orders.created_at >=', $startDate)
            ->orderBy('orders.created_at', 'DESC')
            ->findAll();

        $data = [
            'user' => session()->get(),
            'period' => $period,
            'stats' => $stats,
            'orders' => $orders,
        ];

        return view('admin/reports', $data);
    }

    // SA2, SA15 - Mark BGV Cleared (Admin can also do this)
    public function markBGVCleared($userId)
    {
        $check = $this->checkAdminAccess();
        if ($check) return $check;

        $user = $this->userModel->find($userId);
        if (!$user || $user['user_type'] !== 'delivery') {
            return $this->response->setJSON(['success' => false, 'message' => 'Invalid delivery person']);
        }

        $this->userModel->update($userId, ['bgv_cleared' => 1]);

        return $this->response->setJSON(['success' => true, 'message' => 'BGV cleared successfully']);
    }

    // SA15 - Mark Order Status on Behalf of Delivery Person
    public function updateDeliveryStatus($orderId)
    {
        $check = $this->checkAdminAccess();
        if ($check) return $check;

        $order = $this->orderModel->find($orderId);
        if (!$order) {
            return $this->response->setJSON(['success' => false, 'message' => 'Order not found']);
        }

        $newStatus = $this->request->getPost('status');
        $allowedStatuses = ['confirmed', 'dispatched', 'in_transit', 'delivered', 'cancelled'];

        if (!in_array($newStatus, $allowedStatuses)) {
            return $this->response->setJSON(['success' => false, 'message' => 'Invalid status']);
        }

        $this->orderModel->update($orderId, ['status' => $newStatus]);

        // Add to order status history
        $db = \Config\Database::connect();
        $db->table('order_status_history')->insert([
            'order_id' => $orderId,
            'status' => $newStatus,
            'updated_by' => session()->get('user_id'),
            'updated_by_role' => 'admin',
            'remarks' => $this->request->getPost('remarks'),
        ]);

        // Notify buyer and seller
        $this->notificationModel->insert([
            'user_id' => $order['buyer_id'],
            'title' => 'Order Status Updated',
            'message' => "Your order status has been updated to: {$newStatus}",
            'type' => 'order_update',
            'related_id' => $orderId,
        ]);

        return $this->response->setJSON(['success' => true, 'message' => 'Order status updated']);
    }

    // SA16 - Extend Rental Date (Admin can also do this)
    public function extendRentalDate($orderId)
    {
        $check = $this->checkAdminAccess();
        if ($check) return $check;

        $order = $this->orderModel->find($orderId);
        if (!$order || $order['order_type'] !== 'rent') {
            return $this->response->setJSON(['success' => false, 'message' => 'Invalid rental order']);
        }

        $newEndDate = $this->request->getPost('new_end_date');
        $proof = $this->request->getPost('proof_of_confirmation');

        $this->orderModel->update($orderId, [
            'rental_end_date' => $newEndDate,
            'rental_extension_proof' => $proof,
        ]);

        // Notify buyer
        $this->notificationModel->insert([
            'user_id' => $order['buyer_id'],
            'title' => 'Rental Extended',
            'message' => "Your rental period has been extended to {$newEndDate}",
            'type' => 'rental_extended',
            'related_id' => $orderId,
        ]);

        return $this->response->setJSON(['success' => true, 'message' => 'Rental date extended successfully']);
    }
}
