<?php

namespace App\Http\Controllers\API;

use App\Http\Controllers\Controller;
use App\Http\Requests\API\Container\CreateOrUpdateRequest;
use App\Http\Resources\API\ContainerDetailResource;
use App\Http\Resources\API\ContainerReportResource;
use App\Http\Resources\API\FileAttachmentResource;
use App\Http\Resources\API\LibraryReportResource;
use App\Models\Approval;
use App\Models\Container;
use App\Models\ContainerContent;
use App\Models\Enums\ActionObjectType;
use App\Models\Enums\FileObjectType;
use App\Models\Enums\ObjectAction;
use App\Models\File;
use App\Models\Folder;
use App\Models\Library;
use App\Repositories\ActionRepository;
use App\Repositories\CustomFieldRepository;
use App\Services\File\FileAssociationService;
use App\Services\File\ImageUrlService;
use App\Services\History\ModelChangeDetector;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;


class ContainerController extends Controller
{
    /**
     * Display a listing of the resource.
     */
    public function index(Request $request)
    {
        $pageSize=$request->get('page_size') ?? 10;
        $containers = Container::query()->allowed()->filter($request->all())->paginate($pageSize);

        $total = $containers->total();
        $foldsCount = Folder::query()
            ->where('object_type','container')
            ->where('parent_id',0)
            ->whereIn("object_id", $containers->pluck("id")->toArray())
            ->selectRaw("count(*) as cut, object_id")
            ->groupBy("object_id")
            ->pluck("cut", "object_id");

        $fileCount = File::query()
            ->where('object_type','container')
            ->whereIn('object_id',$containers->pluck("id")->toArray())
            ->where("folder_id", 0)
            ->where("is_latest_version", 1)
            ->selectRaw("count(*) as cut, object_id")
            ->groupBy("object_id")
            ->pluck("cut", "object_id");

        $index=1;
        $containers = $containers->map(function (Container $container) use ($foldsCount,$fileCount,&$index) {
            $container->itemCount =$foldsCount->get($container->id, 0)+$fileCount->get($container->id, 0);
            $container->type = 'container';
            $container->uniId = $container->type . '_' . $container->id;
            $container->display_id=(string)$index++;
            return $container;
        });

        return $this->success([
            'data' => $containers,
            'total' => $total,
        ]);

        //return ContainerResource::collection($containers);
    }

    /**
     * Store a newly created resource in storage.
     */
    public function store(
        CreateOrUpdateRequest $request,
        ImageUrlService $imageUrlService,
        FileAssociationService $service,
        CustomFieldRepository $customFieldRepo
    )
    {
        $formData = [
            ...$request->all(),
            'company_id' => Auth::user()->company_id,
            'created_by' => Auth::id(),
            'whitelist' => $request->whitelist ? sprintf(",%s,", implode(',', $request->whitelist)) : null,
        ];

        $service->check(
            $request->get("file_ids", []),
            FileObjectType::CONTAINER,
            $request->get("file_uuid"),
        );

        $service->fileNameNamingRuleCheckByContainer($request->library_id, (int)$request->naming_rule_id);

        if ($request->has("naming_rule_id") && $request->get("naming_rule_id") > 0) {
            $keys = $customFieldRepo->keysByGroup($request->get("naming_rule_id"));
            $formData['naming_rules'] = $request->only($keys);
        }

        $container = new Container();
        $container->mergeFillable(['company_id', 'created_by']);
        $container->fill($formData);
        $container->save();

        $service->association($container->id);

        $files = File::query()->where('object_id', $container->id)
            ->where('object_type', ActionObjectType::CONTAINER)
            ->where('source', 1)
            ->pluck("id")
            ->sort();

        $contentFormData = [
            'description' => $imageUrlService->interceptImageUrl($request->description),
            'container_id' => $container->id,
            'created_by' => Auth::id(),
            'name' => $request->name,
            'files' => $files->implode(",") ?: null
        ];

        ContainerContent::query()->create($contentFormData);

        ActionRepository::createByContainer($container, ObjectAction::CREATED);

        return $this->created();
    }

    /**
     * Display the specified resource.
     */
    public function show(string $id)
    {
        $container = Container::query()->allowed()
            ->when(\request("version") > 0, fn($query) => $query->where("version", ">=", \request("version")))
            ->findOrFail($id);

        return new ContainerDetailResource($container);
    }

    /**
     * Update the specified resource in storage.
     */
    public function update(
        CreateOrUpdateRequest $request,
        ImageUrlService $imageUrlService,
        CustomFieldRepository $customFieldRepo,
        string $id
    )
    {
        $container = Container::query()->allowed()->findOrFail($id);

        $formData = [
            ...$request->all(),
            'whitelist' => $request->whitelist ? sprintf(",%s,", implode(',', $request->whitelist)) : null,
            'description' => $imageUrlService->interceptImageUrl($request->description) ,
        ];

        if ($request->has("naming_rule_id") && $request->get("naming_rule_id") > 0) {
            $keys = $customFieldRepo->keysByGroup($request->get("naming_rule_id"));
            $formData['naming_rules'] = $request->only($keys);
        }

        $container->fill($formData);
        $changes = ModelChangeDetector::detector(ActionObjectType::CONTAINER, $container);

        $files = File::query()->where('object_id', $container->id)
            ->where('object_type', ActionObjectType::CONTAINER)
            ->where('source', 1)
            ->pluck("id")
            ->sort();

        $contentFormData = [
            'description' => $imageUrlService->interceptImageUrl($request->description),
            'name' => $request->name,
            'files' => $files->implode(",") ?: null
        ];

        $containerContent = $container->content;
        $containerContent->fill($contentFormData);
        $contentChange = ModelChangeDetector::detector(ActionObjectType::CONTAINER_CONTENT, $containerContent);

        if ($contentChange) {
            $container->version++;
            $changes = array_merge($changes, $contentChange);

            ContainerContent::query()->create([
                ...$contentFormData,
                'container_id' => $container->id,
                'created_by' => Auth::id(),
                'version' => $container->version,
            ]);
        }

        $container->save();

        ActionRepository::createByContainer($container, ObjectAction::EDITED, objectChanges: $changes);

        return $this->noContent();
    }

    /**
     * Remove the specified resource from storage.
     */
    public function destroy(string $id)
    {
        $container = Container::query()->allowed()->findOrFail($id);

        $container->delete();

        Approval::query()->where('object_type','container')->where('object_id',$id)->delete();

        ActionRepository::createByContainer($container, ObjectAction::DELETED);

        return $this->noContent();
    }

    public function linkage(string $libraryId)
    {
        $items = Container::select(['id', 'name'])
            ->withCount(['folder' => function ($query) {
                $query->where('parent_id', 0);
            }])
            ->withCount(['files' => function ($query) {
                $query->where('folder_id', 0);
            }])
            ->allowed()->where("library_id", $libraryId)->get()->each(function ($items) {

            // 设置固定的type值
            $items->type = 'container';
            $items->uniId=$items->type.'_'.$items->id;
        });

        return $this->success([
            'data' => $items
        ]);
    }

    public function attachments(Request $request){
        $folderObjectType = FileObjectType::from($request->object_type);
        $object=$folderObjectType->modelBuilderAllowed()->findOrFail($request->object_id);
        $pageSize = $request->get('page_size') ?? 10;
        if($folderObjectType->value==='asset'){
            $object->load('requirements');
            $requirementsId=$object->requirements->pluck('id');
            if(!$requirementsId->isEmpty()){
                $filesWithRequirements = File::query()->where('object_type','requirement')
                    ->whereIn('object_id',$requirementsId)
                    ->where('is_latest_version',1)
                    ->where('source',1)
                    ->paginate($pageSize);

                $filesWithRequirements->transform(function (File $file) use ($object) {
                    $requirement = $object->requirements->where('id',$file->object_id)->first();
                    $file->source_name = $requirement ? $requirement->title : null;
                    $file->type = 'requirement';
                    return $file;
                });
                make_display_id($filesWithRequirements,$pageSize);
//                return FileAttachmentResource::collection($filesWithRequirements);
                return $this->success([
                    'data' => FileAttachmentResource::collection($filesWithRequirements),
                    'total' => $filesWithRequirements->total()
                ]);
            }
        }else if($folderObjectType->value==='project'){
            $object->load('tasks');
            $tasksId=$object->tasks->pluck('id');
            if(!$tasksId->isEmpty()){
                $filesWithTasks=File::query()->where('object_type','task')
                    ->whereIn('object_id',$tasksId)
                    ->where('is_latest_version',1)
                    ->where('source',1)
                    ->paginate($pageSize);

                $filesWithTasks->transform(function (File $file) use ($object) {
                    $task = $object->tasks->where('id',$file->object_id)->first();
                    $file->source_name = $task ? $task->name : null;
                    $file->project_id=$task ?$task->project_id:null;
                    $file->type = 'tasks';
                    return $file;
                });

                make_display_id($filesWithTasks,$pageSize);
//                return FileAttachmentResource::collection($filesWithTasks);

                return $this->success([
                    'data' => FileAttachmentResource::collection($filesWithTasks),
                    'total' => $filesWithTasks->total()
                ]);

            }
        }

        return $this->noContent();

    }
    public function containerReport(Request $request){

        $companyId=Auth::user()->company_id;
        $librarys=Library::query()->where('company_id',$companyId)->withCount('container') ->get(['id', 'name', 'created_at', 'updated_at', 'container_count as container_count']);
        $libraryCount=$librarys->count();
        $containerCount = $librarys->sum('container_count');

        $MyLibrarys=Library::query()->allowed()->filter($request->all())->orderBy('updated_at', 'desc')->get(['id', 'name', 'type','created_at', 'updated_at']);
        $MyContainers = Container::query()->allowed()->when($request->type && $request->asset,function ($query) use ($request){
            $query->whereHas('library', function ($query) use ($request) {
                $query->where('type', $request->type)
                ->where('asset_id',$request->asset);
            });
        })->orderBy('updated_at', 'desc')->get( ['id', 'name','library_id', 'created_at', 'updated_at', 'type']);

        return $this->success([
            'data' =>[
                'libraryCount'=>$libraryCount,
                'containerCount'=>$containerCount,
                'MyLibrarysCount'=>$MyLibrarys->count(),
                'MyContainersCount'=>$MyContainers->count(),
                'MyContainers'=>ContainerReportResource::collection($MyContainers),
                'MyLibrarys'=>LibraryReportResource::collection($MyLibrarys)
            ]
        ]);
    }
}