<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Http\Requests\Admin\ProductConfigOptionGroup\ArchiveGroupRequest;
use App\Http\Requests\Admin\ProductConfigOptionGroup\DuplicateGroupRequest;
use App\Http\Requests\Admin\ProductConfigOptionGroup\ForceDeleteGroupRequest;
use App\Http\Requests\Admin\ProductConfigOptionGroup\RestoreGroupRequest;
use App\Http\Requests\Admin\ProductConfigOptionGroupEditRequest;
use App\Http\Requests\Admin\ProductConfigOptionGroupIndexRequest;
use App\Http\Requests\Admin\ProductConfigOptionGroupRecordsRequest;
use App\Http\Requests\Admin\ProductConfigOptionGroupStoreRequest;
use App\Http\Requests\Admin\ProductConfigOptionGroupUpdateRequest;
use App\Models\Currency;
use App\Models\ProductConfigOptionGroup;
use App\Http\Requests\Admin\ProductConfigOptionGroup\ReorderOptionsRequest;
use App\Http\Requests\Admin\ProductConfigOptionGroup\SyncProductsRequest;
use App\Services\Admin\ProductConfigOptionGroup\ArchiveGroupService;
use App\Services\Admin\ProductConfigOptionGroup\DuplicateGroupService;
use App\Services\Admin\ProductConfigOptionGroup\ForceDeleteGroupService;
use App\Services\Admin\ProductConfigOptionGroup\ReorderOptionsService;
use App\Services\Admin\ProductConfigOptionGroup\RestoreGroupService;
use App\Services\Admin\ProductConfigOptionGroup\SyncProductsService;
use App\Traits\LogsAdminActivity;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class ProductConfigOptionGroupController extends Controller
{
    use LogsAdminActivity;
    public function index(ProductConfigOptionGroupIndexRequest $request)
    {
        return view('admin.product-config-option-groups.index');
    }

    public function create(ProductConfigOptionGroupIndexRequest $request)
    {
        return view('admin.product-config-option-groups.create');
    }

    public function records(ProductConfigOptionGroupRecordsRequest $request)
    {
        $query = ProductConfigOptionGroup::withCount('options');

        $archivedFilter = $request->query('archived', 'no');
        if ($archivedFilter === 'only') {
            $query->whereNotNull('archived_at');
        } elseif ($archivedFilter === 'all') {
            // no filter
        } else {
            $query->whereNull('archived_at'); // default: hide archived
        }

        // Arama
        if ($request->has('search') && ! empty($request->search['value'])) {
            $search = $request->search['value'];
            $query->where(function ($q) use ($search) {
                $q->where('name', 'like', "%{$search}%")
                    ->orWhere('description', 'like', "%{$search}%");
            });
        }

        // Her zaman order kolonuna göre sırala
        $query->orderBy('order', 'asc');

        // Sayfalama
        $total = $query->count();
        $start = $request->input('start', 0);
        $length = $request->input('length', 10);
        $groups = $query->skip($start)->take($length)->get();

        $data = $groups->map(function ($group) {
            $row = $group->toArray();
            $row['status_key'] = $group->isArchived() ? 'archived' : ($group->hidden ? 'hidden' : 'active');
            return $row;
        })->values()->toArray();

        return response()->json([
            'draw' => $request->input('draw'),
            'recordsTotal' => $total,
            'recordsFiltered' => $total,
            'data' => $data,
        ]);
    }

    public function store(ProductConfigOptionGroupStoreRequest $request)
    {
        try {
            DB::beginTransaction();

            $group = ProductConfigOptionGroup::create([
                'name' => $request->name,
                'description' => $request->description,
                'order' => $request->order ?? 1,
                'hidden' => $request->hidden ?? false,
            ]);

            $this->logCreated($group, "Created product config option group #{$group->id} - {$group->name}");

            DB::commit();

            return response()->json([
                'success' => true,
                'message' => __('admin/product-config-option-groups.messages_created'),
                'data' => $group,
            ]);
        } catch (\Exception $e) {
            DB::rollBack();
            Log::error('ProductConfigOptionGroup store error: '.$e->getMessage());

            return response()->json([
                'success' => false,
                'message' => __('admin/product-config-option-groups.messages_error'),
            ], 500);
        }
    }

    public function edit(ProductConfigOptionGroupEditRequest $request, ProductConfigOptionGroup $productConfigOptionGroup)
    {
        // Option create/edit drawer'ının "Değer ekle" grid'i currency başına satır üretir;
        // drawer partial'ın kendi @vite scripti innerHTML enjeksiyonunda çalışmadığından
        // currency listesini grup sayfasından pageConfig ile veriyoruz (bkz. config-option-form.js).
        $currencies = Currency::where('status', true)->get();

        return view('admin.product-config-option-groups.edit', compact('productConfigOptionGroup', 'currencies'));
    }

    public function update(ProductConfigOptionGroupUpdateRequest $request, ProductConfigOptionGroup $productConfigOptionGroup)
    {
        try {
            DB::beginTransaction();

            $productConfigOptionGroup->update([
                'name' => $request->name,
                'description' => $request->description,
                'order' => $request->order ?? 1,
                'hidden' => $request->hidden ?? false,
            ]);

            $this->logUpdated($productConfigOptionGroup, "Updated product config option group #{$productConfigOptionGroup->id} - {$productConfigOptionGroup->name}");

            DB::commit();

            return response()->json([
                'success' => true,
                'message' => __('admin/product-config-option-groups.messages_updated'),
                'data' => $productConfigOptionGroup,
            ]);
        } catch (\Exception $e) {
            DB::rollBack();
            Log::error('ProductConfigOptionGroup update error: '.$e->getMessage());

            return response()->json([
                'success' => false,
                'message' => __('admin/product-config-option-groups.messages_error'),
            ], 500);
        }
    }

    /**
     * Resolve the acting admin guard-agnostically. The web route uses the
     * `admin` guard (session); the api/v1 route uses Sanctum (config guard
     * `web`), where `user('admin')` is null and the authenticated Admin is
     * the token's tokenable resolved by the default resolver. (PRC-496)
     */
    private function currentAdmin($request = null)
    {
        $request = $request ?: request();

        return auth('admin')->user() ?? $request->user();
    }

    public function destroy($id)
    {
        $group = ProductConfigOptionGroup::findOrFail($id);
        if (! $this->currentAdmin()?->can('archive', $group)) {
            abort(403);
        }
        try {
            app(ArchiveGroupService::class)->execute($group, $this->currentAdmin(), request()->ip());
            return response()->json(['success' => true, 'message' => trans('admin/product-config-option-groups.archived_success')]);
        } catch (\DomainException $e) {
            return response()->json(['success' => false, 'message' => $e->getMessage()], 409);
        }
    }

    public function archive(ArchiveGroupRequest $request, $id)
    {
        try {
            app(ArchiveGroupService::class)->execute(
                $request->input('_group'),
                $this->currentAdmin($request),
                $request->ip()
            );
            return response()->json(['success' => true, 'message' => trans('admin/product-config-option-groups.archived_success')]);
        } catch (\DomainException $e) {
            return response()->json(['success' => false, 'message' => $e->getMessage()], 409);
        }
    }

    public function restore(RestoreGroupRequest $request, $id)
    {
        try {
            app(RestoreGroupService::class)->execute(
                $request->input('_group'),
                $this->currentAdmin($request),
                $request->ip()
            );
            return response()->json(['success' => true, 'message' => trans('admin/product-config-option-groups.restored_success')]);
        } catch (\DomainException $e) {
            return response()->json(['success' => false, 'message' => $e->getMessage()], 409);
        }
    }

    public function forceDelete(ForceDeleteGroupRequest $request, $id)
    {
        try {
            app(ForceDeleteGroupService::class)->execute(
                $request->input('_group'),
                $this->currentAdmin($request),
                $request->ip()
            );
            return response()->json(['success' => true, 'message' => trans('admin/product-config-option-groups.force_deleted_success')]);
        } catch (\DomainException $e) {
            return response()->json(['success' => false, 'message' => $e->getMessage()], 422);
        }
    }

    public function duplicate(DuplicateGroupRequest $request, $id)
    {
        try {
            $clone = app(DuplicateGroupService::class)->execute(
                $request->input('_group'),
                $this->currentAdmin($request),
                $request->ip()
            );
            return response()->json([
                'success' => true,
                'message' => trans('admin/product-config-option-groups.duplicated_success'),
                'redirect' => route('admin.product-config-option-groups.edit', $clone->id),
            ]);
        } catch (\DomainException $e) {
            return response()->json(['success' => false, 'message' => $e->getMessage()], 422);
        }
    }

    public function reorderOptions(ReorderOptionsRequest $request, $id)
    {
        try {
            app(ReorderOptionsService::class)->execute(
                $request->input('_group'),
                $this->currentAdmin($request),
                $request->input('option_ids'),
                $request->ip()
            );
            return response()->json(['success' => true]);
        } catch (\DomainException $e) {
            return response()->json(['success' => false, 'message' => $e->getMessage()], 422);
        }
    }

    public function syncProducts(SyncProductsRequest $request, $id)
    {
        try {
            app(SyncProductsService::class)->execute(
                $request->input('_group'),
                $this->currentAdmin($request),
                $request->input('attach_ids', []),
                $request->input('detach_ids', []),
                $request->ip()
            );
            return response()->json(['success' => true, 'message' => trans('admin/product-config-option-groups.products_synced')]);
        } catch (\DomainException $e) {
            return response()->json(['success' => false, 'message' => $e->getMessage()], 422);
        }
    }

    public function productsList(\Illuminate\Http\Request $request, $id)
    {
        $group = \App\Models\ProductConfigOptionGroup::findOrFail($id);
        if (! $this->currentAdmin($request)?->can('syncProducts', $group)) {
            abort(403);
        }

        $attachedIds = \App\Models\ProductConfigOptionRelation::where('group_id', $id)
            ->distinct('product_id')->pluck('product_id')->all();

        $query = \App\Models\Product::query()->orderBy('name');

        if ($search = $request->query('search')) {
            // Handle DataTable's nested search.value or plain search param
            $searchTerm = is_array($search) ? ($search['value'] ?? '') : $search;
            if ($searchTerm) {
                $query->where('name', 'like', "%{$searchTerm}%");
            }
        }

        $status = $request->query('status_filter');
        if ($status === 'attached') {
            $query->whereIn('id', $attachedIds ?: [0]);
        } elseif ($status === 'not_attached') {
            if (! empty($attachedIds)) {
                $query->whereNotIn('id', $attachedIds);
            }
        }

        $total = (clone $query)->count();
        $start = (int) $request->query('start', 0);
        $length = (int) $request->query('length', 25);

        $rows = $query->skip($start)->take($length)->get()->map(function ($p) use ($attachedIds) {
            return [
                'id' => $p->id,
                'name' => $p->name,
                'attached' => in_array($p->id, $attachedIds),
            ];
        });

        return response()->json([
            'draw' => (int) $request->query('draw', 0),
            'recordsTotal' => $total,
            'recordsFiltered' => $total,
            'data' => $rows,
        ]);
    }
}
