<?php

namespace App\Controllers;

use App\Models\ProductModel;
use App\Models\ProductImageModel;
use App\Models\BrandModel;
use App\Models\OfferModel;
use App\Models\OrderModel;
use App\Models\NotificationModel;
use App\Models\UserModel;
use App\Models\ReviewModel;

class Buyer extends BaseController
{
    protected $productModel;
    protected $imageModel;
    protected $brandModel;
    protected $offerModel;
    protected $orderModel;
    protected $notificationModel;
    protected $userModel;
    protected $reviewModel;

    public function __construct()
    {
        $this->productModel = new ProductModel();
        $this->imageModel = new ProductImageModel();
        $this->brandModel = new BrandModel();
        $this->offerModel = new OfferModel();
        $this->orderModel = new OrderModel();
        $this->notificationModel = new NotificationModel();
        $this->userModel = new UserModel();
        $this->reviewModel = new ReviewModel();
    }

    // B1 - Browse Products
    public function index()
    {
        $category = $this->request->getGet('category');
        $type = $this->request->getGet('type'); // buy or rent
        $search = $this->request->getGet('search');
        $gender = $this->request->getGet('gender');
        $minPrice = $this->request->getGet('min_price');
        $maxPrice = $this->request->getGet('max_price');
        $sort = $this->request->getGet('sort') ?? 'latest';

        $builder = $this->productModel
            ->select('products.*, product_images.image_path as primary_image, users.name as seller_name, users.seller_reliability_score, brands.brand_name')
            ->join('product_images', 'product_images.product_id = products.id AND product_images.is_primary = 1', 'left')
            ->join('users', 'users.id = products.seller_id')
            ->join('brands', 'brands.id = products.brand_id', 'left')
            ->where('products.status', 'approved');

        if ($category) {
            $builder->where('products.category', $category);
        }
        if ($type) {
            $builder->where('products.listing_type', $type);
        }
        if ($search) {
            $builder->groupStart()
                   ->like('products.title', $search)
                   ->orLike('products.description', $search)
                   ->orLike('products.category', $search)
                   ->groupEnd();
        }
        if ($gender) {
            $builder->where('products.gender', $gender);
        }
        if ($minPrice) {
            $builder->where('products.price >=', $minPrice);
        }
        if ($maxPrice) {
            $builder->where('products.price <=', $maxPrice);
        }

        // Sorting
        switch ($sort) {
            case 'price_low':
                $builder->orderBy('products.price', 'ASC');
                break;
            case 'price_high':
                $builder->orderBy('products.price', 'DESC');
                break;
            case 'popular':
                $builder->orderBy('users.seller_reliability_score', 'DESC');
                break;
            default:
                $builder->orderBy('products.created_at', 'DESC');
        }

        $products = $builder->paginate(12);

        $data = [
            'user' => session()->get('logged_in') ? $this->userModel->find(session()->get('user_id')) : null,
            'products' => $products,
            'pager' => $this->productModel->pager,
            'filters' => [
                'category' => $category,
                'type' => $type,
                'search' => $search,
                'gender' => $gender,
                'min_price' => $minPrice,
                'max_price' => $maxPrice,
                'sort' => $sort,
            ],
        ];

        return view('buyer/browse', $data);
    }

    // Product Details
    public function productDetails($productId)
    {
        $product = $this->productModel->find($productId);

        if (!$product || $product['status'] !== 'approved') {
            return redirect()->to('/buyer')->with('error', 'Product not found');
        }

        // Get all images
        $images = $this->imageModel->where('product_id', $productId)
                                   ->orderBy('display_order', 'ASC')
                                   ->findAll();

        // Get seller info
        $seller = $this->userModel->find($product['seller_id']);

        // Get brand info
        $brand = null;
        if ($product['brand_id']) {
            $brand = $this->brandModel->find($product['brand_id']);
        }

        // Get similar products
        $similarProducts = $this->productModel
            ->select('products.*, product_images.image_path as primary_image')
            ->join('product_images', 'product_images.product_id = products.id AND product_images.is_primary = 1', 'left')
            ->where('products.category', $product['category'])
            ->where('products.id !=', $productId)
            ->where('products.status', 'approved')
            ->limit(4)
            ->findAll();

        $data = [
            'user' => session()->get('logged_in') ? $this->userModel->find(session()->get('user_id')) : null,
            'product' => $product,
            'images' => $images,
            'seller' => $seller,
            'brand' => $brand,
            'similarProducts' => $similarProducts,
        ];

        return view('buyer/product_details', $data);
    }

    // Make Offer (B1, B17, B18)
    public function makeOffer()
    {
        if (!session()->get('logged_in')) {
            return $this->response->setJSON(['success' => false, 'message' => 'Please login first']);
        }

        $validation = \Config\Services::validation();

        $rules = [
            'product_id' => 'required|integer',
            'offer_type' => 'required|in_list[buy,rent]',
            'offered_price' => 'required|decimal',
        ];

        if ($this->request->getPost('offer_type') === 'rent') {
            $rules['rental_start_date'] = 'required|valid_date';
            $rules['rental_end_date'] = 'required|valid_date';
            $rules['deposit_amount'] = 'required|decimal';
        }

        if (!$this->validate($rules)) {
            return $this->response->setJSON([
                'success' => false,
                'errors' => $validation->getErrors()
            ]);
        }

        $productId = $this->request->getPost('product_id');
        $product = $this->productModel->find($productId);

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

        $userId = session()->get('user_id');

        // Check for date conflicts if rental (B16, B22)
        if ($this->request->getPost('offer_type') === 'rent') {
            $startDate = $this->request->getPost('rental_start_date');
            $endDate = $this->request->getPost('rental_end_date');

            $conflicts = $this->offerModel
                ->where('product_id', $productId)
                ->where('status', 'accepted')
                ->groupStart()
                    ->where('rental_start_date <=', $endDate)
                    ->where('rental_end_date >=', $startDate)
                ->groupEnd()
                ->countAllResults();

            if ($conflicts > 0) {
                return $this->response->setJSON([
                    'success' => false,
                    'message' => 'Product already booked for selected dates'
                ]);
            }
        }

        // Map posted field `offered_price` to DB column `offer_price`
        $offerData = [
            'product_id' => $productId,
            'buyer_id' => $userId,
            'seller_id' => $product['seller_id'],
            'offer_type' => $this->request->getPost('offer_type'),
            'offer_price' => $this->request->getPost('offered_price'),
            'message' => $this->request->getPost('message'),
            'status' => 'pending',
        ];

        if ($offerData['offer_type'] === 'rent') {
            $offerData['rental_start_date'] = $this->request->getPost('rental_start_date');
            $offerData['rental_end_date'] = $this->request->getPost('rental_end_date');
            $offerData['deposit_amount'] = $this->request->getPost('deposit_amount');
        }

        $offerId = $this->offerModel->insert($offerData);

        // Notify seller (B18)
        $this->notificationModel->insert([
            'user_id' => $product['seller_id'],
            'title' => 'New Offer Received',
            'message' => "You have a new {$offerData['offer_type']} offer for {$product['title']}",
            'type' => 'offer_received',
            'related_id' => $offerId,
        ]);

        return $this->response->setJSON([
            'success' => true,
            'message' => 'Offer sent successfully!',
            'offer_id' => $offerId
        ]);
    }

    // My Offers (B10, B23)
    public function myOffers()
    {
        if (!session()->get('logged_in')) {
            return redirect()->to('/login');
        }

        $userId = session()->get('user_id');
        $user = $this->userModel->find($userId);

        // Use model helper which provides aliases/defaults for backward compatibility
        $offers = $this->offerModel->getBuyerOffers($userId);

        $data = [
            'user' => $user,
            'offers' => $offers,
        ];

        return view('buyer/my_offers', $data);
    }

    // Transaction History (B10)
    public function transactions()
    {
        if (!session()->get('logged_in')) {
            return redirect()->to('/login');
        }

        $userId = session()->get('user_id');
        $user = $this->userModel->find($userId);

        // Get accepted offers (which will become orders in Phase 2)
        $transactions = $this->offerModel
            ->select('offers.*, products.title, products.listing_type, products.id as product_id, product_images.image_path as primary_image, users.name as seller_name')
            ->join('products', 'products.id = offers.product_id')
            ->join('users', 'users.id = offers.seller_id')
            ->join('product_images', 'product_images.product_id = products.id AND product_images.is_primary = 1', 'left')
            ->where('offers.buyer_id', $userId)
            ->where('offers.status', 'accepted')
            ->orderBy('offers.created_at', 'DESC')
            ->findAll();

        // Add order_number and final_price for display
        foreach ($transactions as &$transaction) {
            $transaction['order_number'] = 'FLX' . str_pad($transaction['id'], 6, '0', STR_PAD_LEFT);
            $transaction['final_price'] = $transaction['offered_price'];
            if ($transaction['listing_type'] === 'rent') {
                $transaction['final_price'] += $transaction['deposit_amount'] ?? 0;
            }
            $transaction['status'] = $transaction['status'] ?? 'pending';
        }

        $data = [
            'user' => $user,
            'transactions' => $transactions,
        ];

        return view('buyer/transactions', $data);
    }

    // Cancel Offer
    public function cancelOffer($offerId)
    {
        if (!session()->get('logged_in')) {
            return $this->response->setJSON(['success' => false, 'message' => 'Not logged in']);
        }

        $userId = session()->get('user_id');
        $offer = $this->offerModel->find($offerId);

        if (!$offer || $offer['buyer_id'] != $userId) {
            return $this->response->setJSON(['success' => false, 'message' => 'Invalid offer']);
        }

        if ($offer['status'] !== 'pending') {
            return $this->response->setJSON(['success' => false, 'message' => 'Cannot cancel this offer']);
        }

        $this->offerModel->delete($offerId);

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

    // B11-B15: Review System
    public function submitReview()
    {
        if (!session()->get('logged_in')) {
            return $this->response->setJSON(['success' => false, 'message' => 'Please login first']);
        }

        $validation = \Config\Services::validation();
        $rules = [
            'order_id' => 'required|integer',
            'rating' => 'required|integer|greater_than[0]|less_than[6]',
            'comment' => 'required|min_length[10]|max_length[500]',
        ];

        if (!$this->validate($rules)) {
            return $this->response->setJSON([
                'success' => false,
                'errors' => $validation->getErrors()
            ]);
        }

        $userId = session()->get('user_id');
        $orderId = $this->request->getPost('order_id');

        // Check if user can review
        if (!$this->reviewModel->canReview($orderId, $userId)) {
            return $this->response->setJSON([
                'success' => false,
                'message' => 'You cannot review this order'
            ]);
        }

        $order = $this->orderModel->find($orderId);
        $reviewedId = ($order['buyer_id'] == $userId) ? $order['seller_id'] : $order['buyer_id'];

        $reviewData = [
            'order_id' => $orderId,
            'reviewer_id' => $userId,
            'reviewed_id' => $reviewedId,
            'reviewer_type' => 'buyer',
            'rating' => $this->request->getPost('rating'),
            'comment' => $this->request->getPost('comment'),
        ];

        $this->reviewModel->insert($reviewData);

        // Notify seller
        $this->notificationModel->insert([
            'user_id' => $reviewedId,
            'title' => 'New Review Received',
            'message' => "You have received a {$reviewData['rating']}-star review",
            'type' => 'review_received',
            'related_id' => $orderId,
        ]);

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

    // My Orders (for reviewing)
    public function myOrders()
    {
        if (!session()->get('logged_in')) {
            return redirect()->to('/login');
        }

        $userId = session()->get('user_id');
        $user = $this->userModel->find($userId);

        $orders = $this->orderModel
            ->select('orders.*, products.title as product_name, users.name as seller_name, product_images.image_path as primary_image')
            ->join('products', 'products.id = orders.product_id')
            ->join('users', 'users.id = orders.seller_id')
            ->join('product_images', 'product_images.product_id = products.id AND product_images.is_primary = 1', 'left')
            ->where('orders.buyer_id', $userId)
            ->orderBy('orders.created_at', 'DESC')
            ->findAll();

        // Check which orders can be reviewed
        foreach ($orders as &$order) {
            $order['can_review'] = $this->reviewModel->canReview($order['id'], $userId);
            $order['review'] = $this->reviewModel->where([
                'order_id' => $order['id'],
                'reviewer_id' => $userId
            ])->first();
        }

        $data = [
            'user' => $user,
            'orders' => $orders,
        ];

        return view('buyer/my_orders', $data);
    }
}
