<?php

namespace App\Services;

use App\Models\Commons\Category;
use App\Models\Commons\CategoryTemplate;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;

class CategoryTemplateService extends Service
{
    public function index(int $categoryId, array $params)
    {
        $tenantId = $this->tenantId();
        $size = (int) ($params['size'] ?? 20);

        return CategoryTemplate::query()
            ->where('tenant_id', $tenantId)
            ->where('category_id', $categoryId)
            ->orderByDesc('version_no')
            ->paginate($size);
    }

    public function store(int $categoryId, array $data)
    {
        $tenantId = $this->tenantId();
        $userId = $this->apiUserId();
        $this->assertCategoryExists($tenantId, $categoryId);

        $v = Validator::make($data, [
            'version_no' => 'required|integer|min:1',
            'template_json' => 'required|json',
            'applied_at' => 'required|date',
            'remarks' => 'nullable|string|max:255',
        ]);
        $payload = $v->validate();

        $dup = CategoryTemplate::query()
            ->where('tenant_id', $tenantId)
            ->where('category_id', $categoryId)
            ->where('version_no', $payload['version_no'])
            ->exists();
        if ($dup) {
            throw new BadRequestHttpException(__('error.duplicate_key')); // version_no 중복
        }

        $payload['tenant_id'] = $tenantId;
        $payload['category_id'] = $categoryId;
        $payload['created_by'] = $userId;

        return CategoryTemplate::create($payload);
    }

    public function show(int $tplId)
    {
        $tenantId = $this->tenantId();

        $tpl = CategoryTemplate::query()
            ->where('tenant_id', $tenantId)
            ->find($tplId);

        if (! $tpl) {
            throw new BadRequestHttpException(__('error.not_found'));
        }

        return $tpl;
    }

    public function update(int $tplId, array $data)
    {
        $tenantId = $this->tenantId();
        $userId = $this->apiUserId();

        $tpl = CategoryTemplate::query()
            ->where('tenant_id', $tenantId)
            ->find($tplId);

        if (! $tpl) {
            throw new BadRequestHttpException(__('error.not_found'));
        }

        $v = Validator::make($data, [
            'template_json' => 'nullable|json',
            'applied_at' => 'nullable|date',
            'remarks' => 'nullable|string|max:255',
        ]);
        $payload = $v->validate();
        $payload['updated_by'] = $userId;

        $tpl->update($payload);

        return $tpl->refresh();
    }

    public function destroy(int $tplId): void
    {
        $tenantId = $this->tenantId();

        $tpl = CategoryTemplate::query()
            ->where('tenant_id', $tenantId)
            ->find($tplId);

        if (! $tpl) {
            throw new BadRequestHttpException(__('error.not_found'));
        }
        $tpl->delete();
    }

    /**
     * 적용 정책:
     * - categories.active_template_version (또는 별도 맵 테이블)에 version_no 반영
     * - (옵션) template_json 기반으로 category_fields를 실제로 갱신하려면 여기서 동기화
     */
    public function apply(int $categoryId, int $tplId): void
    {
        $tenantId = $this->tenantId();
        $userId = $this->apiUserId();

        $tpl = CategoryTemplate::query()
            ->where('tenant_id', $tenantId)
            ->where('category_id', $categoryId)
            ->find($tplId);

        if (! $tpl) {
            throw new BadRequestHttpException(__('error.not_found'));
        }

        DB::transaction(function () {
            // 1) categories 테이블에 활성 버전 반영(컬럼이 있다면)
            // Category::where('tenant_id', $tenantId)->where('id', $categoryId)->update([
            //     'active_template_version' => $tpl->version_no,
            //     'updated_by' => $userId,
            // ]);

            // 2) (선택) template_json → category_fields 동기화
            //    - 추가/수정/삭제 전략은 운영정책에 맞게 구현
            //    - 여기서는 예시로 "fields" 배열만 처리
            // $snapshot = json_decode($tpl->template_json, true);
            // foreach (($snapshot['fields'] ?? []) as $i => $f) {
            //     // key, name, type, required, default, options 매핑 ...
            // }
        });
    }

    public function preview(int $categoryId, int $tplId): array
    {
        $tenantId = $this->tenantId();

        $tpl = CategoryTemplate::query()
            ->where('tenant_id', $tenantId)
            ->where('category_id', $categoryId)
            ->find($tplId);

        if (! $tpl) {
            throw new BadRequestHttpException(__('error.not_found'));
        }

        $json = json_decode($tpl->template_json, true);
        if (! is_array($json)) {
            throw new BadRequestHttpException(__('error.invalid_payload'));
        }

        // 프론트 렌더링 편의 구조로 가공 가능
        return $json;
    }

    public function diff(int $categoryId, int $a, int $b): array
    {
        $tenantId = $this->tenantId();

        $aTpl = CategoryTemplate::query()
            ->where('tenant_id', $tenantId)->where('category_id', $categoryId)
            ->where('version_no', $a)->first();

        $bTpl = CategoryTemplate::query()
            ->where('tenant_id', $tenantId)->where('category_id', $categoryId)
            ->where('version_no', $b)->first();

        if (! $aTpl || ! $bTpl) {
            throw new BadRequestHttpException(__('error.not_found'));
        }

        $aj = json_decode($aTpl->template_json, true) ?: [];
        $bj = json_decode($bTpl->template_json, true) ?: [];

        // 아주 단순한 diff 예시 (fields 키만 비교)
        $aKeys = collect($aj['fields'] ?? [])->pluck('key')->all();
        $bKeys = collect($bj['fields'] ?? [])->pluck('key')->all();

        return [
            'added' => array_values(array_diff($bKeys, $aKeys)),
            'removed' => array_values(array_diff($aKeys, $bKeys)),
            // 변경(diff in detail)은 정책에 맞게 확장
        ];
    }

    private function assertCategoryExists(int $tenantId, int $categoryId): void
    {
        $exists = Category::query()
            ->where('tenant_id', $tenantId)
            ->where('id', $categoryId)
            ->exists();
        if (! $exists) {
            throw new BadRequestHttpException(__('error.category_not_found'));
        }
    }
}
