<?php

namespace App\Repositories;

use App\Models\Booking;
use App\Models\Campaign;

class CampaignRepository extends BaseRepository
{
    protected $model;

    public function __construct()
    {
        $this->model = new Campaign();
    }

    public function getAllByOrganization(?string $orgHex)
    {
        $query = $this->model->query();
        return $this->applyOrganizationScope($query, $orgHex)->get();
    }

    public function getByIdInOrganization(string $id, ?string $orgHex)
    {
        $query = $this->model->where('id', $this->normalizeId($id));
        return $this->applyOrganizationScope($query, $orgHex)->first();
    }

    public function getWithBriefInOrganization(string $id, ?string $orgHex)
    {
        $query = $this->model->with('brief')->where('id', $this->normalizeId($id));
        return $this->applyOrganizationScope($query, $orgHex)->first();
    }

    public function getWithBookingsInOrganization(string $id, ?string $orgHex)
    {
        $query = $this->model->with([
            'brief',
            'assignedTo',
            'bookings.creator',
            'bookings.assignedTo',
            'bookings.videos',
            'bookings.bookingVideo',
            'bookings.bookingLivestream',
            'bookings.bookingNotes.user',
        ])->where('id', $this->normalizeId($id));

        return $this->applyOrganizationScope($query, $orgHex)->first();
    }

    /**
     * [TỐI ƯU] Phiên bản nhẹ: không load bookingNotes.user (lazy load khi cần),
     * thêm withCount cho booking_notes để hiển thị badge mà không cần load full content.
     * Chỉ load user của note sau này khi user click vào badge (lazy load).
     */
    public function getWithBookingsLight(string $id, ?string $orgHex)
    {
        $query = $this->model->with([
            'brief',
            'assignedTo',
            // Gộp withCount ngay trong closure của bookings để tránh override eager load
            'bookings' => function ($q) {
                $q->withCount('bookingNotes');
            },
            'bookings.creator',
            'bookings.assignedTo',
            'bookings.videos',
            'bookings.bookingVideo',
            'bookings.bookingLivestream',
            // KHÔNG load bookings.bookingNotes.user — lazy load khi user click badge
        ])->where('id', $this->normalizeId($id));

        return $this->applyOrganizationScope($query, $orgHex)->first();
    }

    public function searchByName(string $name, ?string $orgHex)
    {
        $query = $this->model->where('campaign_name', 'LIKE', "%{$name}%");
        return $this->applyOrganizationScope($query, $orgHex)->get();
    }

    public function create(array $data)
    {
        return $this->model->create($data);
    }

    public function updateInOrganization(string $id, array $data, ?string $orgHex)
    {
        $query = $this->model->where('id', $this->normalizeId($id));
        $campaign = $this->applyOrganizationScope($query, $orgHex)->first();

        if ($campaign) {
            $campaign->update($data);
        }

        return $campaign;
    }

    public function deleteInOrganization(string $id, ?string $orgHex)
    {
        $query = $this->model->where('id', $this->normalizeId($id));
        return $this->applyOrganizationScope($query, $orgHex)->delete();
    }

    public function paginateByOrganization(?string $orgHex, int $perPage = 15)
    {
        $query = $this->model->query();
        $query = $this->applyOrganizationScope($query, $orgHex);
        return $query->paginate($perPage);
    }

    public function paginateFilteredByOrganization(?string $orgHex, array $filters, int $perPage = 10)
    {
        $safePerPage = max(1, min(100, $perPage));

        $query = $this->model->query();
        $query = $this->applyOrganizationScope($query, $orgHex);

        $query->with('brief')
              ->with('assignedTo')
              ->withCount(['bookings'])
              ->withSum('bookings', 'cast_cost')
              ->withSum('bookings', 'sample_cost')
              ->withSum('bookings', 'shipping_cost')
              ->addSelect([
                  'total_cost' => Booking::selectRaw('COALESCE(SUM(cast_cost + sample_cost + shipping_cost), 0)')
                      ->whereColumn('campaign_id', 'campaigns.id')
                      ->where('organization_id', $this->normalizeId($orgHex)),
              ]);

        $keyword = trim((string)($filters['keyword'] ?? ''));
        if ($keyword !== '') {
            $like = '%' . $keyword . '%';
            $query->where(function ($q) use ($like) {
                $q->where('campaign_name', 'LIKE', $like)
                    ->orWhere('product_name', 'LIKE', $like);
            });
        }

        $status = trim((string)($filters['status'] ?? ''));
        if ($status !== '') {
            $query->where('status', $status);
        }

        $sortMap = [
            'campaign_name' => 'campaign_name',
            'product_name' => 'product_name',
            'status' => 'status',
            'start_date' => 'start_date',
            'end_date' => 'end_date',
            'koc_count' => 'bookings_count',
            'bookings_count' => 'bookings_count',
            'cast_cost' => 'bookings_sum_cast_cost',
            'sample_cost' => 'bookings_sum_sample_cost',
            'shipping_cost' => 'bookings_sum_shipping_cost',
            'total_cost' => 'total_cost',
            'created_at' => 'created_at',
        ];
        $sortField = $filters['sort_field'] ?? null;
        $sortDirection = strtolower((string)($filters['sort_direction'] ?? 'asc')) === 'desc' ? 'desc' : 'asc';

        if (is_string($sortField) && isset($sortMap[$sortField])) {
            $query->orderBy($sortMap[$sortField], $sortDirection);
        } else {
            $query->orderBy('created_at', 'desc');
        }

        return $query->paginate($safePerPage);
    }
}
