<?php

namespace App\Services;

use App\Enums\ContentStatus;
use App\Http\Responses\ApiResponse;
use App\Models\Content;
use App\Models\ContentCategory;
use App\Models\ContentModelField;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;

class ContentService
{
    public function index(array $params): array
    {
        $query = Content::with(['category', 'model', 'user'])
            ->orderBy('sort', 'asc')
            ->orderBy('id', 'desc');

        if (! empty($params['keyword'])) {
            $query->where('title', 'like', "%{$params['keyword']}%");
        }

        if (! empty($params['category_id'])) {
            $query->where('category_id', $params['category_id']);
        }

        if (! empty($params['model_id'])) {
            $query->where('model_id', $params['model_id']);
        }

        if (isset($params['status']) && $params['status'] !== '') {
            $query->where('status', $params['status']);
        }

        $perPage = $params['per_page'] ?? 15;
        $paginator = $query->paginate($perPage);

        return ApiResponse::paginate($paginator);
    }

    public function store(array $data): array
    {
        $category = ContentCategory::find($data['category_id']);

        if (! $category) {
            return ApiResponse::error(40100, '分类不存在');
        }

        $modelId = $data['model_id'] ?? $category->model_id;

        if (! $modelId) {
            return ApiResponse::error(40401, '该分类未绑定模型');
        }

        $content = DB::transaction(function () use ($data, $modelId) {
            $content = Content::create([
                'category_id' => $data['category_id'],
                'model_id' => $modelId,
                'title' => $data['title'],
                'content' => $data['content'] ?? null,
                'summary' => $data['summary'] ?? null,
                'image' => $data['image'] ?? null,
                'author' => $data['author'] ?? null,
                'source' => $data['source'] ?? null,
                'publish_at' => $data['publish_at'] ?? null,
                'sort' => $data['sort'] ?? 0,
                'status' => $data['status'] ?? ContentStatus::DRAFT->value,
                'user_id' => $data['user_id'],
            ]);

            $this->insertExtensionData($content, $data);

            return $content;
        });

        return ApiResponse::success($content, '创建成功');
    }

    public function show(int $id): array
    {
        $content = Content::with(['category', 'model', 'user'])->find($id);

        if (! $content) {
            return ApiResponse::error(40302, '内容不存在');
        }

        $extensionData = $this->getExtensionData($content);

        $contentArray = $content->toArray();
        $contentArray['extension'] = $extensionData;

        return ApiResponse::success($contentArray);
    }

    public function update(int $id, array $data): array
    {
        $content = Content::find($id);

        if (! $content) {
            return ApiResponse::error(40302, '内容不存在');
        }

        DB::transaction(function () use ($content, $data) {
            $content->update([
                'category_id' => $data['category_id'] ?? $content->category_id,
                'title' => $data['title'] ?? $content->title,
                'content' => $data['content'] ?? $content->content,
                'summary' => $data['summary'] ?? $content->summary,
                'image' => $data['image'] ?? $content->image,
                'author' => $data['author'] ?? $content->author,
                'source' => $data['source'] ?? $content->source,
                'publish_at' => $data['publish_at'] ?? $content->publish_at,
                'sort' => $data['sort'] ?? $content->sort,
                'status' => $data['status'] ?? $content->status,
            ]);

            $this->updateExtensionData($content, $data);
        });

        return ApiResponse::success($content, '更新成功');
    }

    public function destroy(int $id): array
    {
        $content = Content::find($id);

        if (! $content) {
            return ApiResponse::error(40302, '内容不存在');
        }

        DB::transaction(function () use ($content) {
            $this->deleteExtensionData($content);
            $content->delete();
        });

        return ApiResponse::success(null, '删除成功');
    }

    public function batchDelete(array $ids): array
    {
        DB::transaction(function () use ($ids) {
            foreach ($ids as $id) {
                $content = Content::find($id);
                if ($content) {
                    $this->deleteExtensionData($content);
                    $content->delete();
                }
            }
        });

        return ApiResponse::success(null, '批量删除成功');
    }

    public function updateStatus(int $id, int $status): array
    {
        $content = Content::find($id);

        if (! $content) {
            return ApiResponse::error(40302, '内容不存在');
        }

        $updateData = ['status' => $status];

        if ($status === ContentStatus::PUBLISHED->value && ! $content->publish_at) {
            $updateData['publish_at'] = now();
        }

        $content->update($updateData);

        return ApiResponse::success($content, '操作成功');
    }

    public function getFormConfig(int $categoryId): array
    {
        $category = ContentCategory::find($categoryId);

        if (! $category || ! $category->model_id) {
            return ApiResponse::error(40401, '该分类未绑定模型');
        }

        $fields = ContentModelField::where('model_id', $category->model_id)
            ->where('status', 1)
            ->orderBy('sort', 'asc')
            ->orderBy('id', 'asc')
            ->get();

        return ApiResponse::success($fields);
    }

    protected function insertExtensionData(Content $content, array $data): void
    {
        $model = $content->model;

        if (! $model || ! Schema::hasTable($model->table_name)) {
            return;
        }

        $columns = Schema::getColumnListing($model->table_name);
        $excluded = ['id', 'create_time', 'update_time'];
        $extensionData = ['id' => $content->id];
        $extPayload = $data['extension'] ?? [];

        foreach ($columns as $column) {
            if (! in_array($column, $excluded) && array_key_exists($column, $extPayload)) {
                $extensionData[$column] = $extPayload[$column];
            }
        }

        if (count($extensionData) > 1) {
            $extensionData['create_time'] = now();
            $extensionData['update_time'] = now();
            DB::table($model->table_name)->insert($extensionData);
        }
    }

    protected function updateExtensionData(Content $content, array $data): void
    {
        $model = $content->model;

        if (! $model || ! Schema::hasTable($model->table_name)) {
            return;
        }

        $columns = Schema::getColumnListing($model->table_name);
        $excluded = ['id', 'create_time', 'update_time'];
        $extensionData = [];
        $extPayload = $data['extension'] ?? [];

        foreach ($columns as $column) {
            if (! in_array($column, $excluded) && array_key_exists($column, $extPayload)) {
                $extensionData[$column] = $extPayload[$column];
            }
        }

        if (empty($extensionData)) {
            return;
        }

        $extensionData['update_time'] = now();

        // upsert 模式：先尝试更新，若目标行不存在则插入
        $affected = DB::table($model->table_name)->where('id', $content->id)->update($extensionData);

        if ($affected === 0) {
            // 行不存在，执行插入（兼容旧数据无扩展记录的场景）
            $insertData = array_merge(['id' => $content->id], $extensionData);
            $insertData['create_time'] = now();
            DB::table($model->table_name)->insert($insertData);
        }
    }

    protected function getExtensionData(Content $content): ?object
    {
        $model = $content->model;

        if (! $model || ! Schema::hasTable($model->table_name)) {
            return null;
        }

        return DB::table($model->table_name)->where('id', $content->id)->first();
    }

    protected function deleteExtensionData(Content $content): void
    {
        $model = $content->model;

        if (! $model || ! Schema::hasTable($model->table_name)) {
            return;
        }

        DB::table($model->table_name)->where('id', $content->id)->delete();
    }
}
