<?php

declare(strict_types=1);

namespace App\Http\Controllers;

use App\Http\Requests\Producer\StoreProducerProfileRequest;
use App\Http\Resources\ProducerResource;
use App\Models\Producer;
use App\Models\Rating;
use App\Models\User;
use App\Support\ApiResponse;
use Exception;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Gate;

class ProducerController extends Controller
{
    public function index(Request $request)
    {
        Gate::authorize('viewAny', Producer::class);

        $query = Producer::query()
            ->with(['user', 'province', 'county'])
            ->withCount('products');

        if ($request->filled('status')) {
            $query->where('status', $request->string('status'));
        }

        if ($request->filled('search')) {
            $search = $request->string('search');
            $query->where(function ($q) use ($search): void {
                $q->where('brand_name', 'like', "%{$search}%")
                    ->orWhereHas('user', function ($uq) use ($search): void {
                        $uq->where('first_name', 'like', "%{$search}%")
                            ->orWhere('last_name', 'like', "%{$search}%")
                            ->orWhere('cellphone', 'like', "%{$search}%");
                    });
            });
        }

        if (! $request->user()?->hasRole('admin')) {
            $query->where('status', Producer::STATUS_APPROVED);
        }

        $perPage = min($request->integer('per_page', 15), 50);

        return ProducerResource::collection(
            $request->boolean('noPaginate') ? $query->get() : $query->paginate($perPage)
        );
    }

    public function store(StoreProducerProfileRequest $request)
    {
        Gate::authorize('create', Producer::class);

        try {
            DB::beginTransaction();

            $user = $this->resolveOrCreateUser($request, User::ROLE_PRODUCER, User::ACCOUNT_PRODUCER);

            if ($user->producer) {
                DB::rollBack();

                return ApiResponse::badRequest('برای این کاربر قبلاً پروفایل تولیدکننده ثبت شده است.');
            }

            $producerData = $this->producerPayload($request);
            $producerData['user_id'] = $user->id;
            $producerData['created_by'] = Auth::id() ?? $user->id;
            $producerData['status'] = Producer::STATUS_PENDING;

            // DB requires non-null for some legacy columns
            $producerData['activity_main_category'] = $producerData['activity_main_category'] ?? 'نامشخص';
            $producerData['business_license'] = $producerData['business_license'] ?? [];
            $producerData['work_latitude'] = $producerData['work_latitude'] ?? 0;

            $producer = Producer::create($producerData);
            $user->syncRoles([User::ROLE_PRODUCER, User::ROLE_USER]);
            $user->update(['account_type' => User::ACCOUNT_PRODUCER]);

            DB::commit();
        } catch (Exception $exception) {
            DB::rollBack();

            return ApiResponse::response(message: $exception->getMessage(), status: 419);
        }

        return ApiResponse::created(
            new ProducerResource($producer->load(['user', 'province', 'county'])),
            $producer->status === Producer::STATUS_APPROVED
                ? 'تولیدکننده ثبت شد.'
                : 'درخواست تولیدکننده ثبت شد و در انتظار تایید ادمین است.'
        );
    }

    public function show(Producer $producer)
    {
        Gate::authorize('view', $producer);

        $producer->load(['user', 'province', 'county'])
            ->loadCount(['products', 'projects']);

        $ratings = Rating::query()
            ->where('rateable_type', Producer::class)
            ->where('rateable_id', $producer->id)
            ->with('user:id,first_name,last_name,avatar')
            ->latest()
            ->limit(20)
            ->get();

        $producer->setAttribute(
            'satisfaction_avg',
            $ratings->avg('score') !== null ? round((float) $ratings->avg('score'), 1) : null
        );
        $producer->setAttribute('ratings_list', $ratings->map(fn (Rating $rating) => [
            'id' => $rating->id,
            'score' => (int) $rating->score,
            'comment' => $rating->comment ?? $rating->body ?? null,
            'user' => $rating->user ? [
                'id' => $rating->user->id,
                'name' => trim(($rating->user->first_name ?? '') . ' ' . ($rating->user->last_name ?? '')),
            ] : null,
            'created_at' => $rating->created_at?->toISOString(),
        ])->values());

        return new ProducerResource($producer);
    }

    public function update(StoreProducerProfileRequest $request, Producer $producer)
    {
        Gate::authorize('update', $producer);

        if (
            ! $request->user()->hasRole('admin')
            && ! in_array($producer->status, [Producer::STATUS_PENDING, Producer::STATUS_NEEDS_EDIT, Producer::STATUS_REJECTED], true)
        ) {
            return ApiResponse::forbidden('این پروفایل قابل ویرایش نیست.');
        }

        try {
            DB::beginTransaction();

            $this->updateUserPersonal($request, $producer->user);

            $data = $this->producerPayload($request);
            $data['updated_by'] = Auth::id();

            if (! $request->user()->hasRole('admin') && $producer->status === Producer::STATUS_NEEDS_EDIT) {
                $data['status'] = Producer::STATUS_PENDING;
                $data['admin_reason'] = null;
            }

            $producer->update($data);
            DB::commit();
        } catch (Exception $exception) {
            DB::rollBack();

            return ApiResponse::response(message: $exception->getMessage(), status: 419);
        }

        return new ProducerResource($producer->fresh()->load(['user', 'province', 'county']));
    }

    public function destroy(Producer $producer)
    {
        Gate::authorize('delete', $producer);
        $producer->delete();

        return ApiResponse::success(message: 'با موفقیت حذف شد');
    }

    private function resolveOrCreateUser(StoreProducerProfileRequest $request, string $role, string $accountType): User
    {
        if ($request->user()) {
            return $request->user();
        }

        abort(401, 'برای ثبت پروفایل تولیدکننده باید وارد شوید.');
    }

    private function updateUserPersonal(StoreProducerProfileRequest $request, ?User $user): void
    {
        if (! $user) {
            return;
        }

        $fields = $request->only([
            'first_name', 'last_name', 'avatar', 'national_code', 'national_cart_image',
            'email', 'phone', 'dob', 'address', 'province_id', 'county_id', 'postal_code',
            'latitude', 'longitude',
        ]);

        $user->update(array_filter($fields, fn ($v) => $v !== null));
    }

    private function producerPayload(StoreProducerProfileRequest $request): array
    {
        return $request->safe()->only([
            'brand_name', 'activity_main_category', 'activity_sub_category', 'activity_product',
            'unit_capacity', 'unit_area', 'work_email', 'work_phone',
            'work_province_id', 'work_county_id', 'work_address', 'work_postal_code',
            'work_latitude', 'work_longitude', 'business_license', 'education_certificates',
            'skill_certificates', 'work_experience', 'ownership_document',
            'lease_start_date', 'lease_end_date', 'unit_images', 'unit_videos',
        ]);
    }
}
